diff --git a/src/backend/exports.js b/src/backend/exports.js
index ab339c5ed..fe4767925 100644
--- a/src/backend/exports.js
+++ b/src/backend/exports.js
@@ -40,6 +40,9 @@ const { PuterExecModule } = require("./src/modules/puterexec/PuterExecModule.js"
const { MailModule } = require("./src/modules/mail/MailModule.js");
const { ConvertModule } = require("./src/modules/convert/ConvertModule.js");
const { CaptchaModule } = require("./src/modules/captcha/CaptchaModule.js");
+const { EntityStoreModule } = require("./src/modules/entitystore/EntityStoreModule.js");
+const { AnalyticsModule } = require("./src/modules/analytics/AnalyticsModule.js");
+const { KVStoreModule } = require("./src/modules/kvstore/KVStoreModule.js");
module.exports = {
helloworld: () => {
@@ -63,6 +66,9 @@ module.exports = {
TemplateModule,
AppsModule,
CaptchaModule,
+ EntityStoreModule,
+ AnalyticsModule,
+ KVStoreModule,
],
// Pre-built modules
@@ -79,6 +85,7 @@ module.exports = {
MailModule,
ConvertModule,
CaptchaModule,
+ KVStoreModule,
// Development modules
PerfMonModule,
diff --git a/src/backend/src/modules/analytics/AnalyticsInterfaceService.js b/src/backend/src/modules/analytics/AnalyticsInterfaceService.js
new file mode 100644
index 000000000..1102d1365
--- /dev/null
+++ b/src/backend/src/modules/analytics/AnalyticsInterfaceService.js
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+const BaseService = require("../../services/BaseService");
+
+/**
+* Service class that manages Analytics interface registrations.
+* Handles registration of the puter-analytics interface.
+* @extends BaseService
+*/
+class AnalyticsInterfaceService extends BaseService {
+ /**
+ * Service class for managing Analytics interface registrations.
+ * Extends the base service to provide analytics interface management.
+ */
+ async ['__on_driver.register.interfaces'] () {
+ const svc_registry = this.services.get('registry');
+ const col_interfaces = svc_registry.get('interfaces');
+
+ // Register the puter-analytics interface
+ col_interfaces.set('puter-analytics', {
+ no_sdk: true,
+ description: 'Analytics.',
+ methods: {
+ create_trace: {
+ description: 'Get a trace UID.',
+ parameters: {
+ trace_id: { type: 'string', optional: true },
+ },
+ result: { type: 'string' }
+ },
+ record: {
+ description: 'Record an event.',
+ parameters: {
+ trace_id: { type: 'string', optional: true },
+ tags: { type: 'json' },
+ fields: { type: 'json' },
+ },
+ result: { type: 'void' }
+ }
+ }
+ });
+ }
+}
+
+module.exports = {
+ AnalyticsInterfaceService
+};
\ No newline at end of file
diff --git a/src/backend/src/modules/analytics/AnalyticsModule.js b/src/backend/src/modules/analytics/AnalyticsModule.js
new file mode 100644
index 000000000..2343bc760
--- /dev/null
+++ b/src/backend/src/modules/analytics/AnalyticsModule.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * 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 { AnalyticsInterfaceService } = require("./AnalyticsInterfaceService");
+
+/**
+ * A module for registering analytics interfaces.
+ */
+class AnalyticsModule extends AdvancedBase {
+ async install(context) {
+ const services = context.get('services');
+
+ // Register interface services
+ services.registerService('analytics-interface', AnalyticsInterfaceService);
+ }
+}
+
+module.exports = {
+ AnalyticsModule,
+};
\ No newline at end of file
diff --git a/src/backend/src/modules/entitystore/EntityStoreInterfaceService.js b/src/backend/src/modules/entitystore/EntityStoreInterfaceService.js
new file mode 100644
index 000000000..53bd6a9ec
--- /dev/null
+++ b/src/backend/src/modules/entitystore/EntityStoreInterfaceService.js
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+// METADATA // {"ai-commented":{"service":"claude"}}
+const BaseService = require("../../services/BaseService");
+
+/**
+* Service class that manages Entity Store interface registrations.
+* Handles registration of the crud-q interface which is used by various
+* entity storage services.
+* @extends BaseService
+*/
+class EntityStoreInterfaceService extends BaseService {
+ /**
+ * Service class for managing Entity Store interface registrations.
+ * Extends the base service to provide entity storage interface management.
+ */
+ async ['__on_driver.register.interfaces'] () {
+ const svc_registry = this.services.get('registry');
+ const col_interfaces = svc_registry.get('interfaces');
+
+ // Define the standard CRUD interface methods that will be reused
+ const crudMethods = {
+ create: {
+ parameters: {
+ object: {
+ type: 'json',
+ subtype: 'object',
+ required: true,
+ },
+ options: { type: 'json' },
+ }
+ },
+ read: {
+ parameters: {
+ uid: { type: 'string' },
+ id: { type: 'json' },
+ params: { type: 'json' },
+ }
+ },
+ select: {
+ parameters: {
+ predicate: { type: 'json' },
+ offset: { type: 'number' },
+ limit: { type: 'number' },
+ params: { type: 'json' },
+ }
+ },
+ update: {
+ parameters: {
+ id: { type: 'json' },
+ object: {
+ type: 'json',
+ subtype: 'object',
+ required: true,
+ },
+ options: { type: 'json' },
+ }
+ },
+ upsert: {
+ parameters: {
+ id: { type: 'json' },
+ object: {
+ type: 'json',
+ subtype: 'object',
+ required: true,
+ },
+ options: { type: 'json' },
+ }
+ },
+ delete: {
+ parameters: {
+ uid: { type: 'string' },
+ id: { type: 'json' },
+ }
+ },
+ };
+
+ // Register the crud-q interface
+ col_interfaces.set('crud-q', {
+ methods: { ...crudMethods }
+ });
+
+ // Register entity-specific interfaces that use crud-q
+ const entityInterfaces = [
+ {
+ name: 'puter-apps',
+ description: 'Manage a developer\'s apps on Puter.'
+ },
+ {
+ name: 'puter-subdomains',
+ description: 'Manage subdomains on Puter.'
+ },
+ {
+ name: 'puter-notifications',
+ description: 'Read notifications on Puter.'
+ }
+ ];
+
+ // Register each entity interface with the same CRUD methods
+ for (const entity of entityInterfaces) {
+ col_interfaces.set(entity.name, {
+ description: entity.description,
+ methods: { ...crudMethods }
+ });
+ }
+ }
+}
+
+module.exports = {
+ EntityStoreInterfaceService
+};
\ No newline at end of file
diff --git a/src/backend/src/modules/entitystore/EntityStoreModule.js b/src/backend/src/modules/entitystore/EntityStoreModule.js
new file mode 100644
index 000000000..fa42c8789
--- /dev/null
+++ b/src/backend/src/modules/entitystore/EntityStoreModule.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * 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 { EntityStoreInterfaceService } = require("./EntityStoreInterfaceService");
+
+/**
+ * A module for registering entity store interfaces.
+ */
+class EntityStoreModule extends AdvancedBase {
+ async install(context) {
+ const services = context.get('services');
+
+ // Register interface services
+ services.registerService('entitystore-interface', EntityStoreInterfaceService);
+ }
+}
+
+module.exports = {
+ EntityStoreModule,
+};
\ No newline at end of file
diff --git a/src/backend/src/modules/kvstore/KVStoreInterfaceService.js b/src/backend/src/modules/kvstore/KVStoreInterfaceService.js
new file mode 100644
index 000000000..5f022b712
--- /dev/null
+++ b/src/backend/src/modules/kvstore/KVStoreInterfaceService.js
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+const BaseService = require("../../services/BaseService");
+
+/**
+* Service class that manages KVStore interface registrations.
+* Handles registration of the puter-kvstore interface.
+* @extends BaseService
+*/
+class KVStoreInterfaceService extends BaseService {
+ /**
+ * Service class for managing KVStore interface registrations.
+ * Extends the base service to provide key-value store interface management.
+ */
+ async ['__on_driver.register.interfaces'] () {
+ const svc_registry = this.services.get('registry');
+ const col_interfaces = svc_registry.get('interfaces');
+
+ // Register the puter-kvstore interface
+ col_interfaces.set('puter-kvstore', {
+ description: 'A simple key-value store.',
+ methods: {
+ get: {
+ description: 'Get a value by key.',
+ parameters: {
+ key: { type: 'json', required: true },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'json' },
+ },
+ set: {
+ description: 'Set a value by key.',
+ parameters: {
+ key: { type: 'string', required: true, },
+ value: { type: 'json' },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'void' },
+ },
+ del: {
+ description: 'Delete a value by key.',
+ parameters: {
+ key: { type: 'string' },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'void' },
+ },
+ list: {
+ description: 'List all key-value pairs.',
+ parameters: {
+ as: {
+ type: 'string',
+ },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'array' },
+ },
+ flush: {
+ description: 'Delete all key-value pairs.',
+ parameters: {},
+ result: { type: 'void' },
+ },
+ incr: {
+ description: 'Increment a value by key.',
+ parameters: {
+ key: { type: 'string', required: true, },
+ amount: { type: 'number' },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'number' },
+ },
+ decr: {
+ description: 'Increment a value by key.',
+ parameters: {
+ key: { type: 'string', required: true, },
+ amount: { type: 'number' },
+ app_uid: { type: 'string', optional: true },
+ },
+ result: { type: 'number' },
+ },
+ }
+ });
+ }
+}
+
+module.exports = {
+ KVStoreInterfaceService
+};
\ No newline at end of file
diff --git a/src/backend/src/modules/kvstore/KVStoreModule.js b/src/backend/src/modules/kvstore/KVStoreModule.js
new file mode 100644
index 000000000..55dd59709
--- /dev/null
+++ b/src/backend/src/modules/kvstore/KVStoreModule.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * 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 { KVStoreInterfaceService } = require("./KVStoreInterfaceService");
+
+/**
+ * A module for registering key-value store interfaces.
+ */
+class KVStoreModule extends AdvancedBase {
+ async install(context) {
+ const services = context.get('services');
+
+ // Register interface services
+ services.registerService('kvstore-interface', KVStoreInterfaceService);
+ }
+}
+
+module.exports = {
+ KVStoreModule,
+};
\ No newline at end of file
diff --git a/src/backend/src/services/drivers/DriverService.js b/src/backend/src/services/drivers/DriverService.js
index 82a07c4fd..58d41a693 100644
--- a/src/backend/src/services/drivers/DriverService.js
+++ b/src/backend/src/services/drivers/DriverService.js
@@ -111,12 +111,6 @@ class DriverService extends BaseService {
const col_interfaces = svc_registry.get('interfaces');
const col_drivers = svc_registry.get('drivers');
const col_types = svc_registry.get('types');
- {
- const default_interfaces = require('./interfaces');
- for ( const k in default_interfaces ) {
- col_interfaces.set(k, default_interfaces[k]);
- }
- }
{
const types = this.modules.types;
for ( const k in types ) {
diff --git a/src/backend/src/services/drivers/interfaces.js b/src/backend/src/services/drivers/interfaces.js
deleted file mode 100644
index 2871ea4d4..000000000
--- a/src/backend/src/services/drivers/interfaces.js
+++ /dev/null
@@ -1,299 +0,0 @@
-// METADATA // {"ai-commented":{"service":"xai"}}
-/*
- * Copyright (C) 2024-present Puter Technologies Inc.
- *
- * This file is part of Puter.
- *
- * Puter is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-const ENTITY_STORAGE_INTERFACE = {
- methods: {
- create: {
- parameters: {
- object: {
- type: 'json',
- subtype: 'object',
- required: true,
- },
- options: { type: 'json' },
- }
- },
- read: {
- parameters: {
- uid: { type: 'string' },
- id: { type: 'json' },
- params: { type: 'json' },
- }
- },
- select: {
- parameters: {
- predicate: { type: 'json' },
- offset: { type: 'number' },
- limit: { type: 'number' },
- params: { type: 'json' },
- }
- },
- update: {
- parameters: {
- id: { type: 'json' },
- object: {
- type: 'json',
- subtype: 'object',
- required: true,
- },
- options: { type: 'json' },
- }
- },
- upsert: {
- parameters: {
- id: { type: 'json' },
- object: {
- type: 'json',
- subtype: 'object',
- required: true,
- },
- options: { type: 'json' },
- }
- },
- delete: {
- parameters: {
- uid: { type: 'string' },
- id: { type: 'json' },
- }
- },
- },
-}
-
-module.exports = {
- 'hello-world': {
- description: 'A simple driver that returns a greeting.',
- methods: {
- greet: {
- description: 'Returns a greeting.',
- parameters: {
- subject: {
- type: 'string',
- optional: true,
- },
- },
- result: { type: 'string' },
- }
- }
- },
- // Note: these are all prefixed with 'puter-' to avoid name collisions
- // with possible future support for user-contributed driver interfaces.
- 'puter-ocr': {
- description: 'Optical character recognition.',
- methods: {
- recognize: {
- description: 'Recognize text in an image or document.',
- parameters: {
- source: {
- type: 'file',
- },
- },
- result: { type: 'image' },
- },
- },
- },
- 'puter-kvstore': {
- description: 'A simple key-value store.',
- methods: {
- get: {
- description: 'Get a value by key.',
- parameters: {
- key: { type: 'json', required: true },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'json' },
- },
- set: {
- description: 'Set a value by key.',
- parameters: {
- key: { type: 'string', required: true, },
- value: { type: 'json' },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'void' },
- },
- del: {
- description: 'Delete a value by key.',
- parameters: {
- key: { type: 'string' },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'void' },
- },
- list: {
- description: 'List all key-value pairs.',
- parameters: {
- as: {
- type: 'string',
- },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'array' },
- },
- flush: {
- description: 'Delete all key-value pairs.',
- parameters: {},
- result: { type: 'void' },
- },
- incr: {
- description: 'Increment a value by key.',
- parameters: {
- key: { type: 'string', required: true, },
- amount: { type: 'number' },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'number' },
- },
- decr: {
- description: 'Increment a value by key.',
- parameters: {
- key: { type: 'string', required: true, },
- amount: { type: 'number' },
- app_uid: { type: 'string', optional: true },
- },
- result: { type: 'number' },
- },
- /*
- expireat: {
- description: 'Set a key\'s time-to-live.',
- parameters: {
- key: { type: 'string', required: true, },
- timestamp: { type: 'number', required: true, },
- app_uid: { type: 'string', optional: true },
- },
- },
- expire: {
- description: 'Set a key\'s time-to-live.',
- parameters: {
- key: { type: 'string', required: true, },
- ttl: { type: 'number', required: true, },
- app_uid: { type: 'string', optional: true },
- },
- }
- */
- }
- },
- 'puter-chat-completion': {
- description: 'Chatbot.',
- methods: {
- complete: {
- description: 'Get completions for a chat log.',
- parameters: {
- messages: { type: 'json' },
- vision: { type: 'flag' },
- },
- result: { type: 'json' }
- }
- }
- },
- 'puter-image-generation': {
- description: 'AI Image Generation.',
- methods: {
- generate: {
- description: 'Generate an image from a prompt.',
- parameters: {
- prompt: { type: 'string' },
- },
- result_choices: [
- {
- names: ['image'],
- type: {
- $: 'stream',
- content_type: 'image',
- }
- },
- {
- names: ['url'],
- type: {
- $: 'string:url:web',
- content_type: 'image',
- }
- },
- ],
- result: {
- description: 'URL of the generated image.',
- type: 'string'
- }
- }
- }
- },
- 'puter-tts': {
- description: 'Text-to-speech.',
- methods: {
- list_voices: {
- description: 'List available voices.',
- parameters: {},
- },
- synthesize: {
- description: 'Synthesize speech from text.',
- parameters: {
- text: { type: 'string' },
- voice: { type: 'string' },
- language: { type: 'string' },
- ssml: { type: 'flag' },
- },
- result_choices: [
- {
- names: ['audio'],
- type: {
- $: 'stream',
- content_type: 'audio',
- }
- },
- ]
- },
- }
- },
- 'puter-analytics': {
- no_sdk: true,
- description: 'Analytics.',
- methods: {
- create_trace: {
- description: 'Get a trace UID.',
- parameters: {
- trace_id: { type: 'string', optional: true },
- },
- result: { type: 'string' }
- },
- record: {
- description: 'Record an event.',
- parameters: {
- trace_id: { type: 'string', optional: true },
- tags: { type: 'json' },
- fields: { type: 'json' },
- },
- result: { type: 'void' }
- }
- }
- },
- 'puter-apps': {
- ...ENTITY_STORAGE_INTERFACE,
- description: 'Manage a developer\'s apps on Puter.',
- },
- 'puter-subdomains': {
- ...ENTITY_STORAGE_INTERFACE,
- description: 'Manage subdomains on Puter.',
- },
- 'puter-notifications': {
- ...ENTITY_STORAGE_INTERFACE,
- description: 'Read notifications on Puter.',
- },
- 'crud-q': {
- ...ENTITY_STORAGE_INTERFACE,
- },
-};