concept-lang
Version:
A semantic network system for defining concepts, relationships, and building knowledge graphs with automatic inference
266 lines (255 loc) • 9.33 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConceptPluginManager = void 0;
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
class ConceptPluginManager {
constructor(block) {
this.plugins = new Map();
this.listeners = new Map();
this.block = block;
this.initializeEventTypes();
}
initializeEventTypes() {
const eventTypes = [
'concept:added',
'concept:updated',
'pair:added',
'pair:updated',
'data:added',
'data:updated',
'inference:completed',
'block:state:changed',
];
eventTypes.forEach(eventType => {
this.listeners.set(eventType, new Set());
});
}
async loadPlugin(pathOrName) {
try {
let pluginPath;
// Check if it's a local path
if (path.isAbsolute(pathOrName) ||
pathOrName.startsWith('./') ||
pathOrName.startsWith('../')) {
pluginPath = path.resolve(pathOrName);
}
else {
// Try to resolve as npm package
pluginPath = require.resolve(pathOrName);
}
// Load the plugin
const pluginModule = require(pluginPath);
const PluginClass = pluginModule.default || pluginModule;
if (!PluginClass || typeof PluginClass !== 'function') {
throw new Error(`Invalid plugin at ${pluginPath}: must export a ConceptPlugin class`);
}
// Instantiate the plugin
const plugin = new PluginClass();
if (!plugin || typeof plugin !== 'object') {
throw new Error(`Invalid plugin at ${pluginPath}: must export a ConceptPlugin object`);
}
if (!plugin.config || !plugin.config.name) {
throw new Error(`Plugin at ${pluginPath} must have a valid config with name`);
}
if (typeof plugin.registerListeners !== 'function') {
throw new Error(`Plugin ${plugin.config.name} must implement registerListeners method`);
}
// Initialize plugin if method exists
if (plugin.initialize) {
await plugin.initialize();
}
// Set block instance for concept execution
if (plugin.setBlock) {
plugin.setBlock(this.block);
}
// Register plugin listeners
const pluginListeners = plugin.registerListeners();
for (const [eventType, listener] of pluginListeners) {
this.registerListener(eventType, listener);
}
// Store plugin
this.plugins.set(plugin.config.name, plugin);
console.log(`✅ Loaded plugin: ${plugin.config.name} v${plugin.config.version}`);
return plugin;
}
catch (error) {
console.error(`❌ Failed to load plugin ${pathOrName}:`, error);
throw error;
}
}
async unloadPlugin(name) {
const plugin = this.plugins.get(name);
if (!plugin) {
throw new Error(`Plugin ${name} is not loaded`);
}
// Cleanup plugin if method exists
if (plugin.cleanup) {
await plugin.cleanup();
}
// Remove plugin listeners
const pluginListeners = plugin.registerListeners();
for (const [eventType, listener] of pluginListeners) {
this.unregisterListener(eventType, listener);
}
// Remove plugin
this.plugins.delete(name);
console.log(`✅ Unloaded plugin: ${name}`);
}
getLoadedPlugins() {
return Array.from(this.plugins.values());
}
getLoadedPluginNames() {
return Array.from(this.plugins.keys());
}
registerListener(eventType, listener) {
const listeners = this.listeners.get(eventType);
if (listeners) {
listeners.add(listener);
}
}
unregisterListener(eventType, listener) {
const listeners = this.listeners.get(eventType);
if (listeners) {
listeners.delete(listener);
}
}
async emitEvent(event) {
const listeners = this.listeners.get(event.type);
if (listeners && listeners.size > 0) {
const promises = Array.from(listeners).map(async (listener) => {
try {
await listener(event);
}
catch (error) {
console.error(`Error in plugin listener for ${event.type}:`, error);
}
});
await Promise.all(promises);
}
}
getListeners(eventType) {
const listeners = this.listeners.get(eventType);
return listeners ? Array.from(listeners) : [];
}
/**
* Get all plugin hooks
*/
getAllPluginHooks() {
const hooks = {};
for (const [name, plugin] of this.plugins) {
if (plugin.getHooks) {
const pluginHooks = plugin.getHooks();
Object.entries(pluginHooks).forEach(([hookName, hookFn]) => {
hooks[`${name}:${hookName}`] = hookFn;
});
}
}
return hooks;
}
/**
* Create a plugin configuration file template
*/
static createPluginTemplate(pluginName, outputDir = './plugins') {
const template = `import { ConceptPlugin, PluginConfig, ConceptEvent, ConceptEventType, ConceptListener } from 'concept-lang';
const config: PluginConfig = {
name: '${pluginName}',
version: '3.0.0',
description: 'A concept language plugin',
author: 'Your Name',
license: 'MIT',
main: 'index.js',
conceptListeners: ['concept:added', 'data:added']
};
class ${pluginName}Plugin implements ConceptPlugin {
readonly config = config;
async initialize(): Promise<void> {
console.log(\`Initializing \${this.config.name} plugin\`);
}
async cleanup(): Promise<void> {
console.log(\`Cleaning up \${this.config.name} plugin\`);
}
registerListeners(): Map<ConceptEventType, ConceptListener> {
const listeners = new Map<ConceptEventType, ConceptListener>();
// Example: Listen to concept additions
listeners.set('concept:added', (event: ConceptEvent) => {
console.log('New concept added:', event.data);
});
// Example: Listen to data additions
listeners.set('data:added', (event: ConceptEvent) => {
console.log('New data added:', event.data);
});
return listeners;
}
getHooks() {
return {
// Example hook that processes 'hello' commands
hello: (params: any[]) => {
console.log('Hello hook triggered with params:', params);
return params;
}
};
}
}
export default ${pluginName}Plugin;
`;
const pluginDir = path.resolve(outputDir, pluginName);
if (!fs.existsSync(pluginDir)) {
fs.mkdirSync(pluginDir, { recursive: true });
}
const filePath = path.join(pluginDir, 'index.ts');
fs.writeFileSync(filePath, template);
// Create package.json for the plugin
const packageJson = {
name: pluginName,
version: '3.0.0',
description: 'A concept language plugin',
main: 'index.js',
types: 'index.d.ts',
dependencies: {
'concept-lang': '^1.0.0',
},
scripts: {
build: 'tsc',
dev: 'tsc --watch',
},
};
fs.writeFileSync(path.join(pluginDir, 'package.json'), JSON.stringify(packageJson, null, 2));
console.log(`✅ Created plugin template at: ${filePath}`);
}
}
exports.ConceptPluginManager = ConceptPluginManager;
//# sourceMappingURL=plugin-manager.js.map
;