@exellix/ai-tasks 8.4.1 → 8.4.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 (95) hide show
  1. package/.docs/DOWNSTREAM_ENV.md +42 -0
  2. package/.docs/FEEDBACK_TO_CLIENT_DOWNSTREAM_FIXES.md +64 -0
  3. package/.docs/INTERMEDIATE_STEPS.md +82 -0
  4. package/.docs/activity-structure.md +31 -0
  5. package/.docs/ai-task-ai-scoping-spec.md +338 -0
  6. package/.docs/ai-tasks-model-profile-aliases-7x.md +74 -0
  7. package/.docs/blockers-and-issues.md +346 -0
  8. package/.docs/building-runTask-sdk.md +659 -0
  9. package/.docs/building-skill-execution-orchestrator.md +968 -0
  10. package/.docs/code-used-before/run-task.txt +39 -0
  11. package/.docs/code-used-before/task-executor.ts.old +57 -0
  12. package/.docs/code-used-before/test-run-task.ts.old +42 -0
  13. package/.docs/code-used-before/types.txt +23 -0
  14. package/.docs/env-ready-policy.md +40 -0
  15. package/.docs/flow-io/flow-README.md +76 -0
  16. package/.docs/flow-io/narrix.md +124 -0
  17. package/.docs/flow-io/web-scoping.md +135 -0
  18. package/.docs/flow-io/xynthesis-post.md +154 -0
  19. package/.docs/flow-io/xynthesis-pre.md +181 -0
  20. package/.docs/gap-analysis.md +201 -0
  21. package/.docs/integration-facts-ai-tasks.md +109 -0
  22. package/.docs/investigation/ai-skills.md +170 -0
  23. package/.docs/investigation/external-packages-assignments.md +66 -0
  24. package/.docs/investigation/integration-summary.md +20 -0
  25. package/.docs/investigation/narrix-catalox.md +29 -0
  26. package/.docs/investigation/workplan-close-graph-engine-gaps.md +101 -0
  27. package/.docs/logging-stack.md +30 -0
  28. package/.docs/memory-narrix-adapter-developer-guide.md +402 -0
  29. package/.docs/memory-narrix-adapter-requirements.md +112 -0
  30. package/.docs/narrix-context-consumption-gap.md +184 -0
  31. package/.docs/narrix-context-downstream-report.md +30 -0
  32. package/.docs/narrix-ingest-and-packs-library-spec.md +240 -0
  33. package/.docs/narrix-record-input-current-design.md +48 -0
  34. package/.docs/pacakge.md +48 -0
  35. package/.docs/possible-components/README.md +11 -0
  36. package/.docs/possible-components/integration/README.md +10 -0
  37. package/.docs/possible-components/integration/gaps-when-merging.md +16 -0
  38. package/.docs/possible-components/integration/platform.md +54 -0
  39. package/.docs/possible-components/integration/reintegrate-into-ai-tasks.md +26 -0
  40. package/.docs/possible-components/integration/roadmap-and-checklists.md +54 -0
  41. package/.docs/possible-components/post-component/README.md +18 -0
  42. package/.docs/possible-components/post-component/builder-guide.md +175 -0
  43. package/.docs/possible-components/post-component/gaps-and-artifacts.md +52 -0
  44. package/.docs/possible-components/post-component/handler-audit.md +47 -0
  45. package/.docs/possible-components/post-component/handler-polish.md +41 -0
  46. package/.docs/possible-components/post-component/unified-protocol.md +59 -0
  47. package/.docs/possible-components/pre-component/README.md +22 -0
  48. package/.docs/possible-components/pre-component/builder-guide.md +127 -0
  49. package/.docs/possible-components/pre-component/gaps-and-artifacts.md +35 -0
  50. package/.docs/possible-components/pre-component/handler-ai-scoping.md +45 -0
  51. package/.docs/possible-components/pre-component/handler-narrix-preprocessor.md +49 -0
  52. package/.docs/possible-components/pre-component/handler-narrix-system2.md +35 -0
  53. package/.docs/possible-components/pre-component/handler-synthesized-context.md +65 -0
  54. package/.docs/possible-components/pre-component/handler-web-scope.md +29 -0
  55. package/.docs/possible-components/pre-component/unified-protocol.md +89 -0
  56. package/.docs/prefer-openrouter-routing-policy.md +132 -0
  57. package/.docs/questions-for-ai-skills.md +123 -0
  58. package/.docs/realtime-narrixing-gap-analysis.md +40 -0
  59. package/.docs/realtime-narrixing.md +433 -0
  60. package/.docs/run-context-object.md +32 -0
  61. package/.docs/session-id-usage.md +26 -0
  62. package/.docs/skill-library-spec.md +249 -0
  63. package/.docs/synthesized-context-strategy-spec.md +906 -0
  64. package/.docs/upstream-issue/2026-03-21_woroces-ai-tasks_ISSUE-006_web-scope-question-from-cni-entity.md +46 -0
  65. package/.docs/web-scopper-embed.md +93 -0
  66. package/.docs/xynthesis-wiring-and-io.md +12 -0
  67. package/README.md +15 -13
  68. package/dist/index.d.ts +2 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +1 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/internal/runPostStepLlmCall.d.ts.map +1 -1
  73. package/dist/internal/runPostStepLlmCall.js +4 -2
  74. package/dist/internal/runPostStepLlmCall.js.map +1 -1
  75. package/dist/invocation/resolveProfileInvocationRouting.js +2 -2
  76. package/dist/invocation/resolveProfileInvocationRouting.js.map +1 -1
  77. package/dist/utils/aiProfileModelFormat.d.ts +2 -2
  78. package/dist/utils/aiProfileModelFormat.js +2 -2
  79. package/dist/utils/aiProfilesCatalog.d.ts +16 -0
  80. package/dist/utils/aiProfilesCatalog.d.ts.map +1 -0
  81. package/dist/utils/aiProfilesCatalog.js +23 -0
  82. package/dist/utils/aiProfilesCatalog.js.map +1 -0
  83. package/dist/utils/resolveAiProfileModel.d.ts +2 -2
  84. package/dist/utils/resolveAiProfileModel.d.ts.map +1 -1
  85. package/dist/utils/resolveAiProfileModel.js +5 -5
  86. package/dist/utils/resolveAiProfileModel.js.map +1 -1
  87. package/dist/utils/routeModelConfigSlots.d.ts +3 -1
  88. package/dist/utils/routeModelConfigSlots.d.ts.map +1 -1
  89. package/dist/utils/routeModelConfigSlots.js +2 -1
  90. package/dist/utils/routeModelConfigSlots.js.map +1 -1
  91. package/documenations/upstream-feature-requests/README.md +2 -1
  92. package/documenations/upstream-feature-requests/ai-tasks-wrap-up-after-upstream.md +7 -4
  93. package/documenations/upstream-feature-requests/xynthesis-ai-profiles-2.1-import-break.md +324 -0
  94. package/documenations/upstream-feature-requests/xynthesis-orchestrator-invoke-contract-4.2.md +6 -4
  95. package/package.json +3 -2
@@ -0,0 +1,968 @@
1
+ # Building an External Package for Skill Execution Orchestration
2
+
3
+ This guide explains how to create an external package that uses `@woroces/ai-skills`'s `runTask` method to orchestrate skill execution with different execution strategies. This package will handle running skills, manage execution strategies, coordinate workflows, and provide a higher-level API for task orchestration.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Overview](#overview)
8
+ 2. [Architecture](#architecture)
9
+ 3. [Prerequisites](#prerequisites)
10
+ 4. [Project Setup](#project-setup)
11
+ 5. [Core Components](#core-components)
12
+ 6. [Execution Strategy System](#execution-strategy-system)
13
+ 7. [Skill Execution Manager](#skill-execution-manager)
14
+ 8. [Workflow Orchestration](#workflow-orchestration)
15
+ 9. [Complete Implementation](#complete-implementation)
16
+ 10. [Usage Examples](#usage-examples)
17
+ 11. [Advanced Features](#advanced-features)
18
+ 12. [Testing](#testing)
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ ### What This Package Does
25
+
26
+ This external package provides:
27
+
28
+ - **Skill Execution Orchestration**: Manages the execution of skills using `runTask`
29
+ - **Execution Strategy Management**: Handles different execution strategies (DIRECT, and extensible for future types)
30
+ - **Workflow Coordination**: Manages multi-step skill execution workflows
31
+ - **Memory Management**: Tracks and manages `jobMemory` and `taskMemory` across executions
32
+ - **Error Handling & Retry Logic**: Robust error handling with configurable retry strategies
33
+ - **Result Aggregation**: Combines results from multiple skill executions
34
+
35
+ ### Key Concepts
36
+
37
+ - **Task**: A single skill execution request with a specific execution strategy
38
+ - **Execution Strategy**: How a task should be executed (currently `DIRECT`, designed to support more)
39
+ - **Workflow**: A sequence of tasks that execute in order, with memory passed between them
40
+ - **Job**: A collection of workflows or tasks that share the same `jobId` and `jobMemory`
41
+
42
+ ---
43
+
44
+ ## Architecture
45
+
46
+ ```
47
+ ┌─────────────────────────────────────────────────────────┐
48
+ │ Your External Package │
49
+ │ │
50
+ │ ┌──────────────────────────────────────────────────┐ │
51
+ │ │ SkillExecutionOrchestrator │ │
52
+ │ │ - Manages execution strategies │ │
53
+ │ │ - Coordinates workflows │ │
54
+ │ │ - Handles memory management │ │
55
+ │ └──────────────────────────────────────────────────┘ │
56
+ │ │ │
57
+ │ ▼ │
58
+ │ ┌──────────────────────────────────────────────────┐ │
59
+ │ │ ExecutionStrategyManager │ │
60
+ │ │ - DIRECT strategy handler │ │
61
+ │ │ - Extensible for future strategies │ │
62
+ │ └──────────────────────────────────────────────────┘ │
63
+ │ │ │
64
+ │ ▼ │
65
+ │ ┌──────────────────────────────────────────────────┐ │
66
+ │ │ @woroces/ai-skills │ │
67
+ │ │ - XeonoxSkillsClient.runTask() │ │
68
+ │ │ - Handles gateway, registry, parsing │ │
69
+ │ └──────────────────────────────────────────────────┘ │
70
+ └─────────────────────────────────────────────────────────┘
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Prerequisites
76
+
77
+ - Node.js >= 18.0.0
78
+ - TypeScript knowledge
79
+ - Understanding of `@woroces/ai-skills` package
80
+ - Access to GitHub Package Registry
81
+ - Understanding of execution memory management concepts
82
+
83
+ ---
84
+
85
+ ## Project Setup
86
+
87
+ ### Step 1: Initialize Project
88
+
89
+ ```bash
90
+ mkdir skill-execution-orchestrator
91
+ cd skill-execution-orchestrator
92
+ npm init -y
93
+ ```
94
+
95
+ ### Step 2: Install Dependencies
96
+
97
+ ```bash
98
+ # Core dependencies
99
+ npm install @woroces/ai-skills @athenices/execution-memory-manager
100
+
101
+ # Development dependencies
102
+ npm install --save-dev typescript @types/node ts-node jest @types/jest ts-jest
103
+ ```
104
+
105
+ ### Step 3: Configure TypeScript
106
+
107
+ Create `tsconfig.json`:
108
+
109
+ ```json
110
+ {
111
+ "compilerOptions": {
112
+ "target": "ES2020",
113
+ "module": "commonjs",
114
+ "lib": ["ES2020"],
115
+ "outDir": "./dist",
116
+ "rootDir": "./src",
117
+ "strict": true,
118
+ "esModuleInterop": true,
119
+ "skipLibCheck": true,
120
+ "forceConsistentCasingInFileNames": true,
121
+ "declaration": true,
122
+ "declarationMap": true,
123
+ "sourceMap": true,
124
+ "resolveJsonModule": true
125
+ },
126
+ "include": ["src/**/*"],
127
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
128
+ }
129
+ ```
130
+
131
+ ### Step 4: Configure npm Registry
132
+
133
+ Create `.npmrc`:
134
+
135
+ ```
136
+ @woroces:registry=https://npm.pkg.github.com
137
+ @athenices:registry=https://npm.pkg.github.com
138
+ //npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Core Components
144
+
145
+ ### 1. Execution Strategy Interface
146
+
147
+ Create `src/strategies/execution-strategy.ts`:
148
+
149
+ ```typescript
150
+ import { RunTaskRequest, RunSkillResponse } from "@woroces/ai-skills";
151
+
152
+ /**
153
+ * Base interface for execution strategies.
154
+ *
155
+ * Each strategy defines how a task should be executed.
156
+ * Currently supports DIRECT, but designed to be extensible.
157
+ */
158
+ export interface IExecutionStrategy {
159
+ /**
160
+ * Execute a task using this strategy.
161
+ *
162
+ * @param request The task request
163
+ * @returns Promise resolving to the execution result
164
+ */
165
+ execute<TParsed = any>(
166
+ request: RunTaskRequest
167
+ ): Promise<RunSkillResponse<TParsed>>;
168
+
169
+ /**
170
+ * Get the strategy name/type.
171
+ */
172
+ getType(): string;
173
+
174
+ /**
175
+ * Check if this strategy can handle the given request.
176
+ */
177
+ canHandle(request: RunTaskRequest): boolean;
178
+ }
179
+ ```
180
+
181
+ ### 2. Direct Execution Strategy
182
+
183
+ Create `src/strategies/direct-strategy.ts`:
184
+
185
+ ```typescript
186
+ import {
187
+ XeonoxSkillsClient,
188
+ RunTaskRequest,
189
+ RunSkillResponse,
190
+ ExecutionType
191
+ } from "@woroces/ai-skills";
192
+ import type { IExecutionStrategy } from "./execution-strategy";
193
+
194
+ /**
195
+ * Direct execution strategy.
196
+ *
197
+ * Executes tasks by directly passing through to the skill executor.
198
+ * This is the simplest and most common execution strategy.
199
+ */
200
+ export class DirectExecutionStrategy implements IExecutionStrategy {
201
+ private client: XeonoxSkillsClient;
202
+
203
+ constructor(client: XeonoxSkillsClient) {
204
+ this.client = client;
205
+ }
206
+
207
+ async execute<TParsed = any>(
208
+ request: RunTaskRequest
209
+ ): Promise<RunSkillResponse<TParsed>> {
210
+ // Ensure execution type is set to DIRECT
211
+ const taskRequest: RunTaskRequest = {
212
+ ...request,
213
+ executionType: ExecutionType.DIRECT
214
+ };
215
+
216
+ return this.client.runTask<TParsed>(taskRequest);
217
+ }
218
+
219
+ getType(): string {
220
+ return ExecutionType.DIRECT;
221
+ }
222
+
223
+ canHandle(request: RunTaskRequest): boolean {
224
+ return request.executionType === ExecutionType.DIRECT ||
225
+ !request.executionType; // Default to DIRECT if not specified
226
+ }
227
+ }
228
+ ```
229
+
230
+ ### 3. Execution Strategy Manager
231
+
232
+ Create `src/strategies/strategy-manager.ts`:
233
+
234
+ ```typescript
235
+ import { RunTaskRequest, RunSkillResponse, ExecutionType } from "@woroces/ai-skills";
236
+ import type { IExecutionStrategy } from "./execution-strategy";
237
+ import { DirectExecutionStrategy } from "./direct-strategy";
238
+ import { XeonoxSkillsClient } from "@woroces/ai-skills";
239
+
240
+ /**
241
+ * Manages execution strategies.
242
+ *
243
+ * Responsible for:
244
+ * - Registering available strategies
245
+ * - Selecting the appropriate strategy for a task
246
+ * - Providing extensibility for future strategy types
247
+ */
248
+ export class ExecutionStrategyManager {
249
+ private strategies: Map<string, IExecutionStrategy> = new Map();
250
+ private defaultStrategy: IExecutionStrategy;
251
+
252
+ constructor(client: XeonoxSkillsClient) {
253
+ // Register default DIRECT strategy
254
+ const directStrategy = new DirectExecutionStrategy(client);
255
+ this.defaultStrategy = directStrategy;
256
+ this.strategies.set(ExecutionType.DIRECT, directStrategy);
257
+ }
258
+
259
+ /**
260
+ * Register a new execution strategy.
261
+ */
262
+ registerStrategy(strategy: IExecutionStrategy): void {
263
+ this.strategies.set(strategy.getType(), strategy);
264
+ }
265
+
266
+ /**
267
+ * Get the appropriate strategy for a task request.
268
+ */
269
+ getStrategy(request: RunTaskRequest): IExecutionStrategy {
270
+ // Try to find a strategy that can handle this request
271
+ for (const strategy of this.strategies.values()) {
272
+ if (strategy.canHandle(request)) {
273
+ return strategy;
274
+ }
275
+ }
276
+
277
+ // Fall back to default (DIRECT)
278
+ return this.defaultStrategy;
279
+ }
280
+
281
+ /**
282
+ * Execute a task using the appropriate strategy.
283
+ */
284
+ async execute<TParsed = any>(
285
+ request: RunTaskRequest
286
+ ): Promise<RunSkillResponse<TParsed>> {
287
+ const strategy = this.getStrategy(request);
288
+ return strategy.execute<TParsed>(request);
289
+ }
290
+
291
+ /**
292
+ * Get all registered strategy types.
293
+ */
294
+ getAvailableStrategies(): string[] {
295
+ return Array.from(this.strategies.keys());
296
+ }
297
+ }
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Skill Execution Manager
303
+
304
+ Create `src/skill-execution-manager.ts`:
305
+
306
+ ```typescript
307
+ import {
308
+ XeonoxSkillsClient,
309
+ RunTaskRequest,
310
+ RunSkillResponse,
311
+ ExecutionType
312
+ } from "@woroces/ai-skills";
313
+ import type { XeonoxSkillsClientOptions } from "@woroces/ai-skills";
314
+ import type { JobHistory, TaskHistory } from "@athenices/execution-memory-manager";
315
+ import { ExecutionStrategyManager } from "./strategies/strategy-manager";
316
+
317
+ /**
318
+ * Options for skill execution.
319
+ */
320
+ export interface SkillExecutionOptions {
321
+ jobId?: string;
322
+ agentId?: string;
323
+ timeoutMs?: number;
324
+ retryConfig?: RetryConfig;
325
+ }
326
+
327
+ /**
328
+ * Retry configuration for failed executions.
329
+ */
330
+ export interface RetryConfig {
331
+ maxRetries?: number;
332
+ retryDelayMs?: number;
333
+ retryableErrors?: string[];
334
+ }
335
+
336
+ /**
337
+ * Skill Execution Manager
338
+ *
339
+ * High-level manager for executing skills with different strategies.
340
+ * Handles:
341
+ * - Strategy selection and execution
342
+ * - Memory management
343
+ * - Error handling and retries
344
+ * - Result tracking
345
+ */
346
+ export class SkillExecutionManager {
347
+ private client: XeonoxSkillsClient;
348
+ private strategyManager: ExecutionStrategyManager;
349
+ private jobMemory: Map<string, JobHistory> = new Map();
350
+ private taskMemory: Map<string, TaskHistory> = new Map();
351
+
352
+ constructor(options?: XeonoxSkillsClientOptions) {
353
+ this.client = new XeonoxSkillsClient(options);
354
+ this.strategyManager = new ExecutionStrategyManager(this.client);
355
+ }
356
+
357
+ /**
358
+ * Execute a single skill.
359
+ *
360
+ * @param skillKey The skill to execute (e.g., "skills/professional-answer")
361
+ * @param input The input data for the skill
362
+ * @param options Execution options
363
+ */
364
+ async executeSkill<TParsed = any>(
365
+ skillKey: string,
366
+ input: Record<string, any> | string,
367
+ options?: SkillExecutionOptions
368
+ ): Promise<RunSkillResponse<TParsed>> {
369
+ const jobId = options?.jobId || `job-${Date.now()}`;
370
+
371
+ // Get or initialize memory for this job
372
+ const jobMemory = this.jobMemory.get(jobId);
373
+ const taskMemory = this.taskMemory.get(jobId) || {};
374
+
375
+ const taskRequest: RunTaskRequest = {
376
+ skillKey,
377
+ input,
378
+ executionType: ExecutionType.DIRECT,
379
+ jobId,
380
+ agentId: options?.agentId,
381
+ timeoutMs: options?.timeoutMs,
382
+ jobMemory,
383
+ taskMemory
384
+ };
385
+
386
+ // Execute with retry logic if configured
387
+ if (options?.retryConfig) {
388
+ return this.executeWithRetry<TParsed>(taskRequest, options.retryConfig);
389
+ }
390
+
391
+ const result = await this.strategyManager.execute<TParsed>(taskRequest);
392
+
393
+ // Update memory with this execution
394
+ this.updateMemory(jobId, result);
395
+
396
+ return result;
397
+ }
398
+
399
+ /**
400
+ * Execute a skill with variables/context.
401
+ */
402
+ async executeSkillWithContext<TParsed = any>(
403
+ skillKey: string,
404
+ input: Record<string, any> | string,
405
+ variables?: Record<string, any>,
406
+ context?: Record<string, any> | string,
407
+ options?: SkillExecutionOptions
408
+ ): Promise<RunSkillResponse<TParsed>> {
409
+ const jobId = options?.jobId || `job-${Date.now()}`;
410
+ const jobMemory = this.jobMemory.get(jobId);
411
+ const taskMemory = this.taskMemory.get(jobId) || {};
412
+
413
+ const taskRequest: RunTaskRequest = {
414
+ skillKey,
415
+ input,
416
+ variables,
417
+ context,
418
+ executionType: ExecutionType.DIRECT,
419
+ jobId,
420
+ agentId: options?.agentId,
421
+ timeoutMs: options?.timeoutMs,
422
+ jobMemory,
423
+ taskMemory
424
+ };
425
+
426
+ if (options?.retryConfig) {
427
+ return this.executeWithRetry<TParsed>(taskRequest, options.retryConfig);
428
+ }
429
+
430
+ const result = await this.strategyManager.execute<TParsed>(taskRequest);
431
+ this.updateMemory(jobId, result);
432
+
433
+ return result;
434
+ }
435
+
436
+ /**
437
+ * Execute a task with a specific execution strategy.
438
+ */
439
+ async executeTask<TParsed = any>(
440
+ taskRequest: RunTaskRequest
441
+ ): Promise<RunSkillResponse<TParsed>> {
442
+ const jobId = taskRequest.jobId || `job-${Date.now()}`;
443
+
444
+ // Ensure memory is attached
445
+ const enrichedRequest: RunTaskRequest = {
446
+ ...taskRequest,
447
+ jobId,
448
+ jobMemory: taskRequest.jobMemory || this.jobMemory.get(jobId),
449
+ taskMemory: taskRequest.taskMemory || this.taskMemory.get(jobId)
450
+ };
451
+
452
+ const result = await this.strategyManager.execute<TParsed>(enrichedRequest);
453
+ this.updateMemory(jobId, result);
454
+
455
+ return result;
456
+ }
457
+
458
+ /**
459
+ * Execute with retry logic.
460
+ */
461
+ private async executeWithRetry<TParsed = any>(
462
+ request: RunTaskRequest,
463
+ config: RetryConfig
464
+ ): Promise<RunSkillResponse<TParsed>> {
465
+ const maxRetries = config.maxRetries || 3;
466
+ const retryDelay = config.retryDelayMs || 1000;
467
+ const retryableErrors = config.retryableErrors || [];
468
+
469
+ let lastError: Error | null = null;
470
+
471
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
472
+ try {
473
+ return await this.strategyManager.execute<TParsed>(request);
474
+ } catch (error: any) {
475
+ lastError = error;
476
+
477
+ // Check if error is retryable
478
+ const isRetryable = retryableErrors.length === 0 ||
479
+ retryableErrors.some(pattern =>
480
+ error.message?.includes(pattern) ||
481
+ error.code === pattern
482
+ );
483
+
484
+ if (!isRetryable || attempt === maxRetries) {
485
+ throw error;
486
+ }
487
+
488
+ // Wait before retrying
489
+ await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));
490
+ }
491
+ }
492
+
493
+ throw lastError || new Error("Execution failed after retries");
494
+ }
495
+
496
+ /**
497
+ * Update memory with execution result.
498
+ */
499
+ private updateMemory(jobId: string, result: RunSkillResponse<any>): void {
500
+ // Update job memory (history of all task results)
501
+ const currentJobMemory = this.jobMemory.get(jobId) || {};
502
+ const updatedJobMemory: JobHistory = {
503
+ ...currentJobMemory,
504
+ [result.skillKey]: {
505
+ result: result.parsed,
506
+ metadata: result.metadata,
507
+ timestamp: Date.now()
508
+ }
509
+ };
510
+ this.jobMemory.set(jobId, updatedJobMemory);
511
+
512
+ // Update task memory (history of skills executed)
513
+ const currentTaskMemory = this.taskMemory.get(jobId) || {};
514
+ const updatedTaskMemory: TaskHistory = {
515
+ ...currentTaskMemory,
516
+ [result.skillKey]: {
517
+ activityId: result.metadata.activityId,
518
+ timestamp: Date.now()
519
+ }
520
+ };
521
+ this.taskMemory.set(jobId, updatedTaskMemory);
522
+ }
523
+
524
+ /**
525
+ * Get job memory for a specific job.
526
+ */
527
+ getJobMemory(jobId: string): JobHistory | undefined {
528
+ return this.jobMemory.get(jobId);
529
+ }
530
+
531
+ /**
532
+ * Get task memory for a specific job.
533
+ */
534
+ getTaskMemory(jobId: string): TaskHistory | undefined {
535
+ return this.taskMemory.get(jobId);
536
+ }
537
+
538
+ /**
539
+ * Clear memory for a job.
540
+ */
541
+ clearMemory(jobId: string): void {
542
+ this.jobMemory.delete(jobId);
543
+ this.taskMemory.delete(jobId);
544
+ }
545
+
546
+ /**
547
+ * Get available execution strategies.
548
+ */
549
+ getAvailableStrategies(): string[] {
550
+ return this.strategyManager.getAvailableStrategies();
551
+ }
552
+ }
553
+ ```
554
+
555
+ ---
556
+
557
+ ## Workflow Orchestration
558
+
559
+ Create `src/workflow-orchestrator.ts`:
560
+
561
+ ```typescript
562
+ import {
563
+ RunTaskRequest,
564
+ RunSkillResponse,
565
+ ExecutionType
566
+ } from "@woroces/ai-skills";
567
+ import { SkillExecutionManager } from "./skill-execution-manager";
568
+ import type { SkillExecutionOptions } from "./skill-execution-manager";
569
+
570
+ /**
571
+ * Definition of a single step in a workflow.
572
+ */
573
+ export interface WorkflowStep {
574
+ skillKey: string;
575
+ input: Record<string, any> | string;
576
+ variables?: Record<string, any>;
577
+ context?: Record<string, any> | string;
578
+ executionType?: ExecutionType;
579
+ condition?: (previousResults: RunSkillResponse<any>[]) => boolean;
580
+ }
581
+
582
+ /**
583
+ * Workflow execution result.
584
+ */
585
+ export interface WorkflowResult {
586
+ jobId: string;
587
+ steps: Array<{
588
+ step: WorkflowStep;
589
+ result: RunSkillResponse<any>;
590
+ success: boolean;
591
+ error?: Error;
592
+ }>;
593
+ success: boolean;
594
+ finalResult?: RunSkillResponse<any>;
595
+ }
596
+
597
+ /**
598
+ * Workflow Orchestrator
599
+ *
600
+ * Manages execution of multi-step workflows where:
601
+ * - Steps execute in sequence
602
+ * - Memory is passed between steps
603
+ * - Conditional execution is supported
604
+ * - Results are aggregated
605
+ */
606
+ export class WorkflowOrchestrator {
607
+ private executionManager: SkillExecutionManager;
608
+
609
+ constructor(executionManager: SkillExecutionManager) {
610
+ this.executionManager = executionManager;
611
+ }
612
+
613
+ /**
614
+ * Execute a workflow (sequence of steps).
615
+ */
616
+ async executeWorkflow(
617
+ steps: WorkflowStep[],
618
+ options?: SkillExecutionOptions
619
+ ): Promise<WorkflowResult> {
620
+ const jobId = options?.jobId || `workflow-${Date.now()}`;
621
+ const results: WorkflowResult['steps'] = [];
622
+ let previousResults: RunSkillResponse<any>[] = [];
623
+
624
+ for (const step of steps) {
625
+ // Check condition if provided
626
+ if (step.condition && !step.condition(previousResults)) {
627
+ results.push({
628
+ step,
629
+ result: {} as RunSkillResponse<any>,
630
+ success: false,
631
+ error: new Error("Step condition not met")
632
+ });
633
+ continue;
634
+ }
635
+
636
+ try {
637
+ // Build input that can reference previous results
638
+ const enrichedInput = this.enrichInputWithPreviousResults(
639
+ step.input,
640
+ previousResults
641
+ );
642
+
643
+ // Execute the step
644
+ const taskRequest: RunTaskRequest = {
645
+ skillKey: step.skillKey,
646
+ input: enrichedInput,
647
+ variables: step.variables,
648
+ context: step.context,
649
+ executionType: step.executionType || ExecutionType.DIRECT,
650
+ jobId,
651
+ agentId: options?.agentId,
652
+ timeoutMs: options?.timeoutMs,
653
+ jobMemory: this.executionManager.getJobMemory(jobId),
654
+ taskMemory: this.executionManager.getTaskMemory(jobId)
655
+ };
656
+
657
+ const result = await this.executionManager.executeTask(taskRequest);
658
+ previousResults.push(result);
659
+
660
+ results.push({
661
+ step,
662
+ result,
663
+ success: true
664
+ });
665
+ } catch (error: any) {
666
+ results.push({
667
+ step,
668
+ result: {} as RunSkillResponse<any>,
669
+ success: false,
670
+ error
671
+ });
672
+
673
+ // Optionally stop on error
674
+ break;
675
+ }
676
+ }
677
+
678
+ const success = results.every(r => r.success);
679
+ const finalResult = previousResults.length > 0
680
+ ? previousResults[previousResults.length - 1]
681
+ : undefined;
682
+
683
+ return {
684
+ jobId,
685
+ steps: results,
686
+ success,
687
+ finalResult
688
+ };
689
+ }
690
+
691
+ /**
692
+ * Enrich input with results from previous steps.
693
+ */
694
+ private enrichInputWithPreviousResults(
695
+ input: Record<string, any> | string,
696
+ previousResults: RunSkillResponse<any>[]
697
+ ): Record<string, any> | string {
698
+ if (typeof input === 'string') {
699
+ // Simple string replacement for previous results
700
+ let enriched = input;
701
+ previousResults.forEach((result, index) => {
702
+ enriched = enriched.replace(
703
+ new RegExp(`\\$\\{step${index + 1}\\}`, 'g'),
704
+ JSON.stringify(result.parsed)
705
+ );
706
+ });
707
+ return enriched;
708
+ }
709
+
710
+ // For object inputs, merge previous results
711
+ const enriched: Record<string, any> = { ...input };
712
+
713
+ // Add previous results as $previousSteps array
714
+ enriched.$previousSteps = previousResults.map(r => r.parsed);
715
+
716
+ // Add individual step results as $step1, $step2, etc.
717
+ previousResults.forEach((result, index) => {
718
+ enriched[`$step${index + 1}`] = result.parsed;
719
+ });
720
+
721
+ return enriched;
722
+ }
723
+ }
724
+ ```
725
+
726
+ ---
727
+
728
+ ## Complete Implementation
729
+
730
+ ### Main Entry Point
731
+
732
+ Create `src/index.ts`:
733
+
734
+ ```typescript
735
+ // Core exports
736
+ export { SkillExecutionManager } from "./skill-execution-manager";
737
+ export { WorkflowOrchestrator } from "./workflow-orchestrator";
738
+ export { ExecutionStrategyManager } from "./strategies/strategy-manager";
739
+
740
+ // Strategy exports
741
+ export { DirectExecutionStrategy } from "./strategies/direct-strategy";
742
+ export type { IExecutionStrategy } from "./strategies/execution-strategy";
743
+
744
+ // Type exports
745
+ export type { SkillExecutionOptions, RetryConfig } from "./skill-execution-manager";
746
+ export type { WorkflowStep, WorkflowResult } from "./workflow-orchestrator";
747
+
748
+ // Re-export from @woroces/ai-skills for convenience
749
+ export type {
750
+ RunTaskRequest,
751
+ RunSkillResponse,
752
+ ExecutionType
753
+ } from "@woroces/ai-skills";
754
+ export { ExecutionType } from "@woroces/ai-skills";
755
+ ```
756
+
757
+ ---
758
+
759
+ ## Usage Examples
760
+
761
+ ### Example 1: Basic Skill Execution
762
+
763
+ ```typescript
764
+ import { SkillExecutionManager } from "skill-execution-orchestrator";
765
+
766
+ const manager = new SkillExecutionManager({
767
+ enableContentRegistry: true,
768
+ contentRegistryLocalPath: "./.metadata"
769
+ });
770
+
771
+ // Execute a single skill
772
+ const result = await manager.executeSkill(
773
+ "skills/professional-answer",
774
+ { question: "What is AI?" },
775
+ {
776
+ jobId: "job-123",
777
+ agentId: "agent-abc"
778
+ }
779
+ );
780
+
781
+ console.log("Answer:", result.parsed);
782
+ ```
783
+
784
+ ### Example 2: Skill Execution with Context
785
+
786
+ ```typescript
787
+ const result = await manager.executeSkillWithContext(
788
+ "skills/professional-decision",
789
+ { scenario: "Should we migrate to cloud?" },
790
+ { orgName: "TechCorp", department: "Engineering" },
791
+ { industry: "Technology", size: "Enterprise" },
792
+ {
793
+ jobId: "job-456",
794
+ timeoutMs: 30000
795
+ }
796
+ );
797
+ ```
798
+
799
+ ### Example 3: Workflow Execution
800
+
801
+ ```typescript
802
+ import { SkillExecutionManager, WorkflowOrchestrator } from "skill-execution-orchestrator";
803
+ import { ExecutionType } from "@woroces/ai-skills";
804
+
805
+ const manager = new SkillExecutionManager();
806
+ const orchestrator = new WorkflowOrchestrator(manager);
807
+
808
+ // Define a workflow
809
+ const workflow = [
810
+ {
811
+ skillKey: "skills/professional-answer",
812
+ input: { question: "What are the benefits of cloud migration?" },
813
+ executionType: ExecutionType.DIRECT
814
+ },
815
+ {
816
+ skillKey: "skills/professional-decision",
817
+ input: { scenario: "Based on the analysis, should we migrate?" },
818
+ variables: { orgName: "TechCorp" },
819
+ // Only execute if first step succeeded
820
+ condition: (results) => results.length > 0 && results[0].parsed
821
+ }
822
+ ];
823
+
824
+ // Execute workflow
825
+ const workflowResult = await orchestrator.executeWorkflow(workflow, {
826
+ jobId: "workflow-789"
827
+ });
828
+
829
+ if (workflowResult.success) {
830
+ console.log("Workflow completed:", workflowResult.finalResult);
831
+ } else {
832
+ console.error("Workflow failed:", workflowResult.steps);
833
+ }
834
+ ```
835
+
836
+ ### Example 4: With Retry Logic
837
+
838
+ ```typescript
839
+ const result = await manager.executeSkill(
840
+ "skills/professional-answer",
841
+ { question: "Complex question here" },
842
+ {
843
+ jobId: "job-retry",
844
+ retryConfig: {
845
+ maxRetries: 3,
846
+ retryDelayMs: 2000,
847
+ retryableErrors: ["timeout", "rate limit", "network"]
848
+ }
849
+ }
850
+ );
851
+ ```
852
+
853
+ ---
854
+
855
+ ## Advanced Features
856
+
857
+ ### Custom Execution Strategy
858
+
859
+ You can extend the system with custom strategies:
860
+
861
+ ```typescript
862
+ import { IExecutionStrategy, ExecutionStrategyManager } from "skill-execution-orchestrator";
863
+ import { RunTaskRequest, RunSkillResponse } from "@woroces/ai-skills";
864
+
865
+ class ParallelExecutionStrategy implements IExecutionStrategy {
866
+ async execute<TParsed = any>(
867
+ request: RunTaskRequest
868
+ ): Promise<RunSkillResponse<TParsed>> {
869
+ // Custom parallel execution logic
870
+ // This is a placeholder for future implementation
871
+ throw new Error("Parallel execution not yet implemented");
872
+ }
873
+
874
+ getType(): string {
875
+ return "parallel";
876
+ }
877
+
878
+ canHandle(request: RunTaskRequest): boolean {
879
+ return request.executionType === "parallel";
880
+ }
881
+ }
882
+
883
+ // Register the strategy
884
+ const manager = new SkillExecutionManager();
885
+ // Access strategy manager and register (would need to expose this)
886
+ ```
887
+
888
+ ---
889
+
890
+ ## Testing
891
+
892
+ ### Unit Tests Example
893
+
894
+ Create `src/skill-execution-manager.test.ts`:
895
+
896
+ ```typescript
897
+ import { SkillExecutionManager } from "./skill-execution-manager";
898
+ import { ExecutionType } from "@woroces/ai-skills";
899
+
900
+ describe("SkillExecutionManager", () => {
901
+ let manager: SkillExecutionManager;
902
+
903
+ beforeEach(() => {
904
+ manager = new SkillExecutionManager({
905
+ enableContentRegistry: true,
906
+ contentRegistryLocalPath: "./.metadata"
907
+ });
908
+ });
909
+
910
+ test("should execute a skill", async () => {
911
+ const result = await manager.executeSkill(
912
+ "skills/professional-answer",
913
+ { question: "Test question" },
914
+ { jobId: "test-job" }
915
+ );
916
+
917
+ expect(result).toBeDefined();
918
+ expect(result.skillKey).toBe("skills/professional-answer");
919
+ expect(result.flexMd).toBeDefined();
920
+ });
921
+
922
+ test("should manage job memory", async () => {
923
+ const jobId = "memory-test";
924
+
925
+ await manager.executeSkill(
926
+ "skills/professional-answer",
927
+ { question: "First question" },
928
+ { jobId }
929
+ );
930
+
931
+ const memory = manager.getJobMemory(jobId);
932
+ expect(memory).toBeDefined();
933
+ });
934
+ });
935
+ ```
936
+
937
+ ---
938
+
939
+ ## Summary
940
+
941
+ You've now created an external package that:
942
+
943
+ 1. ✅ Uses `runTask` from `@woroces/ai-skills` for skill execution
944
+ 2. ✅ Manages different execution strategies (extensible architecture)
945
+ 3. ✅ Handles skill execution with memory management
946
+ 4. ✅ Provides workflow orchestration for multi-step processes
947
+ 5. ✅ Includes retry logic and error handling
948
+ 6. ✅ Offers a clean, high-level API
949
+
950
+ ### Key Benefits
951
+
952
+ - **Separation of Concerns**: Your package handles orchestration, `@woroces/ai-skills` handles execution
953
+ - **Extensibility**: Easy to add new execution strategies
954
+ - **Memory Management**: Automatic tracking of job and task memory
955
+ - **Workflow Support**: Built-in support for multi-step processes
956
+ - **Error Resilience**: Configurable retry logic
957
+
958
+ ### Next Steps
959
+
960
+ 1. Add more execution strategies (parallel, sequential with dependencies, etc.)
961
+ 2. Implement workflow visualization
962
+ 3. Add result caching
963
+ 4. Implement workflow templates/presets
964
+ 5. Add monitoring and metrics collection
965
+
966
+ ---
967
+
968
+ **Questions?** Refer to the `@woroces/ai-skills` documentation for details on the underlying execution system.