diff --git a/extensions/meteringAndBilling/routes/usage.js b/extensions/meteringAndBilling/routes/usage.js
index c78b029d..ebced8bd 100644
--- a/extensions/meteringAndBilling/routes/usage.js
+++ b/extensions/meteringAndBilling/routes/usage.js
@@ -1,24 +1,24 @@
-/** @type {import('@heyputer/backend/src/services/MeteringService/MeteringServiceWrapper.mjs').MeteringAndBillingServiceWrapper} */
-const meteringAndBillingServiceWrapper = extension.import('service:meteringService');
+/** @type {import('@heyputer/backend/src/services/MeteringService/MeteringServiceWrapper.mjs').MeteringServiceWrapper} */
+const meteringServiceWrapper = extension.import('service:meteringService');
// TODO DS: move this to its own router and just use under this path
-extension.get('/meteringAndBilling/usage', { subdomain: 'api' }, async (req, res) => {
- const meteringAndBillingService = meteringAndBillingServiceWrapper.meteringAndBillingService;
+extension.get('/metering/usage', { subdomain: 'api' }, async (req, res) => {
+ const meteringService = meteringServiceWrapper.meteringService;
const actor = req.actor;
if ( !actor ) {
throw Error('actor not found in context');
}
- const actorUsagePromise = meteringAndBillingService.getActorCurrentMonthUsageDetails(actor);
- const actorAllowanceInfoPromise = meteringAndBillingService.getAllowedUsage(actor);
+ const actorUsagePromise = meteringService.getActorCurrentMonthUsageDetails(actor);
+ const actorAllowanceInfoPromise = meteringService.getAllowedUsage(actor);
const [actorUsage, allowanceInfo] = await Promise.all([actorUsagePromise, actorAllowanceInfoPromise]);
res.status(200).json({ ...actorUsage, allowanceInfo });
return;
});
-extension.get('/meteringAndBilling/usage/:appId', { subdomain: 'api' }, async (req, res) => {
- const meteringAndBillingService = meteringAndBillingServiceWrapper.meteringAndBillingService;
+extension.get('/metering/usage/:appId', { subdomain: 'api' }, async (req, res) => {
+ const meteringService = meteringServiceWrapper.meteringService;
const actor = req.actor;
if ( !actor ) {
@@ -30,9 +30,9 @@ extension.get('/meteringAndBilling/usage/:appId', { subdomain: 'api' }, async (r
return;
}
- const appUsage = await meteringAndBillingService.getActorCurrentMonthAppUsageDetails(actor, appId);
+ const appUsage = await meteringService.getActorCurrentMonthAppUsageDetails(actor, appId);
res.status(200).json(appUsage);
return;
});
-console.debug('Loaded /meteringAndBilling/usage route');
\ No newline at end of file
+console.debug('Loaded /metering/usage route');
\ No newline at end of file
diff --git a/src/backend/src/CoreModule.js b/src/backend/src/CoreModule.js
index 76c6e961..39137057 100644
--- a/src/backend/src/CoreModule.js
+++ b/src/backend/src/CoreModule.js
@@ -17,14 +17,14 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
-const { AdvancedBase } = require("@heyputer/putility");
-const Library = require("./definitions/Library");
-const { NotificationES } = require("./om/entitystorage/NotificationES");
-const { ProtectedAppES } = require("./om/entitystorage/ProtectedAppES");
+const { AdvancedBase } = require('@heyputer/putility');
+const Library = require('./definitions/Library');
+const { NotificationES } = require('./om/entitystorage/NotificationES');
+const { ProtectedAppES } = require('./om/entitystorage/ProtectedAppES');
const { Context } = require('./util/context');
-const { LLOWrite } = require("./filesystem/ll_operations/ll_write");
-const { LLRead } = require("./filesystem/ll_operations/ll_read");
-const { RuntimeModule } = require("./extension/RuntimeModule.js");
+const { LLOWrite } = require('./filesystem/ll_operations/ll_write');
+const { LLRead } = require('./filesystem/ll_operations/ll_read');
+const { RuntimeModule } = require('./extension/RuntimeModule.js');
/**
* Core module for the Puter platform that includes essential services including
@@ -135,7 +135,7 @@ const install = async ({ context, services, app, useapi, modapi }) => {
const { NAPIThumbnailService } = require('./services/thumbnails/NAPIThumbnailService');
const { RateLimitService } = require('./services/sla/RateLimitService');
const { AuthService } = require('./services/auth/AuthService');
- const { PreAuthService } = require("./services/auth/PreAuthService");
+ const { PreAuthService } = require('./services/auth/PreAuthService');
const { SLAService } = require('./services/sla/SLAService');
const { PermissionService } = require('./services/auth/PermissionService');
const { ACLService } = require('./services/auth/ACLService');
@@ -167,7 +167,7 @@ const install = async ({ context, services, app, useapi, modapi }) => {
const FilesystemAPIService = require('./services/FilesystemAPIService');
const ServeGUIService = require('./services/ServeGUIService');
const PuterAPIService = require('./services/PuterAPIService');
- const { RefreshAssociationsService } = require("./services/RefreshAssociationsService");
+ const { RefreshAssociationsService } = require('./services/RefreshAssociationsService');
// Service names beginning with '__' aren't called by other services;
// these provide data/functionality to other services or produce
// side-effects from the events of other services.
@@ -215,7 +215,7 @@ const install = async ({ context, services, app, useapi, modapi }) => {
});
const { EntriService } = require('./services/EntriService.js');
- services.registerService("entri-service", EntriService);
+ services.registerService('entri-service', EntriService);
const { InformationService } = require('./services/information/InformationService');
services.registerService('information', InformationService);
@@ -305,7 +305,7 @@ const install = async ({ context, services, app, useapi, modapi }) => {
const { OTPService } = require('./services/auth/OTPService');
services.registerService('otp', OTPService);
- const { UserProtectedEndpointsService } = require("./services/web/UserProtectedEndpointsService");
+ const { UserProtectedEndpointsService } = require('./services/web/UserProtectedEndpointsService');
services.registerService('__user-protected-endpoints', UserProtectedEndpointsService);
const { AntiCSRFService } = require('./services/auth/AntiCSRFService');
@@ -326,7 +326,7 @@ const install = async ({ context, services, app, useapi, modapi }) => {
const { DevTODService } = require('./services/DevTODService');
services.registerService('__dev-tod', DevTODService);
- const { DriverService } = require("./services/drivers/DriverService");
+ const { DriverService } = require('./services/drivers/DriverService');
services.registerService('driver', DriverService);
const { ScriptService } = require('./services/ScriptService');
@@ -412,10 +412,10 @@ const install = async ({ context, services, app, useapi, modapi }) => {
services.registerService('__chat-api', ChatAPIService);
const { WorkerService } = require('./services/worker/WorkerService');
- services.registerService("worker-service", WorkerService);
+ services.registerService('worker-service', WorkerService);
- const { MeteringAndBillingServiceWrapper } = require("./services/MeteringService/MeteringServiceWrapper.mjs");
- services.registerService('meteringService', MeteringAndBillingServiceWrapper);
+ const { MeteringServiceWrapper } = require('./services/MeteringService/MeteringServiceWrapper.mjs');
+ services.registerService('meteringService', MeteringServiceWrapper);
const { PermissionShortcutService } = require('./services/auth/PermissionShortcutService');
services.registerService('permission-shortcut', PermissionShortcutService);
diff --git a/src/backend/src/filesystem/ll_operations/ll_read.js b/src/backend/src/filesystem/ll_operations/ll_read.js
index 47a86c54..a4069e23 100644
--- a/src/backend/src/filesystem/ll_operations/ll_read.js
+++ b/src/backend/src/filesystem/ll_operations/ll_read.js
@@ -94,8 +94,8 @@ class LLRead extends LLFilesystemOperation {
//define metering service
- /** @type {import("../../services/MeteringService/MeteringService").MeteringAndBillingService} */
- const meteringService = Context.get('services').get('meteringService').meteringAndBillingService;
+ /** @type {import("../../services/MeteringService/MeteringService").MeteringService} */
+ const meteringService = Context.get('services').get('meteringService').meteringService;
// check file cache
const maybe_buffer = await fileCacheService.try_get(fsNode); // TODO DS: do we need those cache hit logs?
if ( maybe_buffer ) {
diff --git a/src/backend/src/modules/puterai/AIChatService.js b/src/backend/src/modules/puterai/AIChatService.js
index 103aecf3..9edc00c8 100644
--- a/src/backend/src/modules/puterai/AIChatService.js
+++ b/src/backend/src/modules/puterai/AIChatService.js
@@ -18,17 +18,17 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const { PassThrough } = require("stream");
-const APIError = require("../../api/APIError");
-const config = require("../../config");
-const BaseService = require("../../services/BaseService");
-const { DB_WRITE } = require("../../services/database/consts");
-const { TypedValue } = require("../../services/drivers/meta/Runtime");
-const { Context } = require("../../util/context");
-const { AsModeration } = require("./lib/AsModeration");
-const FunctionCalling = require("./lib/FunctionCalling");
-const Messages = require("./lib/Messages");
-const Streaming = require("./lib/Streaming");
+const { PassThrough } = require('stream');
+const APIError = require('../../api/APIError');
+const config = require('../../config');
+const BaseService = require('../../services/BaseService');
+const { DB_WRITE } = require('../../services/database/consts');
+const { TypedValue } = require('../../services/drivers/meta/Runtime');
+const { Context } = require('../../util/context');
+const { AsModeration } = require('./lib/AsModeration');
+const FunctionCalling = require('./lib/FunctionCalling');
+const Messages = require('./lib/Messages');
+const Streaming = require('./lib/Streaming');
// Maximum number of fallback attempts when a model fails, including the first attempt
const MAX_FALLBACKS = 3 + 1; // includes first attempt
@@ -47,9 +47,9 @@ class AIChatService extends BaseService {
cuid2: require('@paralleldrive/cuid2').createId,
};
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- get meteringAndBillingService(){
- return this.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ get meteringService(){
+ return this.services.get('meteringService').meteringService;
}
/**
* Initializes the service by setting up core properties.
@@ -98,7 +98,7 @@ class AIChatService extends BaseService {
max_tokens_exceeded: {
status: 400,
message: ({ input_tokens, max_tokens }) =>
- `Input exceeds maximum token count. ` +
+ 'Input exceeds maximum token count. ' +
`Input has ${input_tokens} tokens, ` +
`but the maximum is ${max_tokens}.`,
},
@@ -360,7 +360,7 @@ class AIChatService extends BaseService {
if ( ! model_details ) {
// TODO (xiaochen): replace with a standard link
- const available_models_url = this.global_config.origin + "/puterai/chat/models";
+ const available_models_url = this.global_config.origin + '/puterai/chat/models';
throw APIError.create('field_invalid', null, {
key: 'model',
@@ -374,7 +374,7 @@ class AIChatService extends BaseService {
const model_max_tokens = model_details.max_tokens;
const text = Messages.extract_text(parameters.messages);
const approximate_input_cost = text.length / 4 * model_input_cost; // TODO DS: guesstimate tokens better,
- const usageAllowed = await this.meteringAndBillingService.hasEnoughCredits(actor, approximate_input_cost);
+ const usageAllowed = await this.meteringService.hasEnoughCredits(actor, approximate_input_cost);
// Handle usage limits reached case
if ( !usageAllowed ) {
@@ -386,7 +386,7 @@ class AIChatService extends BaseService {
}
// available is no longer defined, so use meteringService to get available credits
- const availableCredits = await this.meteringAndBillingService.getRemainingUsage(actor);
+ const availableCredits = await this.meteringService.getRemainingUsage(actor);
const max_allowed_output_amount =
availableCredits - approximate_input_cost;
@@ -482,7 +482,7 @@ class AIChatService extends BaseService {
// Check usage for fallback model too (with updated method)
const actor = Context.get('actor');
- const fallbackUsageAllowed = await this.meteringAndBillingService.hasEnoughCredits(actor, 1);
+ const fallbackUsageAllowed = await this.meteringService.hasEnoughCredits(actor, 1);
// If usage not allowed for fallback, use usage-limited-chat instead
if ( !fallbackUsageAllowed ) {
diff --git a/src/backend/src/modules/puterai/AWSPollyService.js b/src/backend/src/modules/puterai/AWSPollyService.js
index 56e5c899..bf3d41a1 100644
--- a/src/backend/src/modules/puterai/AWSPollyService.js
+++ b/src/backend/src/modules/puterai/AWSPollyService.js
@@ -18,11 +18,11 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const { PollyClient, SynthesizeSpeechCommand, DescribeVoicesCommand } = require("@aws-sdk/client-polly");
-const BaseService = require("../../services/BaseService");
-const { TypedValue } = require("../../services/drivers/meta/Runtime");
-const APIError = require("../../api/APIError");
-const { Context } = require("../../util/context");
+const { PollyClient, SynthesizeSpeechCommand, DescribeVoicesCommand } = require('@aws-sdk/client-polly');
+const BaseService = require('../../services/BaseService');
+const { TypedValue } = require('../../services/drivers/meta/Runtime');
+const APIError = require('../../api/APIError');
+const { Context } = require('../../util/context');
// Polly price calculation per engine
const ENGINE_PRICING = {
@@ -45,9 +45,9 @@ const VALID_ENGINES = ['standard', 'neural', 'long-form', 'generative'];
*/
class AWSPollyService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- get meteringAndBillingService() {
- return this.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ get meteringService() {
+ return this.services.get('meteringService').meteringService;
}
static MODULES = {
@@ -134,7 +134,7 @@ class AWSPollyService extends BaseService {
const usageType = `aws-polly:${engine}:character`;
- const usageAllowed = await this.meteringAndBillingService.hasEnoughCreditsFor(actor, usageType, text.length);
+ const usageAllowed = await this.meteringService.hasEnoughCreditsFor(actor, usageType, text.length);
if ( ! usageAllowed ) {
throw APIError.create('insufficient_funds');
@@ -149,7 +149,7 @@ class AWSPollyService extends BaseService {
});
// AWS Polly TTS metering: track character count, voice, engine, cost, audio duration if available
- this.meteringAndBillingService.incrementUsage(actor, usageType, text.length);
+ this.meteringService.incrementUsage(actor, usageType, text.length);
const speech = new TypedValue({
$: 'stream',
diff --git a/src/backend/src/modules/puterai/AWSTextractService.js b/src/backend/src/modules/puterai/AWSTextractService.js
index 74672a4a..ddfc32a6 100644
--- a/src/backend/src/modules/puterai/AWSTextractService.js
+++ b/src/backend/src/modules/puterai/AWSTextractService.js
@@ -18,11 +18,11 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const { TextractClient, AnalyzeDocumentCommand, InvalidS3ObjectException } = require("@aws-sdk/client-textract");
+const { TextractClient, AnalyzeDocumentCommand, InvalidS3ObjectException } = require('@aws-sdk/client-textract');
-const BaseService = require("../../services/BaseService");
-const APIError = require("../../api/APIError");
-const { Context } = require("../../util/context");
+const BaseService = require('../../services/BaseService');
+const APIError = require('../../api/APIError');
+const { Context } = require('../../util/context');
/**
* AWSTextractService class - Provides OCR (Optical Character Recognition) functionality using AWS Textract
@@ -31,9 +31,9 @@ const { Context } = require("../../util/context");
* Handles both S3-stored and buffer-based document processing with automatic region management.
*/
class AWSTextractService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- get meteringAndBillingService(){
- return this.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ get meteringService(){
+ return this.services.get('meteringService').meteringService;
}
/**
* AWS Textract service for OCR functionality
@@ -146,9 +146,9 @@ class AWSTextractService extends BaseService {
} = await this._get_client_and_document(file_facade);
const actor = Context.get('actor');
- const usageType = "aws-textract:detect-document-text:page";
+ const usageType = 'aws-textract:detect-document-text:page';
- const usageAllowed = await this.meteringAndBillingService.hasEnoughCreditsFor(actor, usageType, 1); // allow them to pass if they have enough for 1 page atleast
+ const usageAllowed = await this.meteringService.hasEnoughCreditsFor(actor, usageType, 1); // allow them to pass if they have enough for 1 page atleast
if ( ! usageAllowed ) {
throw APIError.create('insufficient_funds');
@@ -191,7 +191,7 @@ class AWSTextractService extends BaseService {
if ( block.BlockType === 'PAGE' ) pageCount += 1;
}
}
- this.meteringAndBillingService.incrementUsage(actor, usageType, pageCount || 1);
+ this.meteringService.incrementUsage(actor, usageType, pageCount || 1);
return textractResp;
}
diff --git a/src/backend/src/modules/puterai/ClaudeService.js b/src/backend/src/modules/puterai/ClaudeService.js
index 8221ffac..c8b83f52 100644
--- a/src/backend/src/modules/puterai/ClaudeService.js
+++ b/src/backend/src/modules/puterai/ClaudeService.js
@@ -18,13 +18,13 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const { default: Anthropic, toFile } = require("@anthropic-ai/sdk");
-const BaseService = require("../../services/BaseService");
-const FunctionCalling = require("./lib/FunctionCalling");
-const Messages = require("./lib/Messages");
-const FSNodeParam = require("../../api/filesystem/FSNodeParam");
-const { LLRead } = require("../../filesystem/ll_operations/ll_read");
-const { Context } = require("../../util/context");
+const { default: Anthropic, toFile } = require('@anthropic-ai/sdk');
+const BaseService = require('../../services/BaseService');
+const FunctionCalling = require('./lib/FunctionCalling');
+const Messages = require('./lib/Messages');
+const FSNodeParam = require('../../api/filesystem/FSNodeParam');
+const { LLRead } = require('../../filesystem/ll_operations/ll_read');
+const { Context } = require('../../util/context');
/**
* ClaudeService class extends BaseService to provide integration with Anthropic's Claude AI models.
@@ -50,8 +50,8 @@ class ClaudeService extends BaseService {
* @returns {Promise}
*/
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- #meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ #meteringService;
async _init() {
this.anthropic = new Anthropic({
@@ -68,7 +68,7 @@ class ClaudeService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.#meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService; // TODO DS: move to proper extensions
+ this.#meteringService = this.services.get('meteringService').meteringService; // TODO DS: move to proper extensions
}
/**
@@ -341,7 +341,7 @@ class ClaudeService extends BaseService {
// TODO DS: get this inside the class as a private method once the methods aren't exported directly
billForUsage(actor, model, usage) {
- this.#meteringAndBillingService.utilRecordUsageObject(usage, actor, `claude:${this.models_().find(m => [m.id, ...(m.aliases || [])].includes(model)).id}`);
+ this.#meteringService.utilRecordUsageObject(usage, actor, `claude:${this.models_().find(m => [m.id, ...(m.aliases || [])].includes(model)).id}`);
};
/**
diff --git a/src/backend/src/modules/puterai/DeepSeekService.js b/src/backend/src/modules/puterai/DeepSeekService.js
index cb0af051..4915b8e2 100644
--- a/src/backend/src/modules/puterai/DeepSeekService.js
+++ b/src/backend/src/modules/puterai/DeepSeekService.js
@@ -18,9 +18,9 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const BaseService = require("../../services/BaseService");
-const { Context } = require("../../util/context");
-const OpenAIUtil = require("./lib/OpenAIUtil");
+const BaseService = require('../../services/BaseService');
+const { Context } = require('../../util/context');
+const OpenAIUtil = require('./lib/OpenAIUtil');
const dedent = require('dedent');
/**
@@ -36,9 +36,9 @@ class DeepSeekService extends BaseService {
};
/**
- * @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService}
+ * @type {import('../../services/MeteringService/MeteringService').MeteringService}
*/
- meteringAndBillingService;
+ meteringService;
/**
* Gets the system prompt used for AI interactions
* @returns {string} The base system prompt that identifies the AI as running on Puter
@@ -63,7 +63,7 @@ class DeepSeekService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService;
+ this.meteringService = this.services.get('meteringService').meteringService;
}
/**
@@ -114,7 +114,7 @@ class DeepSeekService extends BaseService {
for ( const message of messages ) {
// DeepSeek doesn't appreciate arrays here
if ( message.tool_calls && Array.isArray(message.content) ) {
- message.content = "";
+ message.content = '';
}
}
@@ -167,7 +167,7 @@ class DeepSeekService extends BaseService {
return OpenAIUtil.handle_completion_output({
usage_calculator: ({ usage }) => {
const trackedUsage = OpenAIUtil.extractMeteredUsage(usage);
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, `deepseek:${modelDetails.id}`);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, `deepseek:${modelDetails.id}`);
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
});
diff --git a/src/backend/src/modules/puterai/GeminiImageGenerationService.js b/src/backend/src/modules/puterai/GeminiImageGenerationService.js
index 22b822fb..a4d55d4b 100644
--- a/src/backend/src/modules/puterai/GeminiImageGenerationService.js
+++ b/src/backend/src/modules/puterai/GeminiImageGenerationService.js
@@ -18,10 +18,10 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const APIError = require("../../api/APIError");
-const BaseService = require("../../services/BaseService");
-const { TypedValue } = require("../../services/drivers/meta/Runtime");
-const { Context } = require("../../util/context");
+const APIError = require('../../api/APIError');
+const BaseService = require('../../services/BaseService');
+const { TypedValue } = require('../../services/drivers/meta/Runtime');
+const { Context } = require('../../util/context');
const { GoogleGenAI } = require('@google/genai');
/**
@@ -30,9 +30,9 @@ const { GoogleGenAI } = require('@google/genai');
* the puter-image-generation interface.
*/
class GeminiImageGenerationService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- get meteringAndBillingService(){
- return this.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ get meteringService(){
+ return this.services.get('meteringService').meteringService;
}
static MODULES = {
};
@@ -40,7 +40,7 @@ class GeminiImageGenerationService extends BaseService {
_construct() {
this.models_ = {
'gemini-2.5-flash-image-preview': {
- "1024x1024": 0.039,
+ '1024x1024': 0.039,
},
};
}
@@ -167,7 +167,7 @@ class GeminiImageGenerationService extends BaseService {
const usageType = `gemini:${model}:${price_key}`;
- const usageAllowed = await this.meteringAndBillingService.hasEnoughCreditsFor(actor, usageType, 1);
+ const usageAllowed = await this.meteringService.hasEnoughCreditsFor(actor, usageType, 1);
if ( !usageAllowed ) {
throw APIError.create('insufficient_funds');
@@ -192,19 +192,19 @@ class GeminiImageGenerationService extends BaseService {
}
const response = await this.genAI.models.generateContent({
- model: "gemini-2.5-flash-image-preview",
+ model: 'gemini-2.5-flash-image-preview',
contents: contents,
});
// Metering usage tracking
// Gemini usage: always 1 image, resolution, cost, model
- this.meteringAndBillingService.incrementUsage(actor, usageType, 1);
+ this.meteringService.incrementUsage(actor, usageType, 1);
let url = undefined;
for ( const part of response.candidates[0].content.parts ) {
if ( part.text ) {
// do nothing here
} else if ( part.inlineData ) {
const imageData = part.inlineData.data;
- url = "data:image/png;base64," + imageData;
+ url = 'data:image/png;base64,' + imageData;
}
}
diff --git a/src/backend/src/modules/puterai/GeminiService.js b/src/backend/src/modules/puterai/GeminiService.js
index e69a841f..c76fe5f7 100644
--- a/src/backend/src/modules/puterai/GeminiService.js
+++ b/src/backend/src/modules/puterai/GeminiService.js
@@ -1,14 +1,14 @@
-const BaseService = require("../../services/BaseService");
+const BaseService = require('../../services/BaseService');
const { GoogleGenerativeAI } = require('@google/generative-ai');
-const GeminiSquareHole = require("./lib/GeminiSquareHole");
-const FunctionCalling = require("./lib/FunctionCalling");
-const { Context } = require("../../util/context");
+const GeminiSquareHole = require('./lib/GeminiSquareHole');
+const FunctionCalling = require('./lib/FunctionCalling');
+const { Context } = require('../../util/context');
class GeminiService extends BaseService {
/**
- * @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService}
+ * @type {import('../../services/MeteringService/MeteringService').MeteringService}
*/
- meteringAndBillingService = undefined;
+ meteringService = undefined;
async _init() {
const svc_aiChat = this.services.get('ai-chat');
@@ -16,7 +16,7 @@ class GeminiService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService;
+ this.meteringService = this.services.get('meteringService').meteringService;
}
static IMPLEMENTS = {
@@ -85,7 +85,7 @@ class GeminiService extends BaseService {
completion_tokens: usageMetadata.candidatesTokenCount,
cached_tokens: usageMetadata.cachedContentTokenCount || 0,
};
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, meteringPrefix);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, meteringPrefix);
},
}),
};
@@ -104,7 +104,7 @@ class GeminiService extends BaseService {
completion_tokens: genResult.response.usageMetadata.candidatesTokenCount,
cached_tokens: genResult.response.usageMetadata.cachedContentTokenCount || 0,
};
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, meteringPrefix);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, meteringPrefix);
return result;
}
},
diff --git a/src/backend/src/modules/puterai/GroqAIService.js b/src/backend/src/modules/puterai/GroqAIService.js
index 96d7667f..7d900a49 100644
--- a/src/backend/src/modules/puterai/GroqAIService.js
+++ b/src/backend/src/modules/puterai/GroqAIService.js
@@ -18,11 +18,11 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const BaseService = require("../../services/BaseService");
-const { Context } = require("../../util/context");
-const OpenAIUtil = require("./lib/OpenAIUtil");
+const BaseService = require('../../services/BaseService');
+const { Context } = require('../../util/context');
+const OpenAIUtil = require('./lib/OpenAIUtil');
-/** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
+/** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
/**
* Service class for integrating with Groq AI's language models.
@@ -34,8 +34,8 @@ const OpenAIUtil = require("./lib/OpenAIUtil");
* @extends BaseService
*/
class GroqAIService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ meteringService;
static MODULES = {
Groq: require('groq-sdk'),
};
@@ -56,7 +56,7 @@ class GroqAIService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService; // TODO DS: move to proper extensions
+ this.meteringService = this.services.get('meteringService').meteringService; // TODO DS: move to proper extensions
}
/**
@@ -104,7 +104,7 @@ class GroqAIService extends BaseService {
for ( const message of messages ) {
// Curiously, DeepSeek has the exact same deviation
if ( message.tool_calls && Array.isArray(message.content) ) {
- message.content = "";
+ message.content = '';
}
}
@@ -128,7 +128,7 @@ class GroqAIService extends BaseService {
},
usage_calculator: ({ usage }) => {
const trackedUsage = OpenAIUtil.extractMeteredUsage(usage);
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, `groq:${modelDetails.id}`);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, `groq:${modelDetails.id}`);
// Still return legacy cost calculation for compatibility
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
@@ -201,38 +201,38 @@ class GroqAIService extends BaseService {
},
},
{
- "id": "llama-3.1-70b-versatile",
- "name": "Llama 3.1 70B Versatile 128k",
- "context": 128000,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 59,
- "output": 79,
+ 'id': 'llama-3.1-70b-versatile',
+ 'name': 'Llama 3.1 70B Versatile 128k',
+ 'context': 128000,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 59,
+ 'output': 79,
},
},
{
// This was only available on their Discord, not
// on the pricing page.
- "id": "llama-3.1-70b-specdec",
- "name": "Llama 3.1 8B Instant 128k",
- "context": 128000,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 59,
- "output": 99,
+ 'id': 'llama-3.1-70b-specdec',
+ 'name': 'Llama 3.1 8B Instant 128k',
+ 'context': 128000,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 59,
+ 'output': 99,
},
},
{
- "id": "llama-3.1-8b-instant",
- "name": "Llama 3.1 8B Instant 128k",
- "context": 131072,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 5,
- "output": 8,
+ 'id': 'llama-3.1-8b-instant',
+ 'name': 'Llama 3.1 8B Instant 128k',
+ 'context': 131072,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 5,
+ 'output': 8,
},
max_tokens: 131072,
},
@@ -261,25 +261,25 @@ class GroqAIService extends BaseService {
max_tokens: 512,
},
{
- "id": "llama-3.2-1b-preview",
- "name": "Llama 3.2 1B (Preview) 8k",
- "context": 128000,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 4,
- "output": 4,
+ 'id': 'llama-3.2-1b-preview',
+ 'name': 'Llama 3.2 1B (Preview) 8k',
+ 'context': 128000,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 4,
+ 'output': 4,
},
},
{
- "id": "llama-3.2-3b-preview",
- "name": "Llama 3.2 3B (Preview) 8k",
- "context": 128000,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 6,
- "output": 6,
+ 'id': 'llama-3.2-3b-preview',
+ 'name': 'Llama 3.2 3B (Preview) 8k',
+ 'context': 128000,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 6,
+ 'output': 6,
},
},
{
@@ -303,47 +303,47 @@ class GroqAIService extends BaseService {
},
},
{
- "id": "llama3-70b-8192",
- "name": "Llama 3 70B 8k",
- "context": 8192,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 59,
- "output": 79,
+ 'id': 'llama3-70b-8192',
+ 'name': 'Llama 3 70B 8k',
+ 'context': 8192,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 59,
+ 'output': 79,
},
},
{
- "id": "llama3-8b-8192",
- "name": "Llama 3 8B 8k",
- "context": 8192,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 5,
- "output": 8,
+ 'id': 'llama3-8b-8192',
+ 'name': 'Llama 3 8B 8k',
+ 'context': 8192,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 5,
+ 'output': 8,
},
},
{
- "id": "mixtral-8x7b-32768",
- "name": "Mixtral 8x7B Instruct 32k",
- "context": 32768,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 24,
- "output": 24,
+ 'id': 'mixtral-8x7b-32768',
+ 'name': 'Mixtral 8x7B Instruct 32k',
+ 'context': 32768,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 24,
+ 'output': 24,
},
},
{
- "id": "llama-guard-3-8b",
- "name": "Llama Guard 3 8B 8k",
- "context": 8192,
- "cost": {
- "currency": "usd-cents",
- "tokens": 1000000,
- "input": 20,
- "output": 20,
+ 'id': 'llama-guard-3-8b',
+ 'name': 'Llama Guard 3 8B 8k',
+ 'context': 8192,
+ 'cost': {
+ 'currency': 'usd-cents',
+ 'tokens': 1000000,
+ 'input': 20,
+ 'output': 20,
},
},
];
diff --git a/src/backend/src/modules/puterai/MistralAIService.js b/src/backend/src/modules/puterai/MistralAIService.js
index 3312bb0e..1a7e81f0 100644
--- a/src/backend/src/modules/puterai/MistralAIService.js
+++ b/src/backend/src/modules/puterai/MistralAIService.js
@@ -18,10 +18,10 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const BaseService = require("../../services/BaseService");
+const BaseService = require('../../services/BaseService');
const axios = require('axios');
-const OpenAIUtil = require("./lib/OpenAIUtil");
-const { Context } = require("../../util/context");
+const OpenAIUtil = require('./lib/OpenAIUtil');
+const { Context } = require('../../util/context');
/**
* MistralAIService class extends BaseService to provide integration with the Mistral AI API.
@@ -31,8 +31,8 @@ const { Context } = require("../../util/context");
* for different models and implements the puter-chat-completion interface.
*/
class MistralAIService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ meteringService;
static MODULES = {
'@mistralai/mistralai': require('@mistralai/mistralai'),
};
@@ -250,7 +250,7 @@ class MistralAIService extends BaseService {
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService;
+ this.meteringService = this.services.get('meteringService').meteringService;
// TODO: make this event-driven so it doesn't hold up boot
await this.populate_models_();
@@ -371,7 +371,7 @@ class MistralAIService extends BaseService {
const snake_usage = {};
for ( const key in chunk.usage ) {
- const snakeKey = key.replace(/([A-Z])/g, "_$1").toLowerCase();
+ const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
snake_usage[snakeKey] = chunk.usage[key];
}
@@ -388,9 +388,7 @@ class MistralAIService extends BaseService {
stream,
usage_calculator: ({ usage }) => {
const trackedUsage = OpenAIUtil.extractMeteredUsage(usage);
- if ( this.meteringAndBillingService ) {
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, `mistral:${modelDetails.id}`);
- }
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, `mistral:${modelDetails.id}`);
// Still return legacy cost calculation for compatibility
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
diff --git a/src/backend/src/modules/puterai/OpenAIImageGenerationService.js b/src/backend/src/modules/puterai/OpenAIImageGenerationService.js
index 17deb55c..1a28c16f 100644
--- a/src/backend/src/modules/puterai/OpenAIImageGenerationService.js
+++ b/src/backend/src/modules/puterai/OpenAIImageGenerationService.js
@@ -18,10 +18,10 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const APIError = require("../../api/APIError");
-const BaseService = require("../../services/BaseService");
-const { TypedValue } = require("../../services/drivers/meta/Runtime");
-const { Context } = require("../../util/context");
+const APIError = require('../../api/APIError');
+const BaseService = require('../../services/BaseService');
+const { TypedValue } = require('../../services/drivers/meta/Runtime');
+const { Context } = require('../../util/context');
/**
* Service class for generating images using OpenAI's DALL-E API.
@@ -31,9 +31,9 @@ const { Context } = require("../../util/context");
* validation, and spending tracking.
*/
class OpenAIImageGenerationService extends BaseService {
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- get meteringAndBillingService(){
- return this.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ get meteringService(){
+ return this.services.get('meteringService').meteringService;
}
static MODULES = {
@@ -43,15 +43,15 @@ class OpenAIImageGenerationService extends BaseService {
_construct() {
this.models_ = {
'gpt-image-1': {
- "low:1024x1024": 0.011,
- "low:1024x1536": 0.016,
- "low:1536x1024": 0.016,
- "medium:1024x1024": 0.042,
- "medium:1024x1536": 0.063,
- "medium:1536x1024": 0.063,
- "high:1024x1024": 0.167,
- "high:1024x1536": 0.25,
- "high:1536x1024": 0.25,
+ 'low:1024x1024': 0.011,
+ 'low:1024x1536': 0.016,
+ 'low:1536x1024': 0.016,
+ 'medium:1024x1024': 0.042,
+ 'medium:1024x1536': 0.063,
+ 'medium:1536x1024': 0.063,
+ 'high:1024x1024': 0.167,
+ 'high:1024x1536': 0.25,
+ 'high:1536x1024': 0.25,
},
'dall-e-3': {
'1024x1024': 0.04,
@@ -193,7 +193,7 @@ class OpenAIImageGenerationService extends BaseService {
}
const usageType = `openai:${model}:${price_key}`;
- const usageAllowed = await this.meteringAndBillingService.hasEnoughCreditsFor(actor, usageType, 1);
+ const usageAllowed = await this.meteringService.hasEnoughCreditsFor(actor, usageType, 1);
if ( ! usageAllowed ) {
throw APIError.create('insufficient_funds');
@@ -210,7 +210,7 @@ class OpenAIImageGenerationService extends BaseService {
const result = await this.openai.images.generate(apiParams);
// For image generation, usage is typically image count and resolution
- this.meteringAndBillingService.incrementUsage(actor, usageType, 1);
+ this.meteringService.incrementUsage(actor, usageType, 1);
const spending_meta = {
model,
@@ -218,10 +218,10 @@ class OpenAIImageGenerationService extends BaseService {
};
if ( quality ) {
- spending_meta.size = quality + ":" + spending_meta.size;
+ spending_meta.size = quality + ':' + spending_meta.size;
}
- const url = result.data?.[0]?.url || (result.data?.[0]?.b64_json ? "data:image/png;base64," + result.data[0].b64_json : null);
+ const url = result.data?.[0]?.url || (result.data?.[0]?.b64_json ? 'data:image/png;base64,' + result.data[0].b64_json : null);
if ( !url ) {
throw new Error('Failed to extract image URL from OpenAI response');
diff --git a/src/backend/src/modules/puterai/OpenAiCompletionService/OpenAICompletionService.mjs b/src/backend/src/modules/puterai/OpenAiCompletionService/OpenAICompletionService.mjs
index 83ea7d4d..2f93ca90 100644
--- a/src/backend/src/modules/puterai/OpenAiCompletionService/OpenAICompletionService.mjs
+++ b/src/backend/src/modules/puterai/OpenAiCompletionService/OpenAICompletionService.mjs
@@ -48,13 +48,13 @@ export class OpenAICompletionService {
#models;
- /** @type {import('../../../services/MeteringService/MeteringService.js').MeteringAndBillingService} */
- #meteringAndBillingService;
+ /** @type {import('../../../services/MeteringService/MeteringService.js').MeteringService} */
+ #meteringService;
- constructor({ serviceName, config, globalConfig, aiChatService, meteringAndBillingService, models = OPEN_AI_MODELS, defaultModel = 'gpt-4.1-nano' }) {
+ constructor({ serviceName, config, globalConfig, aiChatService, meteringService, models = OPEN_AI_MODELS, defaultModel = 'gpt-4.1-nano' }) {
this.#models = models;
this.#defaultModel = defaultModel;
- this.#meteringAndBillingService = meteringAndBillingService;
+ this.#meteringService = meteringService;
let apiKey =
config?.services?.openai?.apiKey ??
globalConfig?.services?.openai?.apiKey;
@@ -208,7 +208,7 @@ export class OpenAICompletionService {
delete task.contentPart.puter_path;
task.contentPart.type = 'text';
task.contentPart.text = `{error: input file exceeded maximum of ${MAX_FILE_SIZE} bytes; ` +
- `the user did not write this message}`; // "poor man's system prompt"
+ 'the user did not write this message}'; // "poor man's system prompt"
return; // "continue"
}
@@ -236,8 +236,8 @@ export class OpenAICompletionService {
};
} else {
task.contentPart.type = 'text';
- task.contentPart.text = `{error: input file has unsupported MIME type; ` +
- `the user did not write this message}`; // "poor man's system prompt"
+ task.contentPart.text = '{error: input file has unsupported MIME type; ' +
+ 'the user did not write this message}'; // "poor man's system prompt"
}
})());
}
@@ -271,7 +271,7 @@ export class OpenAICompletionService {
cached_tokens: usage.prompt_tokens_details?.cached_tokens ?? 0,
};
- this.#meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, `openai:${modelDetails.id}`);
+ this.#meteringService.utilRecordUsageObject(trackedUsage, actor, `openai:${modelDetails.id}`);
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
});
diff --git a/src/backend/src/modules/puterai/OpenAiCompletionService/index.mjs b/src/backend/src/modules/puterai/OpenAiCompletionService/index.mjs
index 0452a102..73ab2dc9 100644
--- a/src/backend/src/modules/puterai/OpenAiCompletionService/index.mjs
+++ b/src/backend/src/modules/puterai/OpenAiCompletionService/index.mjs
@@ -31,8 +31,8 @@ export class OpenAICompletionServiceWrapper extends BaseService {
serviceName: this.service_name,
config: this.config,
globalConfig: this.global_config,
- aiChatService: this.services.get("ai-chat"),
- meteringAndBillingService: this.services.get('meteringService').meteringAndBillingService,
+ aiChatService: this.services.get('ai-chat'),
+ meteringService: this.services.get('meteringService').meteringService,
});
}
diff --git a/src/backend/src/modules/puterai/OpenRouterService.js b/src/backend/src/modules/puterai/OpenRouterService.js
index 994da65f..150a8ee7 100644
--- a/src/backend/src/modules/puterai/OpenRouterService.js
+++ b/src/backend/src/modules/puterai/OpenRouterService.js
@@ -18,10 +18,10 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const APIError = require("../../api/APIError");
-const BaseService = require("../../services/BaseService");
-const OpenAIUtil = require("./lib/OpenAIUtil");
-const { Context } = require("../../util/context");
+const APIError = require('../../api/APIError');
+const BaseService = require('../../services/BaseService');
+const OpenAIUtil = require('./lib/OpenAIUtil');
+const { Context } = require('../../util/context');
/**
* XAIService class - Provides integration with X.AI's API for chat completions
@@ -46,8 +46,8 @@ class OpenRouterService extends BaseService {
return model;
}
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ meteringService;
/**
* Initializes the XAI service by setting up the OpenAI client and registering with the AI chat provider
@@ -67,7 +67,7 @@ class OpenRouterService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService; // TODO DS: move to proper extensions
+ this.meteringService = this.services.get('meteringService').meteringService; // TODO DS: move to proper extensions
}
/**
@@ -152,7 +152,7 @@ class OpenRouterService extends BaseService {
const costOverwrites = Object.fromEntries(Object.keys(trackedUsage).map((k) => {
return [k, rawPriceModelDetails.cost[k] * trackedUsage[k]];
}));
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, modelDetails.id, costOverwrites);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, modelDetails.id, costOverwrites);
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
});
diff --git a/src/backend/src/modules/puterai/TogetherAIService.js b/src/backend/src/modules/puterai/TogetherAIService.js
index ab013648..b5853471 100644
--- a/src/backend/src/modules/puterai/TogetherAIService.js
+++ b/src/backend/src/modules/puterai/TogetherAIService.js
@@ -18,13 +18,13 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const { PassThrough } = require("stream");
-const BaseService = require("../../services/BaseService");
-const { TypedValue } = require("../../services/drivers/meta/Runtime");
-const { nou } = require("../../util/langutil");
+const { PassThrough } = require('stream');
+const BaseService = require('../../services/BaseService');
+const { TypedValue } = require('../../services/drivers/meta/Runtime');
+const { nou } = require('../../util/langutil');
const { Together } = require('together-ai');
-const OpenAIUtil = require("./lib/OpenAIUtil");
-const { Context } = require("../../util/context");
+const OpenAIUtil = require('./lib/OpenAIUtil');
+const { Context } = require('../../util/context');
/**
* TogetherAIService class provides integration with Together AI's language models.
@@ -35,9 +35,9 @@ const { Context } = require("../../util/context");
*/
class TogetherAIService extends BaseService {
/**
- * @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService}
+ * @type {import('../../services/MeteringService/MeteringService').MeteringService}
*/
- meteringAndBillingService;
+ meteringService;
static MODULES = {
kv: globalThis.kv,
uuidv4: require('uuid').v4,
@@ -60,7 +60,7 @@ class TogetherAIService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService;
+ this.meteringService = this.services.get('meteringService').meteringService;
}
/**
@@ -133,7 +133,7 @@ class TogetherAIService extends BaseService {
prompt_tokens: trackedUsage.prompt_tokens * (modelDetails?.cost?.input ?? 0),
completion_tokens: trackedUsage.completion_tokens * (modelDetails?.cost?.output ?? 0),
};
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, modelId, costOverrides);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, modelId, costOverrides);
}
if ( chunk.choices.length < 1 ) continue;
@@ -163,7 +163,7 @@ class TogetherAIService extends BaseService {
output_tokens: completion.usage.completion_tokens,
};
// Metering: record usage for non-streamed completion
- this.meteringAndBillingService.utilRecordUsageObject(completion.usage, actor, modelId);
+ this.meteringService.utilRecordUsageObject(completion.usage, actor, modelId);
return ret;
},
},
diff --git a/src/backend/src/modules/puterai/XAIService.js b/src/backend/src/modules/puterai/XAIService.js
index 3599a6ca..5e704d03 100644
--- a/src/backend/src/modules/puterai/XAIService.js
+++ b/src/backend/src/modules/puterai/XAIService.js
@@ -18,9 +18,9 @@
*/
// METADATA // {"ai-commented":{"service":"claude"}}
-const BaseService = require("../../services/BaseService");
-const { Context } = require("../../util/context");
-const OpenAIUtil = require("./lib/OpenAIUtil");
+const BaseService = require('../../services/BaseService');
+const { Context } = require('../../util/context');
+const OpenAIUtil = require('./lib/OpenAIUtil');
/**
* XAIService class - Provides integration with X.AI's API for chat completions
@@ -33,8 +33,8 @@ class XAIService extends BaseService {
static MODULES = {
openai: require('openai'),
};
- /** @type {import('../../services/MeteringService/MeteringService').MeteringAndBillingService} */
- meteringAndBillingService;
+ /** @type {import('../../services/MeteringService/MeteringService').MeteringService} */
+ meteringService;
adapt_model(model) {
return model;
@@ -48,7 +48,7 @@ class XAIService extends BaseService {
async _init() {
this.openai = new this.modules.openai.OpenAI({
apiKey: this.global_config.services.xai.apiKey,
- baseURL: "https://api.x.ai/v1",
+ baseURL: 'https://api.x.ai/v1',
});
const svc_aiChat = this.services.get('ai-chat');
@@ -56,7 +56,7 @@ class XAIService extends BaseService {
service_name: this.service_name,
alias: true,
});
- this.meteringAndBillingService = this.services.get('meteringService').meteringAndBillingService; // TODO DS: move to proper extensions
+ this.meteringService = this.services.get('meteringService').meteringService; // TODO DS: move to proper extensions
}
/**
@@ -128,7 +128,7 @@ class XAIService extends BaseService {
cached_tokens: usage.prompt_tokens_details?.cached_tokens ?? 0,
};
- this.meteringAndBillingService.utilRecordUsageObject(trackedUsage, actor, `openai:${modelDetails.id}`);
+ this.meteringService.utilRecordUsageObject(trackedUsage, actor, `openai:${modelDetails.id}`);
const legacyCostCalculator = OpenAIUtil.create_usage_calculator({
model_details: modelDetails,
});
diff --git a/src/backend/src/modules/puterfs/lib/PuterFSProvider.js b/src/backend/src/modules/puterfs/lib/PuterFSProvider.js
index afaf9365..2e3f7c55 100644
--- a/src/backend/src/modules/puterfs/lib/PuterFSProvider.js
+++ b/src/backend/src/modules/puterfs/lib/PuterFSProvider.js
@@ -50,9 +50,9 @@ class PuterFSProvider extends putility.AdvancedBase {
return Context.get('services');
}
- /** @type {import('../../../services/MeteringService/MeteringService.js').MeteringAndBillingService} */
+ /** @type {import('../../../services/MeteringService/MeteringService.js').MeteringService} */
get #meteringService() {
- return this.#services.get('meteringService').meteringAndBillingService;
+ return this.#services.get('meteringService').meteringService;
}
constructor(...a) {
diff --git a/src/backend/src/routers/file.js b/src/backend/src/routers/file.js
index 20e7cf3c..6f19c792 100644
--- a/src/backend/src/routers/file.js
+++ b/src/backend/src/routers/file.js
@@ -30,8 +30,8 @@ const { Actor } = require('../services/auth/Actor');
// -----------------------------------------------------------------------//
router.get('/file', async (req, res, next) => {
// services and "services"
- /** @type {import('../services/MeteringService/MeteringService').MeteringAndBillingService} */
- const meteringService = req.services.get('meteringService').meteringAndBillingService;
+ /** @type {import('../services/MeteringService/MeteringService').MeteringService} */
+ const meteringService = req.services.get('meteringService').meteringService;
const log = req.services.get('log-service').create('/file');
const errors = req.services.get('error-service').create(log);
const db = req.services.get('database').get(DB_WRITE, 'filesystem');
diff --git a/src/backend/src/services/MeteringService/MeteringService.ts b/src/backend/src/services/MeteringService/MeteringService.ts
index fd6095fa..336ab0e5 100644
--- a/src/backend/src/services/MeteringService/MeteringService.ts
+++ b/src/backend/src/services/MeteringService/MeteringService.ts
@@ -7,17 +7,17 @@ import type { SUService } from '../SUService.js';
import { DEFAULT_FREE_SUBSCRIPTION, DEFAULT_TEMP_SUBSCRIPTION, GLOBAL_APP_KEY, METRICS_PREFIX, PERIOD_ESCAPE, POLICY_PREFIX } from './consts.js';
import { COST_MAPS } from './costMaps/index.js';
import { SUB_POLICIES } from './subPolicies/index.js';
-import { MeteringAndBillingServiceDeps, UsageAddons, UsageByType } from './types.js';
+import { MeteringServiceDeps, UsageAddons, UsageByType } from './types.js';
/**
* Handles usage metering and supports stubbs for billing methods for current scoped actor
*/
-export class MeteringAndBillingService {
+export class MeteringService {
#kvStore: DBKVStore;
#superUserService: SUService;
#alarmService: AlarmService;
#eventService: EventService;
- constructor({ kvStore, superUserService, alarmService, eventService }: MeteringAndBillingServiceDeps) {
+ constructor({ kvStore, superUserService, alarmService, eventService }: MeteringServiceDeps) {
this.#superUserService = superUserService;
this.#kvStore = kvStore;
this.#alarmService = alarmService;
diff --git a/src/backend/src/services/MeteringService/MeteringServiceWrapper.mjs b/src/backend/src/services/MeteringService/MeteringServiceWrapper.mjs
index c9cd4b5b..1a8231fc 100644
--- a/src/backend/src/services/MeteringService/MeteringServiceWrapper.mjs
+++ b/src/backend/src/services/MeteringService/MeteringServiceWrapper.mjs
@@ -1,12 +1,12 @@
import BaseService from '../BaseService.js';
-import { MeteringAndBillingService } from "./MeteringService.js";
+import { MeteringService } from './MeteringService.js';
-export class MeteringAndBillingServiceWrapper extends BaseService {
+export class MeteringServiceWrapper extends BaseService {
- /** @type {import('./MeteringService.js').MeteringAndBillingService} */
- meteringAndBillingService = undefined;
+ /** @type {import('./MeteringService.js').MeteringService} */
+ meteringService = undefined;
_init() {
- this.meteringAndBillingService = new MeteringAndBillingService({
+ this.meteringService = new MeteringService({
kvStore: this.services.get('puter-kvstore').as('puter-kvstore'),
superUserService: this.services.get('su'),
alarmService: this.services.get('alarm'),
diff --git a/src/backend/src/services/MeteringService/types.ts b/src/backend/src/services/MeteringService/types.ts
index 28cc89cb..233755ee 100644
--- a/src/backend/src/services/MeteringService/types.ts
+++ b/src/backend/src/services/MeteringService/types.ts
@@ -1,7 +1,7 @@
-import type { AlarmService } from "../../modules/core/AlarmService";
-import type { EventService } from "../EventService";
-import type { DBKVStore } from "../repositories/DBKVStore/DBKVStore";
-import type { SUService } from "../SUService";
+import type { AlarmService } from '../../modules/core/AlarmService';
+import type { EventService } from '../EventService';
+import type { DBKVStore } from '../repositories/DBKVStore/DBKVStore';
+import type { SUService } from '../SUService';
export interface UsageAddons {
purchasedCredits: number // total extra credits purchased - not expirable
@@ -16,7 +16,7 @@ export interface UsageByType {
[serviceName: string]: number
}
-export interface MeteringAndBillingServiceDeps {
+export interface MeteringServiceDeps {
kvStore: DBKVStore,
superUserService: SUService,
alarmService: AlarmService
diff --git a/src/backend/src/services/repositories/DBKVStore/DBKVStore.ts b/src/backend/src/services/repositories/DBKVStore/DBKVStore.ts
index fdda5f0a..6bde2e9a 100644
--- a/src/backend/src/services/repositories/DBKVStore/DBKVStore.ts
+++ b/src/backend/src/services/repositories/DBKVStore/DBKVStore.ts
@@ -5,20 +5,20 @@ import APIError from '../../../api/APIError.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { Context } from '../../../util/context.js';
-import type { MeteringAndBillingService } from '../../MeteringService/MeteringService.js';
+import type { MeteringService } from '../../MeteringService/MeteringService.js';
const GLOBAL_APP_KEY = 'global';
export class DBKVStore {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
#db: any;
- #meteringService: MeteringAndBillingService;
+ #meteringService: MeteringService;
#global_config: Record = {};
// TODO DS: make table name configurable
- constructor({ sqlClient, meteringAndBillingService, globalConfig }: { sqlClient: unknown, meteringAndBillingService: MeteringAndBillingService, globalConfig: Record }) {
+ constructor({ sqlClient, meteringService, globalConfig }: { sqlClient: unknown, meteringService: MeteringService, globalConfig: Record }) {
this.#db = sqlClient;
- this.#meteringService = meteringAndBillingService;
+ this.#meteringService = meteringService;
this.#global_config = globalConfig;
}
diff --git a/src/backend/src/services/repositories/DBKVStore/index.mjs b/src/backend/src/services/repositories/DBKVStore/index.mjs
index 0eff0335..0aa8845d 100644
--- a/src/backend/src/services/repositories/DBKVStore/index.mjs
+++ b/src/backend/src/services/repositories/DBKVStore/index.mjs
@@ -8,7 +8,7 @@ export class DBKVServiceWrapper extends BaseService {
/** @type {DBKVStore} */
this.kvStore = new DBKVStore({
sqlClient: this.services.get('database').get(DB_READ, 'kvstore'),
- meteringAndBillingService: this.services.get('meteringService').meteringAndBillingService,
+ meteringService: this.services.get('meteringService').meteringService,
globalConfig: this.global_config,
});
}
diff --git a/src/puter-js/src/modules/Auth.js b/src/puter-js/src/modules/Auth.js
index 20795b20..afdd218e 100644
--- a/src/puter-js/src/modules/Auth.js
+++ b/src/puter-js/src/modules/Auth.js
@@ -174,7 +174,7 @@ class Auth{
async getMonthlyUsage() {
try {
- const resp = await fetch(`${this.APIOrigin}/meteringAndBilling/usage`, {
+ const resp = await fetch(`${this.APIOrigin}/metering/usage`, {
headers: {
Authorization: `Bearer ${this.authToken}`,
},
@@ -216,7 +216,7 @@ class Auth{
}
try {
- const resp = await fetch(`${this.APIOrigin}/meteringAndBilling/usage/${appId}`, {
+ const resp = await fetch(`${this.APIOrigin}/metering/usage/${appId}`, {
headers: {
Authorization: `Bearer ${this.authToken}`,
},