@defai.digital/agent-domain 13.0.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.
Files changed (77) hide show
  1. package/LICENSE +214 -0
  2. package/dist/enhanced-executor.d.ts +170 -0
  3. package/dist/enhanced-executor.d.ts.map +1 -0
  4. package/dist/enhanced-executor.js +1072 -0
  5. package/dist/enhanced-executor.js.map +1 -0
  6. package/dist/executor.d.ts +120 -0
  7. package/dist/executor.d.ts.map +1 -0
  8. package/dist/executor.js +929 -0
  9. package/dist/executor.js.map +1 -0
  10. package/dist/index.d.ts +25 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +34 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/loader.d.ts +50 -0
  15. package/dist/loader.d.ts.map +1 -0
  16. package/dist/loader.js +160 -0
  17. package/dist/loader.js.map +1 -0
  18. package/dist/persistent-registry.d.ts +105 -0
  19. package/dist/persistent-registry.d.ts.map +1 -0
  20. package/dist/persistent-registry.js +183 -0
  21. package/dist/persistent-registry.js.map +1 -0
  22. package/dist/production-factories.d.ts +70 -0
  23. package/dist/production-factories.d.ts.map +1 -0
  24. package/dist/production-factories.js +434 -0
  25. package/dist/production-factories.js.map +1 -0
  26. package/dist/prompt-executor.d.ts +119 -0
  27. package/dist/prompt-executor.d.ts.map +1 -0
  28. package/dist/prompt-executor.js +211 -0
  29. package/dist/prompt-executor.js.map +1 -0
  30. package/dist/registry.d.ts +57 -0
  31. package/dist/registry.d.ts.map +1 -0
  32. package/dist/registry.js +123 -0
  33. package/dist/registry.js.map +1 -0
  34. package/dist/selection-service.d.ts +74 -0
  35. package/dist/selection-service.d.ts.map +1 -0
  36. package/dist/selection-service.js +322 -0
  37. package/dist/selection-service.js.map +1 -0
  38. package/dist/selector.d.ts +51 -0
  39. package/dist/selector.d.ts.map +1 -0
  40. package/dist/selector.js +249 -0
  41. package/dist/selector.js.map +1 -0
  42. package/dist/stub-checkpoint.d.ts +23 -0
  43. package/dist/stub-checkpoint.d.ts.map +1 -0
  44. package/dist/stub-checkpoint.js +137 -0
  45. package/dist/stub-checkpoint.js.map +1 -0
  46. package/dist/stub-delegation-tracker.d.ts +25 -0
  47. package/dist/stub-delegation-tracker.d.ts.map +1 -0
  48. package/dist/stub-delegation-tracker.js +118 -0
  49. package/dist/stub-delegation-tracker.js.map +1 -0
  50. package/dist/stub-parallel-executor.d.ts +19 -0
  51. package/dist/stub-parallel-executor.d.ts.map +1 -0
  52. package/dist/stub-parallel-executor.js +176 -0
  53. package/dist/stub-parallel-executor.js.map +1 -0
  54. package/dist/types.d.ts +614 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +15 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/workflow-templates.d.ts +117 -0
  59. package/dist/workflow-templates.d.ts.map +1 -0
  60. package/dist/workflow-templates.js +342 -0
  61. package/dist/workflow-templates.js.map +1 -0
  62. package/package.json +51 -0
  63. package/src/enhanced-executor.ts +1395 -0
  64. package/src/executor.ts +1153 -0
  65. package/src/index.ts +172 -0
  66. package/src/loader.ts +191 -0
  67. package/src/persistent-registry.ts +235 -0
  68. package/src/production-factories.ts +613 -0
  69. package/src/prompt-executor.ts +310 -0
  70. package/src/registry.ts +167 -0
  71. package/src/selection-service.ts +411 -0
  72. package/src/selector.ts +299 -0
  73. package/src/stub-checkpoint.ts +187 -0
  74. package/src/stub-delegation-tracker.ts +161 -0
  75. package/src/stub-parallel-executor.ts +224 -0
  76. package/src/types.ts +784 -0
  77. package/src/workflow-templates.ts +393 -0
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Prompt Executor Implementation
3
+ *
4
+ * Bridges the agent domain with LLM providers for real prompt execution.
5
+ * This file provides both a stub executor for testing and a factory
6
+ * for creating real executors with provider integration.
7
+ */
8
+
9
+ import type {
10
+ PromptExecutor,
11
+ PromptExecutionRequest,
12
+ PromptExecutionResponse,
13
+ } from './types.js';
14
+
15
+ /**
16
+ * Stub prompt executor for testing and development
17
+ * Returns mock responses without calling real providers
18
+ *
19
+ * WARNING: This executor returns fake responses. For production use,
20
+ * inject a real PromptExecutor via config.promptExecutor.
21
+ */
22
+ export class StubPromptExecutor implements PromptExecutor {
23
+ private readonly defaultProvider: string;
24
+ private hasWarnedOnce = false;
25
+
26
+ constructor(defaultProvider = 'claude') {
27
+ this.defaultProvider = defaultProvider;
28
+ }
29
+
30
+ async execute(request: PromptExecutionRequest): Promise<PromptExecutionResponse> {
31
+ // Warn once on first use (not on every call to avoid log spam)
32
+ if (!this.hasWarnedOnce) {
33
+ console.warn(
34
+ '[WARN] StubPromptExecutor: Using mock responses. ' +
35
+ 'For production, inject a real PromptExecutor via config.promptExecutor.'
36
+ );
37
+ this.hasWarnedOnce = true;
38
+ }
39
+
40
+ const startTime = Date.now();
41
+
42
+ // Simulate some processing time
43
+ await new Promise((resolve) => setTimeout(resolve, 10));
44
+
45
+ return {
46
+ success: true,
47
+ content: `[Stub Response] This is a mock response for prompt: "${request.prompt.substring(0, 100)}..."`,
48
+ provider: request.provider ?? this.defaultProvider,
49
+ model: request.model ?? 'stub-model',
50
+ latencyMs: Date.now() - startTime,
51
+ usage: {
52
+ inputTokens: Math.ceil(request.prompt.length / 4),
53
+ outputTokens: 50,
54
+ totalTokens: Math.ceil(request.prompt.length / 4) + 50,
55
+ },
56
+ };
57
+ }
58
+
59
+ async isProviderAvailable(_providerId: string): Promise<boolean> {
60
+ return true;
61
+ }
62
+
63
+ async getAvailableProviders(): Promise<string[]> {
64
+ return [this.defaultProvider];
65
+ }
66
+
67
+ getDefaultProvider(): string {
68
+ return this.defaultProvider;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Provider-based prompt executor configuration
74
+ */
75
+ export interface ProviderPromptExecutorConfig {
76
+ /**
77
+ * Default provider to use when none specified
78
+ */
79
+ defaultProvider: string;
80
+
81
+ /**
82
+ * Default model to use when none specified (per provider)
83
+ */
84
+ defaultModels?: Record<string, string>;
85
+
86
+ /**
87
+ * Default timeout in milliseconds
88
+ */
89
+ defaultTimeout?: number;
90
+ }
91
+
92
+ /**
93
+ * Interface that matches the provider registry from @defai.digital/providers
94
+ * This allows loose coupling without direct dependency
95
+ */
96
+ export interface ProviderRegistryLike {
97
+ get(providerId: string): ProviderLike | undefined;
98
+ getProviderIds(): string[];
99
+ }
100
+
101
+ /**
102
+ * Interface that matches a provider from @defai.digital/providers
103
+ */
104
+ export interface ProviderLike {
105
+ providerId: string;
106
+ complete(request: {
107
+ requestId: string;
108
+ model: string;
109
+ messages: { role: 'user' | 'assistant' | 'system'; content: string }[];
110
+ systemPrompt?: string;
111
+ maxTokens?: number;
112
+ temperature?: number;
113
+ timeout?: number;
114
+ }): Promise<{
115
+ success: boolean;
116
+ content?: string;
117
+ error?: { message: string; category: string };
118
+ latencyMs: number;
119
+ usage?: { inputTokens: number; outputTokens: number; totalTokens: number };
120
+ model?: string;
121
+ }>;
122
+ isAvailable(): Promise<boolean>;
123
+ getModels(): readonly { modelId: string; isDefault?: boolean | undefined }[];
124
+ }
125
+
126
+ /**
127
+ * Real prompt executor that uses the provider registry
128
+ */
129
+ export class ProviderPromptExecutor implements PromptExecutor {
130
+ private readonly registry: ProviderRegistryLike;
131
+ private readonly config: ProviderPromptExecutorConfig;
132
+
133
+ constructor(registry: ProviderRegistryLike, config: ProviderPromptExecutorConfig) {
134
+ this.registry = registry;
135
+ this.config = config;
136
+ }
137
+
138
+ async execute(request: PromptExecutionRequest): Promise<PromptExecutionResponse> {
139
+ const startTime = Date.now();
140
+ const providerId = request.provider ?? this.config.defaultProvider;
141
+
142
+ // Get the provider
143
+ const provider = this.registry.get(providerId);
144
+ if (provider === undefined) {
145
+ return {
146
+ success: false,
147
+ error: `Provider "${providerId}" not found`,
148
+ errorCode: 'PROVIDER_NOT_FOUND',
149
+ latencyMs: Date.now() - startTime,
150
+ };
151
+ }
152
+
153
+ // Check if provider is available
154
+ const isAvailable = await provider.isAvailable();
155
+ if (!isAvailable) {
156
+ return {
157
+ success: false,
158
+ error: `Provider "${providerId}" is not available (CLI not installed or not in PATH)`,
159
+ errorCode: 'PROVIDER_UNAVAILABLE',
160
+ provider: providerId,
161
+ latencyMs: Date.now() - startTime,
162
+ };
163
+ }
164
+
165
+ // Determine model to use
166
+ let model = request.model;
167
+ if (!model) {
168
+ // Use configured default for this provider, or provider's default model
169
+ model = this.config.defaultModels?.[providerId];
170
+ if (!model) {
171
+ const models = provider.getModels();
172
+ const defaultModel = models.find((m) => m.isDefault) ?? models[0];
173
+ model = defaultModel?.modelId;
174
+ }
175
+ }
176
+
177
+ if (!model) {
178
+ return {
179
+ success: false,
180
+ error: `No model specified and no default model available for provider "${providerId}"`,
181
+ errorCode: 'NO_MODEL',
182
+ provider: providerId,
183
+ latencyMs: Date.now() - startTime,
184
+ };
185
+ }
186
+
187
+ try {
188
+ // Build completion request with only defined properties
189
+ const completionRequest: {
190
+ requestId: string;
191
+ model: string;
192
+ messages: { role: 'user' | 'assistant' | 'system'; content: string }[];
193
+ systemPrompt?: string;
194
+ maxTokens?: number;
195
+ temperature?: number;
196
+ timeout?: number;
197
+ } = {
198
+ requestId: crypto.randomUUID(),
199
+ model,
200
+ messages: [{ role: 'user', content: request.prompt }],
201
+ };
202
+
203
+ if (request.systemPrompt !== undefined) {
204
+ completionRequest.systemPrompt = request.systemPrompt;
205
+ }
206
+ if (request.maxTokens !== undefined) {
207
+ completionRequest.maxTokens = request.maxTokens;
208
+ }
209
+ if (request.temperature !== undefined) {
210
+ completionRequest.temperature = request.temperature;
211
+ }
212
+ const timeout = request.timeout ?? this.config.defaultTimeout;
213
+ if (timeout !== undefined) {
214
+ completionRequest.timeout = timeout;
215
+ }
216
+
217
+ // Execute the completion
218
+ const response = await provider.complete(completionRequest);
219
+
220
+ if (response.success) {
221
+ return {
222
+ success: true,
223
+ content: response.content,
224
+ provider: providerId,
225
+ model: response.model ?? model,
226
+ latencyMs: response.latencyMs,
227
+ usage: response.usage,
228
+ };
229
+ } else {
230
+ return {
231
+ success: false,
232
+ error: response.error?.message ?? 'Unknown error',
233
+ errorCode: response.error?.category ?? 'UNKNOWN',
234
+ provider: providerId,
235
+ model,
236
+ latencyMs: response.latencyMs,
237
+ };
238
+ }
239
+ } catch (error) {
240
+ return {
241
+ success: false,
242
+ error: error instanceof Error ? error.message : 'Unknown error',
243
+ errorCode: 'EXECUTION_ERROR',
244
+ provider: providerId,
245
+ model,
246
+ latencyMs: Date.now() - startTime,
247
+ };
248
+ }
249
+ }
250
+
251
+ async isProviderAvailable(providerId: string): Promise<boolean> {
252
+ const provider = this.registry.get(providerId);
253
+ if (provider === undefined) {
254
+ return false;
255
+ }
256
+ return provider.isAvailable();
257
+ }
258
+
259
+ async getAvailableProviders(): Promise<string[]> {
260
+ const providerIds = this.registry.getProviderIds();
261
+ const available: string[] = [];
262
+
263
+ for (const providerId of providerIds) {
264
+ const provider = this.registry.get(providerId);
265
+ if (provider !== undefined) {
266
+ const isAvailable = await provider.isAvailable();
267
+ if (isAvailable) {
268
+ available.push(providerId);
269
+ }
270
+ }
271
+ }
272
+
273
+ return available;
274
+ }
275
+
276
+ getDefaultProvider(): string {
277
+ return this.config.defaultProvider;
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Creates a stub prompt executor for testing
283
+ */
284
+ export function createStubPromptExecutor(
285
+ defaultProvider = 'claude'
286
+ ): PromptExecutor {
287
+ return new StubPromptExecutor(defaultProvider);
288
+ }
289
+
290
+ /**
291
+ * Creates a real prompt executor using a provider registry
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * import { createProviderRegistry } from '@defai.digital/providers';
296
+ * import { createProviderPromptExecutor } from '@defai.digital/agent-domain';
297
+ *
298
+ * const registry = createProviderRegistry();
299
+ * const executor = createProviderPromptExecutor(registry, {
300
+ * defaultProvider: 'claude',
301
+ * defaultTimeout: 120000,
302
+ * });
303
+ * ```
304
+ */
305
+ export function createProviderPromptExecutor(
306
+ registry: ProviderRegistryLike,
307
+ config: ProviderPromptExecutorConfig
308
+ ): PromptExecutor {
309
+ return new ProviderPromptExecutor(registry, config);
310
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Agent Registry Implementation
3
+ *
4
+ * Manages agent profile registration, lookup, and lifecycle.
5
+ */
6
+
7
+ import {
8
+ type AgentProfile,
9
+ validateAgentProfile,
10
+ AgentErrorCode,
11
+ } from '@defai.digital/contracts';
12
+ import type { AgentRegistry, AgentFilter } from './types.js';
13
+
14
+ /**
15
+ * In-memory agent registry implementation
16
+ */
17
+ export class InMemoryAgentRegistry implements AgentRegistry {
18
+ private readonly agents = new Map<string, AgentProfile>();
19
+
20
+ /**
21
+ * Register a new agent profile
22
+ */
23
+ async register(profile: AgentProfile): Promise<void> {
24
+ // Validate the profile
25
+ const validated = validateAgentProfile(profile);
26
+
27
+ // Check for duplicate
28
+ if (this.agents.has(validated.agentId)) {
29
+ throw new AgentRegistryError(
30
+ AgentErrorCode.AGENT_VALIDATION_ERROR,
31
+ `Agent with ID "${validated.agentId}" already exists`
32
+ );
33
+ }
34
+
35
+ // Add timestamps
36
+ const now = new Date().toISOString();
37
+ const withTimestamps: AgentProfile = {
38
+ ...validated,
39
+ createdAt: now,
40
+ updatedAt: now,
41
+ };
42
+
43
+ this.agents.set(validated.agentId, withTimestamps);
44
+ }
45
+
46
+ /**
47
+ * Get an agent by ID
48
+ */
49
+ async get(agentId: string): Promise<AgentProfile | undefined> {
50
+ return this.agents.get(agentId);
51
+ }
52
+
53
+ /**
54
+ * List all registered agents with optional filtering
55
+ */
56
+ async list(filter?: AgentFilter): Promise<AgentProfile[]> {
57
+ let agents = Array.from(this.agents.values());
58
+
59
+ if (filter !== undefined) {
60
+ if (filter.team !== undefined) {
61
+ agents = agents.filter((a) => a.team === filter.team);
62
+ }
63
+
64
+ if (filter.tags !== undefined && filter.tags.length > 0) {
65
+ agents = agents.filter(
66
+ (a) =>
67
+ a.tags !== undefined &&
68
+ filter.tags!.some((tag) => a.tags!.includes(tag))
69
+ );
70
+ }
71
+
72
+ if (filter.enabled !== undefined) {
73
+ agents = agents.filter((a) => a.enabled === filter.enabled);
74
+ }
75
+
76
+ if (filter.capability !== undefined) {
77
+ agents = agents.filter(
78
+ (a) =>
79
+ a.capabilities !== undefined &&
80
+ a.capabilities.includes(filter.capability!)
81
+ );
82
+ }
83
+ }
84
+
85
+ return agents;
86
+ }
87
+
88
+ /**
89
+ * Update an agent profile
90
+ */
91
+ async update(agentId: string, updates: Partial<AgentProfile>): Promise<void> {
92
+ const existing = this.agents.get(agentId);
93
+
94
+ if (existing === undefined) {
95
+ throw new AgentRegistryError(
96
+ AgentErrorCode.AGENT_NOT_FOUND,
97
+ `Agent with ID "${agentId}" not found`
98
+ );
99
+ }
100
+
101
+ // Merge and validate
102
+ const merged = {
103
+ ...existing,
104
+ ...updates,
105
+ agentId, // Cannot change ID
106
+ updatedAt: new Date().toISOString(),
107
+ };
108
+
109
+ const validated = validateAgentProfile(merged);
110
+ this.agents.set(agentId, validated);
111
+ }
112
+
113
+ /**
114
+ * Remove an agent
115
+ */
116
+ async remove(agentId: string): Promise<void> {
117
+ if (!this.agents.has(agentId)) {
118
+ throw new AgentRegistryError(
119
+ AgentErrorCode.AGENT_NOT_FOUND,
120
+ `Agent with ID "${agentId}" not found`
121
+ );
122
+ }
123
+
124
+ this.agents.delete(agentId);
125
+ }
126
+
127
+ /**
128
+ * Check if an agent exists
129
+ */
130
+ async exists(agentId: string): Promise<boolean> {
131
+ return this.agents.has(agentId);
132
+ }
133
+
134
+ /**
135
+ * Clear all agents (useful for testing)
136
+ */
137
+ clear(): void {
138
+ this.agents.clear();
139
+ }
140
+
141
+ /**
142
+ * Get the count of registered agents
143
+ */
144
+ get size(): number {
145
+ return this.agents.size;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Agent registry error
151
+ */
152
+ export class AgentRegistryError extends Error {
153
+ constructor(
154
+ public readonly code: string,
155
+ message: string
156
+ ) {
157
+ super(message);
158
+ this.name = 'AgentRegistryError';
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Creates a new in-memory agent registry
164
+ */
165
+ export function createAgentRegistry(): AgentRegistry {
166
+ return new InMemoryAgentRegistry();
167
+ }