groundswell 0.0.1
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.
- package/.claude/settings.local.json +9 -0
- package/.claude/system_prompts/task-breakdown.md +100 -0
- package/PRPs/001-hierarchical-workflow-engine.md +2438 -0
- package/PRPs/PRDs/001-hierarchical-workflow-engine.md +543 -0
- package/PRPs/PRDs/002-agent-prompt.md +390 -0
- package/PRPs/PRDs/003-agent-prompt.md +943 -0
- package/PRPs/PRDs/004-agent-prompt.md +1136 -0
- package/PRPs/PRDs/tasks-001.json +492 -0
- package/PRPs/README.md +83 -0
- package/PRPs/templates/prp_base.md +222 -0
- package/README.md +218 -0
- package/docs/agent.md +422 -0
- package/docs/prompt.md +419 -0
- package/docs/workflow.md +600 -0
- package/examples/README.md +244 -0
- package/examples/examples/01-basic-workflow.ts +100 -0
- package/examples/examples/02-decorator-options.ts +217 -0
- package/examples/examples/03-parent-child.ts +241 -0
- package/examples/examples/04-observers-debugger.ts +340 -0
- package/examples/examples/05-error-handling.ts +387 -0
- package/examples/examples/06-concurrent-tasks.ts +352 -0
- package/examples/examples/07-agent-loops.ts +432 -0
- package/examples/examples/08-sdk-features.ts +667 -0
- package/examples/examples/09-reflection.ts +573 -0
- package/examples/examples/10-introspection.ts +550 -0
- package/examples/index.ts +143 -0
- package/examples/utils/helpers.ts +57 -0
- package/llms_full.txt +5890 -0
- package/package.json +63 -0
- package/plan/P1P2/PRP.md +527 -0
- package/plan/P1P2/research/LRU_CACHE_BEST_PRACTICES.md +1929 -0
- package/plan/P1P2/research/LRU_CACHE_CODE_PATTERNS.md +857 -0
- package/plan/P1P2/research/LRU_CACHE_INTEGRATION_GUIDE.md +738 -0
- package/plan/P1P2/research/LRU_CACHE_RESEARCH_INDEX.md +424 -0
- package/plan/P1P2/research/REFLECTION_INDEX.md +291 -0
- package/plan/P1P2/research/REFLECTION_RESEARCH_REPORT.md +1342 -0
- package/plan/P1P2/research/RESEARCH_SUMMARY.md +342 -0
- package/plan/P1P2/research/anthropic-sdk.md +174 -0
- package/plan/P1P2/research/async-local-storage.md +200 -0
- package/plan/P1P2/research/reflection-code-patterns.md +1205 -0
- package/plan/P1P2/research/reflection-decision-matrix.md +421 -0
- package/plan/P1P2/research/reflection-implementation-guide.md +1341 -0
- package/plan/P1P2/research/reflection-integration-guide.md +834 -0
- package/plan/P1P2/research/reflection-patterns.md +1468 -0
- package/plan/P1P2/research/reflection-quick-reference.md +558 -0
- package/plan/P1P2/research/zod-schema.md +152 -0
- package/plan/P3P4/PRP.md +1388 -0
- package/plan/P3P4/research/caching-lru.md +116 -0
- package/plan/P3P4/research/introspection-tools.md +177 -0
- package/plan/P3P4/research/reflection-patterns.md +117 -0
- package/plan/P4P5/PRP.md +1136 -0
- package/plan/P4P5/research/RESEARCH_SUMMARY.md +151 -0
- package/plan/architecture/external_deps.md +358 -0
- package/plan/architecture/system_context.md +242 -0
- package/plan/backlog.json +867 -0
- package/plan/research/INTROSPECTION_RESEARCH_SUMMARY.md +378 -0
- package/plan/research/README-INTROSPECTION.md +352 -0
- package/plan/research/agent-introspection-patterns.md +1085 -0
- package/plan/research/introspection-security-guide.md +928 -0
- package/plan/research/introspection-tool-examples.md +875 -0
- package/scripts/generate-llms-full.ts +206 -0
- package/src/__tests__/integration/agent-workflow.test.ts +256 -0
- package/src/__tests__/integration/tree-mirroring.test.ts +114 -0
- package/src/__tests__/unit/agent.test.ts +169 -0
- package/src/__tests__/unit/cache-key.test.ts +182 -0
- package/src/__tests__/unit/cache.test.ts +172 -0
- package/src/__tests__/unit/context.test.ts +138 -0
- package/src/__tests__/unit/decorators.test.ts +100 -0
- package/src/__tests__/unit/introspection-tools.test.ts +277 -0
- package/src/__tests__/unit/prompt.test.ts +135 -0
- package/src/__tests__/unit/reflection.test.ts +210 -0
- package/src/__tests__/unit/tree-debugger.test.ts +85 -0
- package/src/__tests__/unit/workflow.test.ts +81 -0
- package/src/cache/cache-key.ts +244 -0
- package/src/cache/cache.ts +236 -0
- package/src/cache/index.ts +8 -0
- package/src/core/agent.ts +573 -0
- package/src/core/context.ts +119 -0
- package/src/core/event-tree.ts +260 -0
- package/src/core/factory.ts +123 -0
- package/src/core/index.ts +17 -0
- package/src/core/logger.ts +87 -0
- package/src/core/mcp-handler.ts +184 -0
- package/src/core/prompt.ts +150 -0
- package/src/core/workflow-context.ts +349 -0
- package/src/core/workflow.ts +302 -0
- package/src/debugger/index.ts +1 -0
- package/src/debugger/tree-debugger.ts +210 -0
- package/src/decorators/index.ts +3 -0
- package/src/decorators/observed-state.ts +95 -0
- package/src/decorators/step.ts +139 -0
- package/src/decorators/task.ts +96 -0
- package/src/examples/index.ts +2 -0
- package/src/examples/tdd-orchestrator.ts +65 -0
- package/src/examples/test-cycle-workflow.ts +64 -0
- package/src/index.ts +140 -0
- package/src/reflection/index.ts +5 -0
- package/src/reflection/reflection.ts +407 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/introspection.ts +464 -0
- package/src/types/agent.ts +90 -0
- package/src/types/decorators.ts +25 -0
- package/src/types/error-strategy.ts +13 -0
- package/src/types/error.ts +20 -0
- package/src/types/events.ts +74 -0
- package/src/types/index.ts +55 -0
- package/src/types/logging.ts +24 -0
- package/src/types/observer.ts +18 -0
- package/src/types/prompt.ts +40 -0
- package/src/types/reflection.ts +117 -0
- package/src/types/sdk-primitives.ts +128 -0
- package/src/types/snapshot.ts +14 -0
- package/src/types/workflow-context.ts +163 -0
- package/src/types/workflow.ts +37 -0
- package/src/utils/id.ts +11 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/observable.ts +77 -0
- package/tasks.json +0 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +16 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example 6: Concurrent Tasks
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - Using @Task with concurrent: true option
|
|
6
|
+
* - Manual parallel execution patterns
|
|
7
|
+
* - Comparing sequential vs concurrent execution
|
|
8
|
+
* - Fan-out/fan-in patterns
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
Workflow,
|
|
13
|
+
Step,
|
|
14
|
+
Task,
|
|
15
|
+
ObservedState,
|
|
16
|
+
WorkflowTreeDebugger,
|
|
17
|
+
} from 'groundswell';
|
|
18
|
+
import { printHeader, printSection, sleep } from '../utils/helpers.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Simple worker workflow
|
|
22
|
+
*/
|
|
23
|
+
class WorkerWorkflow extends Workflow {
|
|
24
|
+
@ObservedState()
|
|
25
|
+
workerId: string;
|
|
26
|
+
|
|
27
|
+
@ObservedState()
|
|
28
|
+
processingTime: number;
|
|
29
|
+
|
|
30
|
+
@ObservedState()
|
|
31
|
+
result: string = '';
|
|
32
|
+
|
|
33
|
+
constructor(id: string, processingTime: number, parent?: Workflow) {
|
|
34
|
+
super(`Worker-${id}`, parent);
|
|
35
|
+
this.workerId = id;
|
|
36
|
+
this.processingTime = processingTime;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Step({ trackTiming: true, snapshotState: true })
|
|
40
|
+
async process(): Promise<string> {
|
|
41
|
+
this.logger.info(`Worker ${this.workerId} starting (${this.processingTime}ms)`);
|
|
42
|
+
await sleep(this.processingTime);
|
|
43
|
+
this.result = `Result from ${this.workerId}`;
|
|
44
|
+
this.logger.info(`Worker ${this.workerId} completed`);
|
|
45
|
+
return this.result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async run(): Promise<string> {
|
|
49
|
+
this.setStatus('running');
|
|
50
|
+
const result = await this.process();
|
|
51
|
+
this.setStatus('completed');
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Sequential execution pattern
|
|
58
|
+
*/
|
|
59
|
+
class SequentialWorkflow extends Workflow {
|
|
60
|
+
@ObservedState()
|
|
61
|
+
workerCount: number;
|
|
62
|
+
|
|
63
|
+
@ObservedState()
|
|
64
|
+
completedWorkers: number = 0;
|
|
65
|
+
|
|
66
|
+
private workers: { id: string; time: number }[];
|
|
67
|
+
|
|
68
|
+
constructor(name: string, workers: { id: string; time: number }[]) {
|
|
69
|
+
super(name);
|
|
70
|
+
this.workers = workers;
|
|
71
|
+
this.workerCount = workers.length;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@Task()
|
|
75
|
+
async createWorker(config: { id: string; time: number }): Promise<WorkerWorkflow> {
|
|
76
|
+
return new WorkerWorkflow(config.id, config.time, this);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async run(): Promise<string[]> {
|
|
80
|
+
this.setStatus('running');
|
|
81
|
+
this.logger.info(`Starting ${this.workerCount} workers SEQUENTIALLY`);
|
|
82
|
+
|
|
83
|
+
const results: string[] = [];
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
|
|
86
|
+
for (const config of this.workers) {
|
|
87
|
+
const worker = await this.createWorker(config);
|
|
88
|
+
const result = await worker.run();
|
|
89
|
+
results.push(result);
|
|
90
|
+
this.completedWorkers++;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const totalTime = Date.now() - startTime;
|
|
94
|
+
this.logger.info(`All workers completed in ${totalTime}ms`);
|
|
95
|
+
|
|
96
|
+
this.setStatus('completed');
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Concurrent execution using @Task concurrent option
|
|
103
|
+
*/
|
|
104
|
+
class ConcurrentTaskWorkflow extends Workflow {
|
|
105
|
+
@ObservedState()
|
|
106
|
+
workerCount: number;
|
|
107
|
+
|
|
108
|
+
private workers: { id: string; time: number }[];
|
|
109
|
+
|
|
110
|
+
constructor(name: string, workers: { id: string; time: number }[]) {
|
|
111
|
+
super(name);
|
|
112
|
+
this.workers = workers;
|
|
113
|
+
this.workerCount = workers.length;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Note: The concurrent option auto-runs the returned workflows
|
|
117
|
+
@Task({ concurrent: true })
|
|
118
|
+
async createAllWorkers(): Promise<WorkerWorkflow[]> {
|
|
119
|
+
return this.workers.map(
|
|
120
|
+
(config) => new WorkerWorkflow(config.id, config.time, this)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async run(): Promise<void> {
|
|
125
|
+
this.setStatus('running');
|
|
126
|
+
this.logger.info(`Starting ${this.workerCount} workers with @Task concurrent`);
|
|
127
|
+
|
|
128
|
+
const startTime = Date.now();
|
|
129
|
+
|
|
130
|
+
// This will create all workers and run them concurrently
|
|
131
|
+
await this.createAllWorkers();
|
|
132
|
+
|
|
133
|
+
const totalTime = Date.now() - startTime;
|
|
134
|
+
this.logger.info(`All workers completed in ${totalTime}ms`);
|
|
135
|
+
|
|
136
|
+
this.setStatus('completed');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Manual parallel execution pattern (more control)
|
|
142
|
+
*/
|
|
143
|
+
class ManualParallelWorkflow extends Workflow {
|
|
144
|
+
@ObservedState()
|
|
145
|
+
workerCount: number;
|
|
146
|
+
|
|
147
|
+
private workers: { id: string; time: number }[];
|
|
148
|
+
|
|
149
|
+
constructor(name: string, workers: { id: string; time: number }[]) {
|
|
150
|
+
super(name);
|
|
151
|
+
this.workers = workers;
|
|
152
|
+
this.workerCount = workers.length;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@Task()
|
|
156
|
+
async createWorker(config: { id: string; time: number }): Promise<WorkerWorkflow> {
|
|
157
|
+
return new WorkerWorkflow(config.id, config.time, this);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async run(): Promise<string[]> {
|
|
161
|
+
this.setStatus('running');
|
|
162
|
+
this.logger.info(`Starting ${this.workerCount} workers MANUALLY PARALLEL`);
|
|
163
|
+
|
|
164
|
+
const startTime = Date.now();
|
|
165
|
+
|
|
166
|
+
// Create all workers first
|
|
167
|
+
const workerPromises: Promise<WorkerWorkflow>[] = [];
|
|
168
|
+
for (const config of this.workers) {
|
|
169
|
+
workerPromises.push(this.createWorker(config));
|
|
170
|
+
}
|
|
171
|
+
const workers = await Promise.all(workerPromises);
|
|
172
|
+
|
|
173
|
+
// Run all workers in parallel
|
|
174
|
+
const results = await Promise.all(workers.map((w) => w.run()));
|
|
175
|
+
|
|
176
|
+
const totalTime = Date.now() - startTime;
|
|
177
|
+
this.logger.info(`All workers completed in ${totalTime}ms`);
|
|
178
|
+
|
|
179
|
+
this.setStatus('completed');
|
|
180
|
+
return results;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Fan-out / Fan-in pattern
|
|
186
|
+
*/
|
|
187
|
+
class FanOutFanInWorkflow extends Workflow {
|
|
188
|
+
@ObservedState()
|
|
189
|
+
inputData: string[] = [];
|
|
190
|
+
|
|
191
|
+
@ObservedState()
|
|
192
|
+
processedData: string[] = [];
|
|
193
|
+
|
|
194
|
+
@Step({ logStart: true })
|
|
195
|
+
async prepareData(): Promise<void> {
|
|
196
|
+
this.logger.info('Preparing input data');
|
|
197
|
+
this.inputData = ['A', 'B', 'C', 'D', 'E'];
|
|
198
|
+
await sleep(50);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Task()
|
|
202
|
+
async createProcessor(item: string): Promise<WorkerWorkflow> {
|
|
203
|
+
// Variable processing times
|
|
204
|
+
const time = 50 + Math.floor(Math.random() * 100);
|
|
205
|
+
return new WorkerWorkflow(item, time, this);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@Step({ snapshotState: true })
|
|
209
|
+
async fanOut(): Promise<string[]> {
|
|
210
|
+
this.logger.info(`Fan-out: Creating ${this.inputData.length} parallel processors`);
|
|
211
|
+
|
|
212
|
+
// Create all workers
|
|
213
|
+
const workers: WorkerWorkflow[] = [];
|
|
214
|
+
for (const item of this.inputData) {
|
|
215
|
+
workers.push(await this.createProcessor(item));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Run all in parallel
|
|
219
|
+
const results = await Promise.all(workers.map((w) => w.run()));
|
|
220
|
+
|
|
221
|
+
return results;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@Step({ logFinish: true, snapshotState: true })
|
|
225
|
+
async fanIn(results: string[]): Promise<void> {
|
|
226
|
+
this.logger.info(`Fan-in: Aggregating ${results.length} results`);
|
|
227
|
+
this.processedData = results;
|
|
228
|
+
await sleep(50);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async run(): Promise<string[]> {
|
|
232
|
+
this.setStatus('running');
|
|
233
|
+
|
|
234
|
+
await this.prepareData();
|
|
235
|
+
const results = await this.fanOut();
|
|
236
|
+
await this.fanIn(results);
|
|
237
|
+
|
|
238
|
+
this.setStatus('completed');
|
|
239
|
+
return this.processedData;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Run the concurrent tasks example
|
|
245
|
+
*/
|
|
246
|
+
export async function runConcurrentTasksExample(): Promise<void> {
|
|
247
|
+
printHeader('Example 6: Concurrent Tasks');
|
|
248
|
+
|
|
249
|
+
const workerConfigs = [
|
|
250
|
+
{ id: 'W1', time: 200 },
|
|
251
|
+
{ id: 'W2', time: 150 },
|
|
252
|
+
{ id: 'W3', time: 100 },
|
|
253
|
+
{ id: 'W4', time: 180 },
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
// Part 1: Sequential execution
|
|
257
|
+
printSection('Part 1: Sequential Execution');
|
|
258
|
+
{
|
|
259
|
+
const workflow = new SequentialWorkflow('Sequential', workerConfigs);
|
|
260
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
261
|
+
|
|
262
|
+
console.log('Expected time: ~630ms (200+150+100+180)');
|
|
263
|
+
const start = Date.now();
|
|
264
|
+
await workflow.run();
|
|
265
|
+
const elapsed = Date.now() - start;
|
|
266
|
+
console.log(`Actual time: ${elapsed}ms`);
|
|
267
|
+
|
|
268
|
+
console.log('\nTree:');
|
|
269
|
+
console.log(debugger_.toTreeString());
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Part 2: Manual parallel execution
|
|
273
|
+
printSection('Part 2: Manual Parallel Execution');
|
|
274
|
+
{
|
|
275
|
+
const workflow = new ManualParallelWorkflow('ManualParallel', workerConfigs);
|
|
276
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
277
|
+
|
|
278
|
+
console.log('Expected time: ~200ms (max of all workers)');
|
|
279
|
+
const start = Date.now();
|
|
280
|
+
await workflow.run();
|
|
281
|
+
const elapsed = Date.now() - start;
|
|
282
|
+
console.log(`Actual time: ${elapsed}ms`);
|
|
283
|
+
|
|
284
|
+
console.log('\nTree:');
|
|
285
|
+
console.log(debugger_.toTreeString());
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Part 3: @Task concurrent option
|
|
289
|
+
printSection('Part 3: @Task concurrent: true');
|
|
290
|
+
{
|
|
291
|
+
const workflow = new ConcurrentTaskWorkflow('TaskConcurrent', workerConfigs);
|
|
292
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
293
|
+
|
|
294
|
+
console.log('Expected time: ~200ms (using concurrent option)');
|
|
295
|
+
const start = Date.now();
|
|
296
|
+
await workflow.run();
|
|
297
|
+
const elapsed = Date.now() - start;
|
|
298
|
+
console.log(`Actual time: ${elapsed}ms`);
|
|
299
|
+
|
|
300
|
+
console.log('\nTree:');
|
|
301
|
+
console.log(debugger_.toTreeString());
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Part 4: Fan-out / Fan-in
|
|
305
|
+
printSection('Part 4: Fan-Out / Fan-In Pattern');
|
|
306
|
+
{
|
|
307
|
+
const workflow = new FanOutFanInWorkflow('FanOutFanIn');
|
|
308
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
309
|
+
|
|
310
|
+
const results = await workflow.run();
|
|
311
|
+
|
|
312
|
+
console.log('Results:', results);
|
|
313
|
+
console.log('\nTree:');
|
|
314
|
+
console.log(debugger_.toTreeString());
|
|
315
|
+
|
|
316
|
+
const stats = debugger_.getStats();
|
|
317
|
+
console.log('Statistics:', stats);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Part 5: Performance comparison summary
|
|
321
|
+
printSection('Part 5: Performance Summary');
|
|
322
|
+
{
|
|
323
|
+
const configs = [
|
|
324
|
+
{ id: 'A', time: 100 },
|
|
325
|
+
{ id: 'B', time: 100 },
|
|
326
|
+
{ id: 'C', time: 100 },
|
|
327
|
+
{ id: 'D', time: 100 },
|
|
328
|
+
];
|
|
329
|
+
|
|
330
|
+
// Sequential
|
|
331
|
+
const seq = new SequentialWorkflow('SeqTest', configs);
|
|
332
|
+
const seqStart = Date.now();
|
|
333
|
+
await seq.run();
|
|
334
|
+
const seqTime = Date.now() - seqStart;
|
|
335
|
+
|
|
336
|
+
// Parallel
|
|
337
|
+
const par = new ManualParallelWorkflow('ParTest', configs);
|
|
338
|
+
const parStart = Date.now();
|
|
339
|
+
await par.run();
|
|
340
|
+
const parTime = Date.now() - parStart;
|
|
341
|
+
|
|
342
|
+
console.log('4 workers x 100ms each:');
|
|
343
|
+
console.log(` Sequential: ${seqTime}ms`);
|
|
344
|
+
console.log(` Parallel: ${parTime}ms`);
|
|
345
|
+
console.log(` Speedup: ${(seqTime / parTime).toFixed(2)}x`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Run if executed directly
|
|
350
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
351
|
+
runConcurrentTasksExample().catch(console.error);
|
|
352
|
+
}
|