diff --git a/src/backend/src/modules/puterai/AITestModeService.js b/src/backend/src/modules/puterai/AITestModeService.js new file mode 100644 index 000000000..64289acae --- /dev/null +++ b/src/backend/src/modules/puterai/AITestModeService.js @@ -0,0 +1,12 @@ +const BaseService = require("../../services/BaseService"); + +class AITestModeService extends BaseService { + async _init () { + const svc_driver = this.services.get('driver'); + svc_driver.register_test_service('puter-chat-completion', 'openai-completion'); + } +} + +module.exports = { + AITestModeService, +}; diff --git a/src/backend/src/modules/puterai/AWSPollyService.js b/src/backend/src/modules/puterai/AWSPollyService.js index 1c8fd022d..5189e2592 100644 --- a/src/backend/src/modules/puterai/AWSPollyService.js +++ b/src/backend/src/modules/puterai/AWSPollyService.js @@ -12,6 +12,11 @@ class AWSPollyService extends BaseService { } static IMPLEMENTS = { + ['driver-capabilities']: { + supports_test_mode (iface, method_name) { + return iface === 'puter-tts' && method_name === 'synthesize'; + } + }, ['puter-tts']: { async list_voices () { const polly_voices = await this.describe_voices(); diff --git a/src/backend/src/modules/puterai/AWSTextractService.js b/src/backend/src/modules/puterai/AWSTextractService.js index 01e605e8d..e216397a5 100644 --- a/src/backend/src/modules/puterai/AWSTextractService.js +++ b/src/backend/src/modules/puterai/AWSTextractService.js @@ -9,6 +9,11 @@ class AWSTextractService extends BaseService { } static IMPLEMENTS = { + ['driver-capabilities']: { + supports_test_mode (iface, method_name) { + return iface === 'puter-ocr' && method_name === 'recognize'; + } + }, ['puter-ocr']: { async recognize ({ source, test_mode }) { if ( test_mode ) { diff --git a/src/backend/src/modules/puterai/OpenAICompletionService.js b/src/backend/src/modules/puterai/OpenAICompletionService.js index 7c170fe31..5c4fc1f07 100644 --- a/src/backend/src/modules/puterai/OpenAICompletionService.js +++ b/src/backend/src/modules/puterai/OpenAICompletionService.js @@ -22,6 +22,12 @@ class OpenAICompletionService extends BaseService { } static IMPLEMENTS = { + ['driver-capabilities']: { + supports_test_mode (iface, method_name) { + return iface === 'puter-chat-completion' && + method_name === 'complete'; + } + }, ['puter-chat-completion']: { async list () { return [ diff --git a/src/backend/src/modules/puterai/PuterAIModule.js b/src/backend/src/modules/puterai/PuterAIModule.js index a1241530f..f5618759c 100644 --- a/src/backend/src/modules/puterai/PuterAIModule.js +++ b/src/backend/src/modules/puterai/PuterAIModule.js @@ -56,6 +56,9 @@ class PuterAIModule extends AdvancedBase { const { FakeChatService } = require('./FakeChatService'); services.registerService('fake-chat', FakeChatService); + + const{ AITestModeService } = require('./AITestModeService'); + services.registerService('ai-test-mode', AITestModeService); } } diff --git a/src/backend/src/services/auth/PermissionService.js b/src/backend/src/services/auth/PermissionService.js index 27b4bb4bd..59d42d919 100644 --- a/src/backend/src/services/auth/PermissionService.js +++ b/src/backend/src/services/auth/PermissionService.js @@ -226,6 +226,10 @@ class PermissionService extends BaseService { } async scan (actor, permission_options, _reserved, state) { + if ( ! state ) this.log.info('scan', { + actor: actor.uid, + permission_options, + }); const reading = []; if ( ! state ) { diff --git a/src/backend/src/services/drivers/DriverService.js b/src/backend/src/services/drivers/DriverService.js index 74c180317..c9220b67b 100644 --- a/src/backend/src/services/drivers/DriverService.js +++ b/src/backend/src/services/drivers/DriverService.js @@ -37,6 +37,7 @@ class DriverService extends BaseService { _construct () { this.drivers = {}; this.interface_to_implementation = {}; + this.interface_to_test_service = {}; } async ['__on_registry.collections'] () { @@ -77,6 +78,10 @@ class DriverService extends BaseService { register_driver (interface_name, implementation) { this.interface_to_implementation[interface_name] = implementation; } + + register_test_service (interface_name, service_name) { + this.interface_to_test_service[interface_name] = service_name; + } get_interface (interface_name) { const o = {}; @@ -113,7 +118,8 @@ class DriverService extends BaseService { async _call ({ driver, iface, method, args }) { console.log('??', driver, iface, method, args); const processed_args = await this._process_args(iface, method, args); - if ( Context.get('test_mode') ) { + const test_mode = Context.get('test_mode'); + if ( test_mode ) { processed_args.test_mode = true; } @@ -141,18 +147,31 @@ class DriverService extends BaseService { driver = driver ?? iface_to_driver[iface] ?? iface; + let skip_usage = false; + if ( test_mode && this.interface_to_test_service[iface] ) { + driver = this.interface_to_test_service[iface]; + } + const driver_service_exists = (() => { + console.log('CHECKING FOR THIS', driver, iface); return this.services.has(driver) && this.services.get(driver).list_traits() .includes(iface); })(); if ( driver_service_exists ) { const service = this.services.get(driver); + + const caps = service.as('driver-capabilities'); + if ( test_mode && caps && caps.supports_test_mode(iface, method) ) { + skip_usage = true; + } + return await this.call_new_({ actor, service, service_name: driver, iface, method, args: processed_args, + skip_usage, }); } @@ -240,6 +259,7 @@ class DriverService extends BaseService { service, service_name, iface, method, args, + skip_usage, }) { const svc_permission = this.services.get('permission'); const reading = await svc_permission.scan( @@ -324,6 +344,8 @@ class DriverService extends BaseService { { name: 'enforce monthly usage limit', on_call: async args => { + if ( skip_usage ) return args; + // Typo-Tolerance if ( effective_policy?.['monthy-limit'] ) { effective_policy['monthly-limit'] = effective_policy['monthy-limit']; @@ -343,6 +365,8 @@ class DriverService extends BaseService { return args; }, on_return: async result => { + if ( skip_usage ) return result; + console.log('monthly usage is returning'); const svc_monthlyUsage = services.get('monthly-usage'); const extra = {