praisonai 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -277,20 +277,24 @@ class Agent {
277
277
  if (previousResult) {
278
278
  prompt = prompt.replace('{{previous}}', previousResult);
279
279
  }
280
- // Initialize messages array
280
+ // Initialize messages array with system prompt and conversation history
281
281
  const messages = [
282
- { role: 'system', content: this.createSystemPrompt() },
283
- { role: 'user', content: prompt }
282
+ { role: 'system', content: this.createSystemPrompt() }
284
283
  ];
284
+ // Add conversation history (excluding the current prompt which will be added below)
285
+ for (const msg of this.messages) {
286
+ if (msg.role && msg.content) {
287
+ messages.push({ role: msg.role, content: msg.content });
288
+ }
289
+ }
290
+ // Add current user prompt
291
+ messages.push({ role: 'user', content: prompt });
285
292
  let finalResponse = '';
286
293
  if (this.stream && !this.tools) {
287
- // Use streaming without tools
288
- let fullResponse = '';
289
- await this.llmService.streamText(prompt, this.createSystemPrompt(), 0.7, (token) => {
294
+ // Use streaming with full conversation history
295
+ finalResponse = await this.llmService.streamChat(messages, 0.7, (token) => {
290
296
  process.stdout.write(token);
291
- fullResponse += token;
292
297
  });
293
- finalResponse = fullResponse;
294
298
  }
295
299
  else if (this.tools) {
296
300
  // Use tools (non-streaming for now to simplify implementation)
@@ -1,5 +1,10 @@
1
1
  /**
2
- * Providers command - List available LLM providers
2
+ * Providers command - List and manage LLM providers
3
+ *
4
+ * Supports:
5
+ * - list: List all registered providers
6
+ * - register: Register a custom provider (programmatic only)
7
+ * - info: Show provider details
3
8
  */
4
9
  export interface ProvidersOptions {
5
10
  verbose?: boolean;
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  /**
3
- * Providers command - List available LLM providers
3
+ * Providers command - List and manage LLM providers
4
+ *
5
+ * Supports:
6
+ * - list: List all registered providers
7
+ * - register: Register a custom provider (programmatic only)
8
+ * - info: Show provider details
4
9
  */
5
10
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
11
  if (k2 === undefined) k2 = k;
@@ -41,58 +46,127 @@ const providers_1 = require("../../llm/providers");
41
46
  const env_1 = require("../runtime/env");
42
47
  const json_1 = require("../output/json");
43
48
  const pretty = __importStar(require("../output/pretty"));
49
+ const errors_1 = require("../output/errors");
50
+ const BUILTIN_PROVIDERS = ['openai', 'anthropic', 'google', 'gemini', 'oai', 'claude'];
44
51
  const PROVIDER_MODELS = {
45
52
  openai: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo'],
46
53
  anthropic: ['claude-sonnet-4-20250514', 'claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'],
47
54
  google: ['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash']
48
55
  };
49
56
  async function execute(args, options) {
57
+ const subcommand = args[0] || 'list';
50
58
  const outputFormat = options.json ? 'json' : (options.output || 'pretty');
51
- const availableProviders = (0, providers_1.getAvailableProviders)();
52
- const providers = [
53
- {
54
- name: 'openai',
55
- available: availableProviders.includes('openai'),
56
- hasApiKey: (0, env_1.hasApiKey)('openai'),
57
- models: PROVIDER_MODELS.openai
58
- },
59
- {
60
- name: 'anthropic',
61
- available: availableProviders.includes('anthropic'),
62
- hasApiKey: (0, env_1.hasApiKey)('anthropic'),
63
- models: PROVIDER_MODELS.anthropic
64
- },
65
- {
66
- name: 'google',
67
- available: availableProviders.includes('google'),
68
- hasApiKey: (0, env_1.hasApiKey)('google'),
69
- models: PROVIDER_MODELS.google
70
- }
71
- ];
59
+ switch (subcommand) {
60
+ case 'list':
61
+ await listProvidersCommand(options, outputFormat);
62
+ break;
63
+ case 'info':
64
+ await providerInfoCommand(args[1], options, outputFormat);
65
+ break;
66
+ default:
67
+ await listProvidersCommand(options, outputFormat);
68
+ }
69
+ }
70
+ async function listProvidersCommand(options, outputFormat) {
71
+ const registry = (0, providers_1.getDefaultRegistry)();
72
+ const registeredProviders = registry.list();
73
+ const providers = registeredProviders.map(name => {
74
+ const isBuiltin = BUILTIN_PROVIDERS.includes(name);
75
+ return {
76
+ name,
77
+ registered: true,
78
+ available: (0, providers_1.isProviderAvailable)(name),
79
+ hasApiKey: (0, env_1.hasApiKey)(name),
80
+ isBuiltin,
81
+ models: PROVIDER_MODELS[name]
82
+ };
83
+ });
72
84
  if (outputFormat === 'json') {
73
85
  (0, json_1.outputJson)((0, json_1.formatSuccess)({
74
86
  providers: providers.map(p => ({
75
87
  name: p.name,
88
+ registered: p.registered,
76
89
  available: p.available,
77
90
  has_api_key: p.hasApiKey,
91
+ is_builtin: p.isBuiltin,
78
92
  models: options.verbose ? p.models : undefined
79
- }))
93
+ })),
94
+ total: providers.length,
95
+ builtin_count: providers.filter(p => p.isBuiltin).length,
96
+ custom_count: providers.filter(p => !p.isBuiltin).length
80
97
  }));
81
98
  }
82
99
  else {
83
- await pretty.heading('Available Providers');
84
- for (const provider of providers) {
85
- const status = provider.available ? '✅' : '❌';
86
- const keyStatus = provider.hasApiKey ? '🔑' : '⚠️ No API key';
87
- await pretty.plain(` ${status} ${provider.name} ${keyStatus}`);
88
- if (options.verbose && provider.models) {
89
- for (const model of provider.models) {
90
- await pretty.dim(` - ${model}`);
100
+ await pretty.heading('Registered LLM Providers');
101
+ // Built-in providers
102
+ const builtinProviders = providers.filter(p => p.isBuiltin);
103
+ if (builtinProviders.length > 0) {
104
+ await pretty.plain('\n Built-in:');
105
+ for (const provider of builtinProviders) {
106
+ const status = provider.available ? '✅' : '❌';
107
+ const keyStatus = provider.hasApiKey ? '🔑' : '⚠️ No API key';
108
+ await pretty.plain(` ${status} ${provider.name} ${keyStatus}`);
109
+ if (options.verbose && provider.models) {
110
+ for (const model of provider.models) {
111
+ await pretty.dim(` - ${model}`);
112
+ }
91
113
  }
92
114
  }
93
115
  }
116
+ // Custom providers
117
+ const customProviders = providers.filter(p => !p.isBuiltin);
118
+ if (customProviders.length > 0) {
119
+ await pretty.plain('\n Custom:');
120
+ for (const provider of customProviders) {
121
+ const status = provider.available ? '✅' : '❌';
122
+ await pretty.plain(` ${status} ${provider.name}`);
123
+ }
124
+ }
125
+ await pretty.newline();
126
+ await pretty.info('Register custom providers with registerProvider():');
127
+ await pretty.dim(' import { registerProvider } from "praisonai";');
128
+ await pretty.dim(' registerProvider("cloudflare", CloudflareProvider);');
94
129
  await pretty.newline();
95
130
  await pretty.info('Set API keys via environment variables:');
96
131
  await pretty.dim(' OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY');
97
132
  }
98
133
  }
134
+ async function providerInfoCommand(name, options, outputFormat) {
135
+ if (!name) {
136
+ if (outputFormat === 'json') {
137
+ (0, json_1.outputJson)((0, json_1.formatError)(errors_1.ERROR_CODES.MISSING_ARG, 'Provider name required'));
138
+ }
139
+ else {
140
+ await pretty.error('Provider name required. Usage: providers info <name>');
141
+ }
142
+ return;
143
+ }
144
+ const registry = (0, providers_1.getDefaultRegistry)();
145
+ const isRegistered = registry.has(name);
146
+ const isBuiltin = BUILTIN_PROVIDERS.includes(name.toLowerCase());
147
+ const available = (0, providers_1.isProviderAvailable)(name);
148
+ const models = PROVIDER_MODELS[name.toLowerCase()];
149
+ if (outputFormat === 'json') {
150
+ (0, json_1.outputJson)((0, json_1.formatSuccess)({
151
+ name,
152
+ registered: isRegistered,
153
+ available,
154
+ is_builtin: isBuiltin,
155
+ has_api_key: (0, env_1.hasApiKey)(name),
156
+ models: models || []
157
+ }));
158
+ }
159
+ else {
160
+ await pretty.heading(`Provider: ${name}`);
161
+ await pretty.plain(` Registered: ${isRegistered ? '✅ Yes' : '❌ No'}`);
162
+ await pretty.plain(` Available: ${available ? '✅ Yes' : '❌ No'}`);
163
+ await pretty.plain(` Type: ${isBuiltin ? 'Built-in' : 'Custom'}`);
164
+ await pretty.plain(` API Key: ${(0, env_1.hasApiKey)(name) ? '🔑 Set' : '⚠️ Not set'}`);
165
+ if (models && models.length > 0) {
166
+ await pretty.plain('\n Models:');
167
+ for (const model of models) {
168
+ await pretty.dim(` - ${model}`);
169
+ }
170
+ }
171
+ }
172
+ }
@@ -8,5 +8,5 @@ export interface EnvConfig {
8
8
  configPath?: string;
9
9
  }
10
10
  export declare function loadEnvConfig(): EnvConfig;
11
- export declare function hasApiKey(provider: 'openai' | 'anthropic' | 'google'): boolean;
11
+ export declare function hasApiKey(provider: string): boolean;
12
12
  export declare function getApiKey(provider: 'openai' | 'anthropic' | 'google'): string | undefined;
@@ -24,15 +24,21 @@ function loadEnvConfig() {
24
24
  return config;
25
25
  }
26
26
  function hasApiKey(provider) {
27
- switch (provider) {
27
+ const normalizedProvider = provider.toLowerCase();
28
+ switch (normalizedProvider) {
28
29
  case 'openai':
30
+ case 'oai':
29
31
  return !!process.env[cli_spec_1.ENV_VARS.OPENAI_API_KEY];
30
32
  case 'anthropic':
33
+ case 'claude':
31
34
  return !!process.env[cli_spec_1.ENV_VARS.ANTHROPIC_API_KEY];
32
35
  case 'google':
36
+ case 'gemini':
33
37
  return !!process.env[cli_spec_1.ENV_VARS.GOOGLE_API_KEY];
34
38
  default:
35
- return false;
39
+ // For custom providers, check for provider-specific env var
40
+ const envVarName = `${normalizedProvider.toUpperCase()}_API_KEY`;
41
+ return !!process.env[envVarName];
36
42
  }
37
43
  }
38
44
  function getApiKey(provider) {
package/dist/index.d.ts CHANGED
@@ -80,5 +80,5 @@ export { BaseObservabilityProvider, ConsoleObservabilityProvider, MemoryObservab
80
80
  export { BaseVoiceProvider, OpenAIVoiceProvider, ElevenLabsVoiceProvider, createOpenAIVoice, createElevenLabsVoice, type VoiceConfig, type SpeakOptions, type ListenOptions, type Speaker } from './integrations/voice';
81
81
  export { BaseReranker, CohereReranker, CrossEncoderReranker, LLMReranker, createCohereReranker, createCrossEncoderReranker, createLLMReranker, type RerankResult, type RerankConfig } from './knowledge/reranker';
82
82
  export { GraphStore, GraphRAG, createGraphRAG, type GraphNode, type GraphEdge, type GraphQueryResult, type GraphRAGConfig } from './knowledge/graph-rag';
83
- export { createProvider, getDefaultProvider, parseModelString, isProviderAvailable, getAvailableProviders, OpenAIProvider, AnthropicProvider, GoogleProvider, BaseProvider, type LLMProvider, type ProviderConfig, type ProviderFactory, type GenerateTextOptions, type GenerateTextResult, type StreamTextOptions, type StreamChunk, type GenerateObjectOptions, type GenerateObjectResult, type TokenUsage, type Message as ProviderMessage, type ToolCall, type ToolDefinition as ProviderToolDefinition, } from './llm/providers';
83
+ export { createProvider, getDefaultProvider, parseModelString, isProviderAvailable, getAvailableProviders, OpenAIProvider, AnthropicProvider, GoogleProvider, BaseProvider, ProviderRegistry, registerProvider, unregisterProvider, hasProvider, listProviders, getDefaultRegistry, createProviderRegistry, registerBuiltinProviders, type LLMProvider, type ProviderConfig, type ProviderFactory, type ProviderConstructor, type ProviderLoader, type RegisterOptions, type IProviderRegistry, type ProviderInput, type CreateProviderOptions, type GenerateTextOptions, type GenerateTextResult, type StreamTextOptions, type StreamChunk, type GenerateObjectOptions, type GenerateObjectResult, type TokenUsage, type Message as ProviderMessage, type ToolCall, type ToolDefinition as ProviderToolDefinition, } from './llm/providers';
84
84
  export { SlashCommandHandler, createSlashCommandHandler, registerCommand, parseSlashCommand, executeSlashCommand, isSlashCommand, type SlashCommand, type SlashCommandContext, type SlashCommandResult, CostTracker, createCostTracker, estimateTokens, formatCost, MODEL_PRICING, type ModelPricing, type TokenUsage as CostTokenUsage, type RequestStats, type SessionStats, InteractiveTUI, createInteractiveTUI, StatusDisplay, createStatusDisplay, HistoryManager, createHistoryManager, type TUIConfig, type TUIState, RepoMap, createRepoMap, getRepoTree, DEFAULT_IGNORE_PATTERNS, type RepoMapConfig, type FileInfo, type SymbolInfo, type RepoMapResult, GitManager, createGitManager, DiffViewer, createDiffViewer, type GitConfig, type GitStatus, type GitCommit, type GitDiff, type GitDiffFile, SandboxExecutor, createSandboxExecutor, sandboxExec, CommandValidator, DEFAULT_BLOCKED_COMMANDS, DEFAULT_BLOCKED_PATHS, type SandboxMode, type SandboxConfig, type ExecutionResult, AutonomyManager, createAutonomyManager, cliApprovalPrompt, MODE_POLICIES, type AutonomyMode, type ActionType, type ApprovalPolicy, type AutonomyConfig, type ActionRequest, type ActionDecision, Scheduler, createScheduler, cronExpressions, type ScheduleConfig, type ScheduledTask, type SchedulerStats, JobQueue, createJobQueue, MemoryJobStorage, FileJobStorage, createFileJobStorage, type Job, type JobStatus, type JobPriority, type JobQueueConfig, type JobStorageAdapter, type JobHandler, type JobContext, CheckpointManager, createCheckpointManager, MemoryCheckpointStorage, FileCheckpointStorage, createFileCheckpointStorage, type CheckpointData, type CheckpointConfig, type CheckpointStorage, FlowDisplay, createFlowDisplay, renderWorkflow, type FlowNode, type FlowGraph, type FlowDisplayConfig, BaseExternalAgent, ClaudeCodeAgent, GeminiCliAgent, CodexCliAgent, AiderAgent, GenericExternalAgent, getExternalAgentRegistry, createExternalAgent, externalAgentAsTool, type ExternalAgentConfig, type ExternalAgentResult, N8NIntegration, createN8NIntegration, triggerN8NWebhook, type N8NConfig, type N8NWebhookPayload, type N8NWorkflow, type N8NWorkflowNode, FastContext, createFastContext, getQuickContext, type FastContextConfig, type ContextSource, type FastContextResult } from './cli/features';
package/dist/index.js CHANGED
@@ -55,8 +55,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
55
55
  exports.AutoMemory = exports.createFileMemory = exports.FileMemory = exports.createMemory = exports.Memory = exports.CLI_SPEC_VERSION = exports.executeCommand = exports.parseArgs = exports.parseSkillFile = exports.createSkillManager = exports.SkillManager = exports.getObservabilityAdapter = exports.setObservabilityAdapter = exports.ConsoleObservabilityAdapter = exports.MemoryObservabilityAdapter = exports.EvalSuite = exports.reliabilityEval = exports.performanceEval = exports.accuracyEval = exports.createContextAgent = exports.ContextAgent = exports.routeConditions = exports.createRouter = exports.RouterAgent = exports.handoffFilters = exports.handoff = exports.Handoff = exports.getTool = exports.registerTool = exports.getRegistry = exports.ToolRegistry = exports.tool = exports.FunctionTool = exports.createTool = exports.validateTool = exports.ToolValidationError = exports.BaseTool = exports.setDefaultDbAdapter = exports.getDefaultDbAdapter = exports.createDbAdapter = exports.db = exports.repeat = exports.loop = exports.route = exports.parallel = exports.Workflow = exports.Router = exports.PraisonAIAgents = exports.Agents = exports.Agent = void 0;
56
56
  exports.SQLiteAdapter = exports.validateWorkflowDefinition = exports.loadWorkflowFromFile = exports.createWorkflowFromYAML = exports.parseYAMLWorkflow = exports.createPubSub = exports.createEventBus = exports.AgentEvents = exports.AgentEventBus = exports.EventEmitterPubSub = exports.PubSub = exports.createFileCache = exports.createMemoryCache = exports.FileCache = exports.MemoryCache = exports.BaseCache = exports.createTaskAgent = exports.createPlanningAgent = exports.createPlanStorage = exports.createTodoList = exports.createPlan = exports.TaskAgent = exports.PlanningAgent = exports.PlanStorage = exports.TodoItem = exports.TodoList = exports.PlanStep = exports.Plan = exports.createLLMGuardrail = exports.LLMGuardrail = exports.createPromptExpanderAgent = exports.PromptExpanderAgent = exports.createQueryRewriterAgent = exports.QueryRewriterAgent = exports.createDeepResearchAgent = exports.DeepResearchAgent = exports.createImageAgent = exports.ImageAgent = exports.createAutoAgents = exports.AutoAgents = exports.createAgentTelemetry = exports.cleanupTelemetry = exports.disableTelemetry = exports.enableTelemetry = exports.getTelemetry = exports.AgentTelemetry = exports.TelemetryCollector = exports.DEFAULT_POLICIES = exports.createLLMSummarizer = exports.createAutoMemory = void 0;
57
57
  exports.OpenAIProvider = exports.getAvailableProviders = exports.isProviderAvailable = exports.parseModelString = exports.getDefaultProvider = exports.createProvider = exports.createGraphRAG = exports.GraphRAG = exports.GraphStore = exports.createLLMReranker = exports.createCrossEncoderReranker = exports.createCohereReranker = exports.LLMReranker = exports.CrossEncoderReranker = exports.CohereReranker = exports.BaseReranker = exports.createElevenLabsVoice = exports.createOpenAIVoice = exports.ElevenLabsVoiceProvider = exports.OpenAIVoiceProvider = exports.BaseVoiceProvider = exports.createLangfuseObservability = exports.createMemoryObservability = exports.createConsoleObservability = exports.LangfuseObservabilityProvider = exports.MemoryObservabilityProvider = exports.ConsoleObservabilityProvider = exports.BaseObservabilityProvider = exports.createChromaStore = exports.ChromaVectorStore = exports.createQdrantStore = exports.QdrantVectorStore = exports.createWeaviateStore = exports.WeaviateVectorStore = exports.createPineconeStore = exports.PineconeVectorStore = exports.createMemoryVectorStore = exports.MemoryVectorStore = exports.BaseVectorStore = exports.createPostgresSessionStorage = exports.createMemoryPostgres = exports.createNeonPostgres = exports.PostgresSessionStorage = exports.MemoryPostgresAdapter = exports.NeonPostgresAdapter = exports.createMemoryRedis = exports.createUpstashRedis = exports.MemoryRedisAdapter = exports.UpstashRedisAdapter = exports.createSQLiteAdapter = void 0;
58
- exports.FileCheckpointStorage = exports.MemoryCheckpointStorage = exports.createCheckpointManager = exports.CheckpointManager = exports.createFileJobStorage = exports.FileJobStorage = exports.MemoryJobStorage = exports.createJobQueue = exports.JobQueue = exports.cronExpressions = exports.createScheduler = exports.Scheduler = exports.MODE_POLICIES = exports.cliApprovalPrompt = exports.createAutonomyManager = exports.AutonomyManager = exports.DEFAULT_BLOCKED_PATHS = exports.DEFAULT_BLOCKED_COMMANDS = exports.CommandValidator = exports.sandboxExec = exports.createSandboxExecutor = exports.SandboxExecutor = exports.createDiffViewer = exports.DiffViewer = exports.createGitManager = exports.GitManager = exports.DEFAULT_IGNORE_PATTERNS = exports.getRepoTree = exports.createRepoMap = exports.RepoMap = exports.createHistoryManager = exports.HistoryManager = exports.createStatusDisplay = exports.StatusDisplay = exports.createInteractiveTUI = exports.InteractiveTUI = exports.MODEL_PRICING = exports.formatCost = exports.estimateTokens = exports.createCostTracker = exports.CostTracker = exports.isSlashCommand = exports.executeSlashCommand = exports.parseSlashCommand = exports.registerCommand = exports.createSlashCommandHandler = exports.SlashCommandHandler = exports.BaseProvider = exports.GoogleProvider = exports.AnthropicProvider = void 0;
59
- exports.getQuickContext = exports.createFastContext = exports.FastContext = exports.triggerN8NWebhook = exports.createN8NIntegration = exports.N8NIntegration = exports.externalAgentAsTool = exports.createExternalAgent = exports.getExternalAgentRegistry = exports.GenericExternalAgent = exports.AiderAgent = exports.CodexCliAgent = exports.GeminiCliAgent = exports.ClaudeCodeAgent = exports.BaseExternalAgent = exports.renderWorkflow = exports.createFlowDisplay = exports.FlowDisplay = exports.createFileCheckpointStorage = void 0;
58
+ exports.JobQueue = exports.cronExpressions = exports.createScheduler = exports.Scheduler = exports.MODE_POLICIES = exports.cliApprovalPrompt = exports.createAutonomyManager = exports.AutonomyManager = exports.DEFAULT_BLOCKED_PATHS = exports.DEFAULT_BLOCKED_COMMANDS = exports.CommandValidator = exports.sandboxExec = exports.createSandboxExecutor = exports.SandboxExecutor = exports.createDiffViewer = exports.DiffViewer = exports.createGitManager = exports.GitManager = exports.DEFAULT_IGNORE_PATTERNS = exports.getRepoTree = exports.createRepoMap = exports.RepoMap = exports.createHistoryManager = exports.HistoryManager = exports.createStatusDisplay = exports.StatusDisplay = exports.createInteractiveTUI = exports.InteractiveTUI = exports.MODEL_PRICING = exports.formatCost = exports.estimateTokens = exports.createCostTracker = exports.CostTracker = exports.isSlashCommand = exports.executeSlashCommand = exports.parseSlashCommand = exports.registerCommand = exports.createSlashCommandHandler = exports.SlashCommandHandler = exports.registerBuiltinProviders = exports.createProviderRegistry = exports.getDefaultRegistry = exports.listProviders = exports.hasProvider = exports.unregisterProvider = exports.registerProvider = exports.ProviderRegistry = exports.BaseProvider = exports.GoogleProvider = exports.AnthropicProvider = void 0;
59
+ exports.getQuickContext = exports.createFastContext = exports.FastContext = exports.triggerN8NWebhook = exports.createN8NIntegration = exports.N8NIntegration = exports.externalAgentAsTool = exports.createExternalAgent = exports.getExternalAgentRegistry = exports.GenericExternalAgent = exports.AiderAgent = exports.CodexCliAgent = exports.GeminiCliAgent = exports.ClaudeCodeAgent = exports.BaseExternalAgent = exports.renderWorkflow = exports.createFlowDisplay = exports.FlowDisplay = exports.createFileCheckpointStorage = exports.FileCheckpointStorage = exports.MemoryCheckpointStorage = exports.createCheckpointManager = exports.CheckpointManager = exports.createFileJobStorage = exports.FileJobStorage = exports.MemoryJobStorage = exports.createJobQueue = void 0;
60
60
  // ============================================================================
61
61
  // CORE API - The main classes users should use
62
62
  // ============================================================================
@@ -294,15 +294,26 @@ Object.defineProperty(exports, "GraphRAG", { enumerable: true, get: function ()
294
294
  Object.defineProperty(exports, "createGraphRAG", { enumerable: true, get: function () { return graph_rag_1.createGraphRAG; } });
295
295
  // Export providers with explicit names to avoid conflicts
296
296
  var providers_1 = require("./llm/providers");
297
+ // Provider factory and utilities
297
298
  Object.defineProperty(exports, "createProvider", { enumerable: true, get: function () { return providers_1.createProvider; } });
298
299
  Object.defineProperty(exports, "getDefaultProvider", { enumerable: true, get: function () { return providers_1.getDefaultProvider; } });
299
300
  Object.defineProperty(exports, "parseModelString", { enumerable: true, get: function () { return providers_1.parseModelString; } });
300
301
  Object.defineProperty(exports, "isProviderAvailable", { enumerable: true, get: function () { return providers_1.isProviderAvailable; } });
301
302
  Object.defineProperty(exports, "getAvailableProviders", { enumerable: true, get: function () { return providers_1.getAvailableProviders; } });
303
+ // Provider classes
302
304
  Object.defineProperty(exports, "OpenAIProvider", { enumerable: true, get: function () { return providers_1.OpenAIProvider; } });
303
305
  Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return providers_1.AnthropicProvider; } });
304
306
  Object.defineProperty(exports, "GoogleProvider", { enumerable: true, get: function () { return providers_1.GoogleProvider; } });
305
307
  Object.defineProperty(exports, "BaseProvider", { enumerable: true, get: function () { return providers_1.BaseProvider; } });
308
+ // Provider registry (extensibility API)
309
+ Object.defineProperty(exports, "ProviderRegistry", { enumerable: true, get: function () { return providers_1.ProviderRegistry; } });
310
+ Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return providers_1.registerProvider; } });
311
+ Object.defineProperty(exports, "unregisterProvider", { enumerable: true, get: function () { return providers_1.unregisterProvider; } });
312
+ Object.defineProperty(exports, "hasProvider", { enumerable: true, get: function () { return providers_1.hasProvider; } });
313
+ Object.defineProperty(exports, "listProviders", { enumerable: true, get: function () { return providers_1.listProviders; } });
314
+ Object.defineProperty(exports, "getDefaultRegistry", { enumerable: true, get: function () { return providers_1.getDefaultRegistry; } });
315
+ Object.defineProperty(exports, "createProviderRegistry", { enumerable: true, get: function () { return providers_1.createProviderRegistry; } });
316
+ Object.defineProperty(exports, "registerBuiltinProviders", { enumerable: true, get: function () { return providers_1.registerBuiltinProviders; } });
306
317
  // Export CLI Features
307
318
  var features_1 = require("./cli/features");
308
319
  // Slash Commands
@@ -33,6 +33,7 @@ export declare class OpenAIService {
33
33
  generateText(prompt: string, systemPrompt?: string, temperature?: number, tools?: ChatCompletionTool[], tool_choice?: ChatCompletionToolChoiceOption): Promise<string>;
34
34
  generateChat(messages: ChatMessage[], temperature?: number, tools?: ChatCompletionTool[], tool_choice?: ChatCompletionToolChoiceOption): Promise<LLMResponse>;
35
35
  streamText(prompt: string, systemPrompt: string | undefined, temperature: number | undefined, onToken: (token: string) => void, tools?: ChatCompletionTool[], tool_choice?: ChatCompletionToolChoiceOption, onToolCall?: (toolCall: any) => void): Promise<void>;
36
+ streamChat(messages: ChatMessage[], temperature: number | undefined, onToken: (token: string) => void): Promise<string>;
36
37
  chatCompletion(messages: ChatMessage[], temperature?: number, tools?: ChatCompletionTool[], tool_choice?: ChatCompletionToolChoiceOption): Promise<LLMResponse>;
37
38
  }
38
39
  export {};
@@ -230,6 +230,36 @@ class OpenAIService {
230
230
  throw error;
231
231
  }
232
232
  }
233
+ async streamChat(messages, temperature = 0.7, onToken) {
234
+ await logger_1.Logger.debug('Starting chat stream with messages...', {
235
+ model: this.model,
236
+ messageCount: messages.length
237
+ });
238
+ try {
239
+ const openAIMessages = messages.map(convertToOpenAIMessage);
240
+ const stream = await this.getClient().then(client => client.chat.completions.create({
241
+ model: this.model,
242
+ temperature,
243
+ messages: openAIMessages,
244
+ stream: true
245
+ }));
246
+ let fullResponse = '';
247
+ for await (const chunk of stream) {
248
+ const delta = chunk.choices[0]?.delta;
249
+ if (delta?.content) {
250
+ const token = delta.content;
251
+ fullResponse += token;
252
+ onToken(token);
253
+ }
254
+ }
255
+ await logger_1.Logger.debug('Chat stream completed');
256
+ return fullResponse;
257
+ }
258
+ catch (error) {
259
+ await logger_1.Logger.error('Error in chat stream', error);
260
+ throw error;
261
+ }
262
+ }
233
263
  async chatCompletion(messages, temperature = 0.7, tools, tool_choice) {
234
264
  await logger_1.Logger.startSpinner('Chat completion with OpenAI...');
235
265
  try {
@@ -1,12 +1,27 @@
1
1
  /**
2
2
  * LLM Providers - Factory and exports for multi-provider support
3
+ *
4
+ * This module provides an extensible provider registry system that allows
5
+ * users to register custom providers (e.g., Cloudflare, Ollama) alongside
6
+ * the built-in providers (OpenAI, Anthropic, Google).
7
+ *
8
+ * @example Register a custom provider
9
+ * ```typescript
10
+ * import { registerProvider, Agent } from 'praisonai';
11
+ * import { CloudflareProvider } from './my-cloudflare-provider';
12
+ *
13
+ * registerProvider('cloudflare', CloudflareProvider);
14
+ * const agent = new Agent({ llm: 'cloudflare/workers-ai' });
15
+ * ```
3
16
  */
4
17
  export * from './types';
5
18
  export * from './base';
6
19
  export { OpenAIProvider } from './openai';
7
20
  export { AnthropicProvider } from './anthropic';
8
21
  export { GoogleProvider } from './google';
22
+ export { ProviderRegistry, ProviderConstructor, ProviderLoader, RegisterOptions, IProviderRegistry, getDefaultRegistry, createProviderRegistry, registerProvider, unregisterProvider, hasProvider, listProviders, registerBuiltinProviders, } from './registry';
9
23
  import type { LLMProvider, ProviderConfig } from './types';
24
+ import type { ProviderRegistry } from './registry';
10
25
  /**
11
26
  * Parse model string into provider and model ID
12
27
  * Supports formats:
@@ -18,17 +33,53 @@ export declare function parseModelString(model: string): {
18
33
  modelId: string;
19
34
  };
20
35
  /**
21
- * Create a provider instance from a model string
36
+ * Input types for createProvider
37
+ */
38
+ export type ProviderInput = string | LLMProvider | {
39
+ name: string;
40
+ modelId?: string;
41
+ config?: ProviderConfig;
42
+ };
43
+ /**
44
+ * Options for createProvider
45
+ */
46
+ export interface CreateProviderOptions {
47
+ /** Override the default registry */
48
+ registry?: ProviderRegistry;
49
+ /** Provider configuration */
50
+ config?: ProviderConfig;
51
+ /** Model ID (used when input is a constructor or spec without modelId) */
52
+ modelId?: string;
53
+ }
54
+ /**
55
+ * Create a provider instance from various input types
22
56
  *
23
- * @example
57
+ * @example String input (backward compatible)
24
58
  * ```typescript
25
59
  * const provider = createProvider('openai/gpt-4o');
26
60
  * const provider = createProvider('anthropic/claude-3-5-sonnet-latest');
27
61
  * const provider = createProvider('google/gemini-2.0-flash');
28
62
  * const provider = createProvider('gpt-4o-mini'); // Defaults to OpenAI
29
63
  * ```
64
+ *
65
+ * @example Custom provider (after registration)
66
+ * ```typescript
67
+ * registerProvider('cloudflare', CloudflareProvider);
68
+ * const provider = createProvider('cloudflare/workers-ai');
69
+ * ```
70
+ *
71
+ * @example Provider instance (pass-through)
72
+ * ```typescript
73
+ * const myProvider = new CustomProvider('model');
74
+ * const provider = createProvider(myProvider); // Returns same instance
75
+ * ```
76
+ *
77
+ * @example Spec object
78
+ * ```typescript
79
+ * const provider = createProvider({ name: 'openai', modelId: 'gpt-4o', config: { timeout: 5000 } });
80
+ * ```
30
81
  */
31
- export declare function createProvider(model: string, config?: ProviderConfig): LLMProvider;
82
+ export declare function createProvider(input: ProviderInput, options?: CreateProviderOptions | ProviderConfig): LLMProvider;
32
83
  /**
33
84
  * Get the default provider (OpenAI with gpt-4o-mini)
34
85
  */
@@ -38,6 +89,6 @@ export declare function getDefaultProvider(config?: ProviderConfig): LLMProvider
38
89
  */
39
90
  export declare function isProviderAvailable(providerId: string): boolean;
40
91
  /**
41
- * Get list of available providers
92
+ * Get list of available providers (registered and with API keys)
42
93
  */
43
94
  export declare function getAvailableProviders(): string[];
@@ -1,6 +1,19 @@
1
1
  "use strict";
2
2
  /**
3
3
  * LLM Providers - Factory and exports for multi-provider support
4
+ *
5
+ * This module provides an extensible provider registry system that allows
6
+ * users to register custom providers (e.g., Cloudflare, Ollama) alongside
7
+ * the built-in providers (OpenAI, Anthropic, Google).
8
+ *
9
+ * @example Register a custom provider
10
+ * ```typescript
11
+ * import { registerProvider, Agent } from 'praisonai';
12
+ * import { CloudflareProvider } from './my-cloudflare-provider';
13
+ *
14
+ * registerProvider('cloudflare', CloudflareProvider);
15
+ * const agent = new Agent({ llm: 'cloudflare/workers-ai' });
16
+ * ```
4
17
  */
5
18
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
19
  if (k2 === undefined) k2 = k;
@@ -17,7 +30,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
30
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
31
  };
19
32
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.GoogleProvider = exports.AnthropicProvider = exports.OpenAIProvider = void 0;
33
+ exports.registerBuiltinProviders = exports.listProviders = exports.hasProvider = exports.unregisterProvider = exports.registerProvider = exports.createProviderRegistry = exports.getDefaultRegistry = exports.ProviderRegistry = exports.GoogleProvider = exports.AnthropicProvider = exports.OpenAIProvider = void 0;
21
34
  exports.parseModelString = parseModelString;
22
35
  exports.createProvider = createProvider;
23
36
  exports.getDefaultProvider = getDefaultProvider;
@@ -31,18 +44,17 @@ var anthropic_1 = require("./anthropic");
31
44
  Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return anthropic_1.AnthropicProvider; } });
32
45
  var google_1 = require("./google");
33
46
  Object.defineProperty(exports, "GoogleProvider", { enumerable: true, get: function () { return google_1.GoogleProvider; } });
34
- const openai_2 = require("./openai");
35
- const anthropic_2 = require("./anthropic");
36
- const google_2 = require("./google");
37
- /**
38
- * Provider registry for dynamic provider loading
39
- */
40
- const PROVIDER_MAP = {
41
- openai: openai_2.OpenAIProvider,
42
- anthropic: anthropic_2.AnthropicProvider,
43
- google: google_2.GoogleProvider,
44
- gemini: google_2.GoogleProvider, // Alias
45
- };
47
+ // Export registry types and functions
48
+ var registry_1 = require("./registry");
49
+ Object.defineProperty(exports, "ProviderRegistry", { enumerable: true, get: function () { return registry_1.ProviderRegistry; } });
50
+ Object.defineProperty(exports, "getDefaultRegistry", { enumerable: true, get: function () { return registry_1.getDefaultRegistry; } });
51
+ Object.defineProperty(exports, "createProviderRegistry", { enumerable: true, get: function () { return registry_1.createProviderRegistry; } });
52
+ Object.defineProperty(exports, "registerProvider", { enumerable: true, get: function () { return registry_1.registerProvider; } });
53
+ Object.defineProperty(exports, "unregisterProvider", { enumerable: true, get: function () { return registry_1.unregisterProvider; } });
54
+ Object.defineProperty(exports, "hasProvider", { enumerable: true, get: function () { return registry_1.hasProvider; } });
55
+ Object.defineProperty(exports, "listProviders", { enumerable: true, get: function () { return registry_1.listProviders; } });
56
+ Object.defineProperty(exports, "registerBuiltinProviders", { enumerable: true, get: function () { return registry_1.registerBuiltinProviders; } });
57
+ const registry_2 = require("./registry");
46
58
  /**
47
59
  * Parse model string into provider and model ID
48
60
  * Supports formats:
@@ -68,23 +80,66 @@ function parseModelString(model) {
68
80
  return { providerId: 'openai', modelId: model };
69
81
  }
70
82
  /**
71
- * Create a provider instance from a model string
83
+ * Create a provider instance from various input types
72
84
  *
73
- * @example
85
+ * @example String input (backward compatible)
74
86
  * ```typescript
75
87
  * const provider = createProvider('openai/gpt-4o');
76
88
  * const provider = createProvider('anthropic/claude-3-5-sonnet-latest');
77
89
  * const provider = createProvider('google/gemini-2.0-flash');
78
90
  * const provider = createProvider('gpt-4o-mini'); // Defaults to OpenAI
79
91
  * ```
92
+ *
93
+ * @example Custom provider (after registration)
94
+ * ```typescript
95
+ * registerProvider('cloudflare', CloudflareProvider);
96
+ * const provider = createProvider('cloudflare/workers-ai');
97
+ * ```
98
+ *
99
+ * @example Provider instance (pass-through)
100
+ * ```typescript
101
+ * const myProvider = new CustomProvider('model');
102
+ * const provider = createProvider(myProvider); // Returns same instance
103
+ * ```
104
+ *
105
+ * @example Spec object
106
+ * ```typescript
107
+ * const provider = createProvider({ name: 'openai', modelId: 'gpt-4o', config: { timeout: 5000 } });
108
+ * ```
80
109
  */
81
- function createProvider(model, config) {
82
- const { providerId, modelId } = parseModelString(model);
83
- const ProviderClass = PROVIDER_MAP[providerId];
84
- if (!ProviderClass) {
85
- throw new Error(`Unknown provider: ${providerId}. Available providers: ${Object.keys(PROVIDER_MAP).join(', ')}`);
110
+ function createProvider(input, options) {
111
+ // Handle legacy signature: createProvider(model, config)
112
+ const opts = options && 'registry' in options
113
+ ? options
114
+ : { config: options };
115
+ const registry = opts.registry || (0, registry_2.getDefaultRegistry)();
116
+ // Case 1: Already a provider instance - pass through
117
+ if (isProviderInstance(input)) {
118
+ return input;
119
+ }
120
+ // Case 2: Spec object
121
+ if (typeof input === 'object' && 'name' in input) {
122
+ const { name, modelId, config } = input;
123
+ return registry.resolve(name, modelId || 'default', config || opts.config);
86
124
  }
87
- return new ProviderClass(modelId, config);
125
+ // Case 3: String - parse and resolve
126
+ if (typeof input === 'string') {
127
+ const { providerId, modelId } = parseModelString(input);
128
+ return registry.resolve(providerId, modelId, opts.config);
129
+ }
130
+ throw new Error(`Invalid provider input. Expected string, provider instance, or spec object. ` +
131
+ `Got: ${typeof input}`);
132
+ }
133
+ /**
134
+ * Type guard to check if value is a provider instance
135
+ */
136
+ function isProviderInstance(value) {
137
+ return (typeof value === 'object' &&
138
+ value !== null &&
139
+ 'providerId' in value &&
140
+ 'modelId' in value &&
141
+ 'generateText' in value &&
142
+ typeof value.generateText === 'function');
88
143
  }
89
144
  /**
90
145
  * Get the default provider (OpenAI with gpt-4o-mini)
@@ -96,21 +151,31 @@ function getDefaultProvider(config) {
96
151
  * Check if a provider is available (has required API key)
97
152
  */
98
153
  function isProviderAvailable(providerId) {
99
- switch (providerId.toLowerCase()) {
154
+ const normalizedId = providerId.toLowerCase();
155
+ // Check if provider is registered
156
+ if (!(0, registry_2.getDefaultRegistry)().has(normalizedId)) {
157
+ return false;
158
+ }
159
+ // Check for API keys based on known providers
160
+ switch (normalizedId) {
100
161
  case 'openai':
162
+ case 'oai':
101
163
  return !!process.env.OPENAI_API_KEY;
102
164
  case 'anthropic':
165
+ case 'claude':
103
166
  return !!process.env.ANTHROPIC_API_KEY;
104
167
  case 'google':
105
168
  case 'gemini':
106
169
  return !!process.env.GOOGLE_API_KEY;
107
170
  default:
108
- return false;
171
+ // For custom providers, assume available if registered
172
+ // Users can override this behavior
173
+ return true;
109
174
  }
110
175
  }
111
176
  /**
112
- * Get list of available providers
177
+ * Get list of available providers (registered and with API keys)
113
178
  */
114
179
  function getAvailableProviders() {
115
- return Object.keys(PROVIDER_MAP).filter(isProviderAvailable);
180
+ return (0, registry_2.getDefaultRegistry)().list().filter(isProviderAvailable);
116
181
  }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Provider Registry - Extensible provider registration system
3
+ *
4
+ * Fixes Issue #1095: Allows users to register custom providers
5
+ * that can be resolved by name via createProvider().
6
+ */
7
+ import type { LLMProvider, ProviderConfig } from './types';
8
+ /**
9
+ * Provider constructor type
10
+ */
11
+ export type ProviderConstructor = new (modelId: string, config?: ProviderConfig) => LLMProvider;
12
+ /**
13
+ * Lazy loader function that returns a provider constructor
14
+ * Used for tree-shaking and lazy loading of provider implementations
15
+ */
16
+ export type ProviderLoader = () => ProviderConstructor;
17
+ /**
18
+ * Options for registering a provider
19
+ */
20
+ export interface RegisterOptions {
21
+ /** Allow overwriting an existing registration */
22
+ override?: boolean;
23
+ /** Additional names that resolve to this provider */
24
+ aliases?: string[];
25
+ }
26
+ /**
27
+ * Provider Registry Interface
28
+ */
29
+ export interface IProviderRegistry {
30
+ register(name: string, provider: ProviderConstructor | ProviderLoader, options?: RegisterOptions): void;
31
+ unregister(name: string): boolean;
32
+ has(name: string): boolean;
33
+ list(): string[];
34
+ resolve(name: string, modelId: string, config?: ProviderConfig): LLMProvider;
35
+ get(name: string): ProviderConstructor | ProviderLoader | undefined;
36
+ }
37
+ /**
38
+ * Provider Registry Implementation
39
+ *
40
+ * Manages registration and resolution of LLM providers by name.
41
+ * Supports lazy loading, aliases, and isolated instances.
42
+ */
43
+ export declare class ProviderRegistry implements IProviderRegistry {
44
+ private entries;
45
+ private aliases;
46
+ /**
47
+ * Register a provider by name
48
+ *
49
+ * @param name - Provider name (e.g., 'cloudflare', 'ollama')
50
+ * @param provider - Provider constructor or lazy loader function
51
+ * @param options - Registration options
52
+ * @throws Error if name is already registered (unless override: true)
53
+ */
54
+ register(name: string, provider: ProviderConstructor | ProviderLoader, options?: RegisterOptions): void;
55
+ /**
56
+ * Unregister a provider by name
57
+ *
58
+ * @param name - Provider name to unregister
59
+ * @returns true if provider was unregistered, false if not found
60
+ */
61
+ unregister(name: string): boolean;
62
+ /**
63
+ * Check if a provider is registered
64
+ *
65
+ * @param name - Provider name to check
66
+ * @returns true if provider is registered
67
+ */
68
+ has(name: string): boolean;
69
+ /**
70
+ * List all registered provider names (canonical names only)
71
+ *
72
+ * @returns Array of provider names
73
+ */
74
+ list(): string[];
75
+ /**
76
+ * List all names including aliases
77
+ *
78
+ * @returns Array of all registered names and aliases
79
+ */
80
+ listAll(): string[];
81
+ /**
82
+ * Resolve a provider by name, creating an instance
83
+ *
84
+ * @param name - Provider name
85
+ * @param modelId - Model ID to pass to constructor
86
+ * @param config - Optional provider config
87
+ * @returns Provider instance
88
+ * @throws Error if provider not found
89
+ */
90
+ resolve(name: string, modelId: string, config?: ProviderConfig): LLMProvider;
91
+ /**
92
+ * Get the provider constructor/loader without instantiating
93
+ *
94
+ * @param name - Provider name
95
+ * @returns Provider constructor/loader or undefined
96
+ */
97
+ get(name: string): ProviderConstructor | ProviderLoader | undefined;
98
+ /**
99
+ * Get the resolved constructor for an entry
100
+ */
101
+ private getConstructor;
102
+ /**
103
+ * Determine if a value is a loader function vs a constructor
104
+ * Loaders are arrow functions or regular functions that return a class
105
+ * Constructors have a prototype with constructor
106
+ */
107
+ private isLoaderFunction;
108
+ }
109
+ /**
110
+ * Get the default global provider registry
111
+ *
112
+ * This is the registry used by createProvider() when no custom registry is specified.
113
+ * Built-in providers (OpenAI, Anthropic, Google) are registered here.
114
+ */
115
+ export declare function getDefaultRegistry(): ProviderRegistry;
116
+ /**
117
+ * Create a new isolated provider registry
118
+ *
119
+ * Use this when you need a separate registry that doesn't share
120
+ * registrations with the default global registry.
121
+ */
122
+ export declare function createProviderRegistry(): ProviderRegistry;
123
+ /**
124
+ * Register a provider to the default global registry
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * import { registerProvider } from 'praisonai';
129
+ * import { CloudflareProvider } from './my-cloudflare-provider';
130
+ *
131
+ * registerProvider('cloudflare', CloudflareProvider);
132
+ *
133
+ * // Now works:
134
+ * const agent = new Agent({ llm: 'cloudflare/workers-ai' });
135
+ * ```
136
+ */
137
+ export declare function registerProvider(name: string, provider: ProviderConstructor | ProviderLoader, options?: RegisterOptions): void;
138
+ /**
139
+ * Unregister a provider from the default global registry
140
+ */
141
+ export declare function unregisterProvider(name: string): boolean;
142
+ /**
143
+ * Check if a provider is registered in the default registry
144
+ */
145
+ export declare function hasProvider(name: string): boolean;
146
+ /**
147
+ * List all providers in the default registry
148
+ */
149
+ export declare function listProviders(): string[];
150
+ /**
151
+ * Register built-in providers to a registry
152
+ * Uses lazy loaders to avoid importing all providers at module load time
153
+ */
154
+ export declare function registerBuiltinProviders(registry: ProviderRegistry): void;
155
+ /**
156
+ * Reset the default registry (mainly for testing)
157
+ * @internal
158
+ */
159
+ export declare function _resetDefaultRegistry(): void;
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ /**
3
+ * Provider Registry - Extensible provider registration system
4
+ *
5
+ * Fixes Issue #1095: Allows users to register custom providers
6
+ * that can be resolved by name via createProvider().
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ProviderRegistry = void 0;
10
+ exports.getDefaultRegistry = getDefaultRegistry;
11
+ exports.createProviderRegistry = createProviderRegistry;
12
+ exports.registerProvider = registerProvider;
13
+ exports.unregisterProvider = unregisterProvider;
14
+ exports.hasProvider = hasProvider;
15
+ exports.listProviders = listProviders;
16
+ exports.registerBuiltinProviders = registerBuiltinProviders;
17
+ exports._resetDefaultRegistry = _resetDefaultRegistry;
18
+ /**
19
+ * Provider Registry Implementation
20
+ *
21
+ * Manages registration and resolution of LLM providers by name.
22
+ * Supports lazy loading, aliases, and isolated instances.
23
+ */
24
+ class ProviderRegistry {
25
+ constructor() {
26
+ this.entries = new Map();
27
+ this.aliases = new Map(); // alias -> canonical name
28
+ }
29
+ /**
30
+ * Register a provider by name
31
+ *
32
+ * @param name - Provider name (e.g., 'cloudflare', 'ollama')
33
+ * @param provider - Provider constructor or lazy loader function
34
+ * @param options - Registration options
35
+ * @throws Error if name is already registered (unless override: true)
36
+ */
37
+ register(name, provider, options = {}) {
38
+ const normalizedName = name.toLowerCase();
39
+ // Check for existing registration
40
+ if (this.entries.has(normalizedName) && !options.override) {
41
+ throw new Error(`Provider '${name}' is already registered. ` +
42
+ `Use { override: true } to replace it.`);
43
+ }
44
+ // Determine if this is a loader function or direct constructor
45
+ const isLoader = this.isLoaderFunction(provider);
46
+ const entry = {
47
+ provider,
48
+ isLoader,
49
+ canonicalName: normalizedName,
50
+ };
51
+ this.entries.set(normalizedName, entry);
52
+ // Register aliases
53
+ if (options.aliases) {
54
+ for (const alias of options.aliases) {
55
+ const normalizedAlias = alias.toLowerCase();
56
+ if (this.entries.has(normalizedAlias) && !options.override) {
57
+ throw new Error(`Alias '${alias}' conflicts with existing provider. ` +
58
+ `Use { override: true } to replace it.`);
59
+ }
60
+ this.aliases.set(normalizedAlias, normalizedName);
61
+ }
62
+ }
63
+ }
64
+ /**
65
+ * Unregister a provider by name
66
+ *
67
+ * @param name - Provider name to unregister
68
+ * @returns true if provider was unregistered, false if not found
69
+ */
70
+ unregister(name) {
71
+ const normalizedName = name.toLowerCase();
72
+ // Check if it's an alias
73
+ if (this.aliases.has(normalizedName)) {
74
+ this.aliases.delete(normalizedName);
75
+ return true;
76
+ }
77
+ // Check if it's a canonical name
78
+ if (this.entries.has(normalizedName)) {
79
+ // Remove all aliases pointing to this provider
80
+ for (const [alias, canonical] of this.aliases.entries()) {
81
+ if (canonical === normalizedName) {
82
+ this.aliases.delete(alias);
83
+ }
84
+ }
85
+ this.entries.delete(normalizedName);
86
+ return true;
87
+ }
88
+ return false;
89
+ }
90
+ /**
91
+ * Check if a provider is registered
92
+ *
93
+ * @param name - Provider name to check
94
+ * @returns true if provider is registered
95
+ */
96
+ has(name) {
97
+ const normalizedName = name.toLowerCase();
98
+ return this.entries.has(normalizedName) || this.aliases.has(normalizedName);
99
+ }
100
+ /**
101
+ * List all registered provider names (canonical names only)
102
+ *
103
+ * @returns Array of provider names
104
+ */
105
+ list() {
106
+ return Array.from(this.entries.keys());
107
+ }
108
+ /**
109
+ * List all names including aliases
110
+ *
111
+ * @returns Array of all registered names and aliases
112
+ */
113
+ listAll() {
114
+ return [...this.entries.keys(), ...this.aliases.keys()];
115
+ }
116
+ /**
117
+ * Resolve a provider by name, creating an instance
118
+ *
119
+ * @param name - Provider name
120
+ * @param modelId - Model ID to pass to constructor
121
+ * @param config - Optional provider config
122
+ * @returns Provider instance
123
+ * @throws Error if provider not found
124
+ */
125
+ resolve(name, modelId, config) {
126
+ const normalizedName = name.toLowerCase();
127
+ // Resolve alias to canonical name
128
+ const canonicalName = this.aliases.get(normalizedName) || normalizedName;
129
+ const entry = this.entries.get(canonicalName);
130
+ if (!entry) {
131
+ const available = this.list();
132
+ throw new Error(`Unknown provider: '${name}'. ` +
133
+ `Available providers: ${available.length > 0 ? available.join(', ') : 'none'}. ` +
134
+ `Register a custom provider with registerProvider('${name}', YourProviderClass).`);
135
+ }
136
+ // Get constructor (resolve loader if needed)
137
+ const Constructor = this.getConstructor(entry);
138
+ return new Constructor(modelId, config);
139
+ }
140
+ /**
141
+ * Get the provider constructor/loader without instantiating
142
+ *
143
+ * @param name - Provider name
144
+ * @returns Provider constructor/loader or undefined
145
+ */
146
+ get(name) {
147
+ const normalizedName = name.toLowerCase();
148
+ const canonicalName = this.aliases.get(normalizedName) || normalizedName;
149
+ return this.entries.get(canonicalName)?.provider;
150
+ }
151
+ /**
152
+ * Get the resolved constructor for an entry
153
+ */
154
+ getConstructor(entry) {
155
+ if (!entry.isLoader) {
156
+ return entry.provider;
157
+ }
158
+ // Lazy load and cache
159
+ if (!entry.cachedConstructor) {
160
+ const loader = entry.provider;
161
+ entry.cachedConstructor = loader();
162
+ }
163
+ return entry.cachedConstructor;
164
+ }
165
+ /**
166
+ * Determine if a value is a loader function vs a constructor
167
+ * Loaders are arrow functions or regular functions that return a class
168
+ * Constructors have a prototype with constructor
169
+ */
170
+ isLoaderFunction(value) {
171
+ // If it has a prototype with more than just constructor, it's likely a class
172
+ if (value.prototype && Object.getOwnPropertyNames(value.prototype).length > 1) {
173
+ return false;
174
+ }
175
+ // Check if it looks like a class (has 'prototype' that is an object with constructor)
176
+ if (value.prototype && value.prototype.constructor === value) {
177
+ // Additional check: classes typically have a name and their toString starts with 'class'
178
+ const str = value.toString();
179
+ if (str.startsWith('class ') || str.includes('function ')) {
180
+ return false;
181
+ }
182
+ }
183
+ // Arrow functions and simple functions are loaders
184
+ return typeof value === 'function' && !value.prototype?.constructor;
185
+ }
186
+ }
187
+ exports.ProviderRegistry = ProviderRegistry;
188
+ // ============================================================================
189
+ // Default Registry Singleton
190
+ // ============================================================================
191
+ let defaultRegistry = null;
192
+ /**
193
+ * Get the default global provider registry
194
+ *
195
+ * This is the registry used by createProvider() when no custom registry is specified.
196
+ * Built-in providers (OpenAI, Anthropic, Google) are registered here.
197
+ */
198
+ function getDefaultRegistry() {
199
+ if (!defaultRegistry) {
200
+ defaultRegistry = new ProviderRegistry();
201
+ registerBuiltinProviders(defaultRegistry);
202
+ }
203
+ return defaultRegistry;
204
+ }
205
+ /**
206
+ * Create a new isolated provider registry
207
+ *
208
+ * Use this when you need a separate registry that doesn't share
209
+ * registrations with the default global registry.
210
+ */
211
+ function createProviderRegistry() {
212
+ return new ProviderRegistry();
213
+ }
214
+ /**
215
+ * Register a provider to the default global registry
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * import { registerProvider } from 'praisonai';
220
+ * import { CloudflareProvider } from './my-cloudflare-provider';
221
+ *
222
+ * registerProvider('cloudflare', CloudflareProvider);
223
+ *
224
+ * // Now works:
225
+ * const agent = new Agent({ llm: 'cloudflare/workers-ai' });
226
+ * ```
227
+ */
228
+ function registerProvider(name, provider, options) {
229
+ getDefaultRegistry().register(name, provider, options);
230
+ }
231
+ /**
232
+ * Unregister a provider from the default global registry
233
+ */
234
+ function unregisterProvider(name) {
235
+ return getDefaultRegistry().unregister(name);
236
+ }
237
+ /**
238
+ * Check if a provider is registered in the default registry
239
+ */
240
+ function hasProvider(name) {
241
+ return getDefaultRegistry().has(name);
242
+ }
243
+ /**
244
+ * List all providers in the default registry
245
+ */
246
+ function listProviders() {
247
+ return getDefaultRegistry().list();
248
+ }
249
+ // ============================================================================
250
+ // Built-in Provider Registration
251
+ // ============================================================================
252
+ /**
253
+ * Register built-in providers to a registry
254
+ * Uses lazy loaders to avoid importing all providers at module load time
255
+ */
256
+ function registerBuiltinProviders(registry) {
257
+ // OpenAI - lazy loaded
258
+ registry.register('openai', () => {
259
+ const { OpenAIProvider } = require('./openai');
260
+ return OpenAIProvider;
261
+ }, { aliases: ['oai'] });
262
+ // Anthropic - lazy loaded
263
+ registry.register('anthropic', () => {
264
+ const { AnthropicProvider } = require('./anthropic');
265
+ return AnthropicProvider;
266
+ }, { aliases: ['claude'] });
267
+ // Google - lazy loaded
268
+ registry.register('google', () => {
269
+ const { GoogleProvider } = require('./google');
270
+ return GoogleProvider;
271
+ }, { aliases: ['gemini'] });
272
+ }
273
+ /**
274
+ * Reset the default registry (mainly for testing)
275
+ * @internal
276
+ */
277
+ function _resetDefaultRegistry() {
278
+ defaultRegistry = null;
279
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praisonai",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "PraisonAI TypeScript AI Agents Framework - Node.js, npm, and Javascript AI Agents Framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",