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.
Files changed (120) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.claude/system_prompts/task-breakdown.md +100 -0
  3. package/PRPs/001-hierarchical-workflow-engine.md +2438 -0
  4. package/PRPs/PRDs/001-hierarchical-workflow-engine.md +543 -0
  5. package/PRPs/PRDs/002-agent-prompt.md +390 -0
  6. package/PRPs/PRDs/003-agent-prompt.md +943 -0
  7. package/PRPs/PRDs/004-agent-prompt.md +1136 -0
  8. package/PRPs/PRDs/tasks-001.json +492 -0
  9. package/PRPs/README.md +83 -0
  10. package/PRPs/templates/prp_base.md +222 -0
  11. package/README.md +218 -0
  12. package/docs/agent.md +422 -0
  13. package/docs/prompt.md +419 -0
  14. package/docs/workflow.md +600 -0
  15. package/examples/README.md +244 -0
  16. package/examples/examples/01-basic-workflow.ts +100 -0
  17. package/examples/examples/02-decorator-options.ts +217 -0
  18. package/examples/examples/03-parent-child.ts +241 -0
  19. package/examples/examples/04-observers-debugger.ts +340 -0
  20. package/examples/examples/05-error-handling.ts +387 -0
  21. package/examples/examples/06-concurrent-tasks.ts +352 -0
  22. package/examples/examples/07-agent-loops.ts +432 -0
  23. package/examples/examples/08-sdk-features.ts +667 -0
  24. package/examples/examples/09-reflection.ts +573 -0
  25. package/examples/examples/10-introspection.ts +550 -0
  26. package/examples/index.ts +143 -0
  27. package/examples/utils/helpers.ts +57 -0
  28. package/llms_full.txt +5890 -0
  29. package/package.json +63 -0
  30. package/plan/P1P2/PRP.md +527 -0
  31. package/plan/P1P2/research/LRU_CACHE_BEST_PRACTICES.md +1929 -0
  32. package/plan/P1P2/research/LRU_CACHE_CODE_PATTERNS.md +857 -0
  33. package/plan/P1P2/research/LRU_CACHE_INTEGRATION_GUIDE.md +738 -0
  34. package/plan/P1P2/research/LRU_CACHE_RESEARCH_INDEX.md +424 -0
  35. package/plan/P1P2/research/REFLECTION_INDEX.md +291 -0
  36. package/plan/P1P2/research/REFLECTION_RESEARCH_REPORT.md +1342 -0
  37. package/plan/P1P2/research/RESEARCH_SUMMARY.md +342 -0
  38. package/plan/P1P2/research/anthropic-sdk.md +174 -0
  39. package/plan/P1P2/research/async-local-storage.md +200 -0
  40. package/plan/P1P2/research/reflection-code-patterns.md +1205 -0
  41. package/plan/P1P2/research/reflection-decision-matrix.md +421 -0
  42. package/plan/P1P2/research/reflection-implementation-guide.md +1341 -0
  43. package/plan/P1P2/research/reflection-integration-guide.md +834 -0
  44. package/plan/P1P2/research/reflection-patterns.md +1468 -0
  45. package/plan/P1P2/research/reflection-quick-reference.md +558 -0
  46. package/plan/P1P2/research/zod-schema.md +152 -0
  47. package/plan/P3P4/PRP.md +1388 -0
  48. package/plan/P3P4/research/caching-lru.md +116 -0
  49. package/plan/P3P4/research/introspection-tools.md +177 -0
  50. package/plan/P3P4/research/reflection-patterns.md +117 -0
  51. package/plan/P4P5/PRP.md +1136 -0
  52. package/plan/P4P5/research/RESEARCH_SUMMARY.md +151 -0
  53. package/plan/architecture/external_deps.md +358 -0
  54. package/plan/architecture/system_context.md +242 -0
  55. package/plan/backlog.json +867 -0
  56. package/plan/research/INTROSPECTION_RESEARCH_SUMMARY.md +378 -0
  57. package/plan/research/README-INTROSPECTION.md +352 -0
  58. package/plan/research/agent-introspection-patterns.md +1085 -0
  59. package/plan/research/introspection-security-guide.md +928 -0
  60. package/plan/research/introspection-tool-examples.md +875 -0
  61. package/scripts/generate-llms-full.ts +206 -0
  62. package/src/__tests__/integration/agent-workflow.test.ts +256 -0
  63. package/src/__tests__/integration/tree-mirroring.test.ts +114 -0
  64. package/src/__tests__/unit/agent.test.ts +169 -0
  65. package/src/__tests__/unit/cache-key.test.ts +182 -0
  66. package/src/__tests__/unit/cache.test.ts +172 -0
  67. package/src/__tests__/unit/context.test.ts +138 -0
  68. package/src/__tests__/unit/decorators.test.ts +100 -0
  69. package/src/__tests__/unit/introspection-tools.test.ts +277 -0
  70. package/src/__tests__/unit/prompt.test.ts +135 -0
  71. package/src/__tests__/unit/reflection.test.ts +210 -0
  72. package/src/__tests__/unit/tree-debugger.test.ts +85 -0
  73. package/src/__tests__/unit/workflow.test.ts +81 -0
  74. package/src/cache/cache-key.ts +244 -0
  75. package/src/cache/cache.ts +236 -0
  76. package/src/cache/index.ts +8 -0
  77. package/src/core/agent.ts +573 -0
  78. package/src/core/context.ts +119 -0
  79. package/src/core/event-tree.ts +260 -0
  80. package/src/core/factory.ts +123 -0
  81. package/src/core/index.ts +17 -0
  82. package/src/core/logger.ts +87 -0
  83. package/src/core/mcp-handler.ts +184 -0
  84. package/src/core/prompt.ts +150 -0
  85. package/src/core/workflow-context.ts +349 -0
  86. package/src/core/workflow.ts +302 -0
  87. package/src/debugger/index.ts +1 -0
  88. package/src/debugger/tree-debugger.ts +210 -0
  89. package/src/decorators/index.ts +3 -0
  90. package/src/decorators/observed-state.ts +95 -0
  91. package/src/decorators/step.ts +139 -0
  92. package/src/decorators/task.ts +96 -0
  93. package/src/examples/index.ts +2 -0
  94. package/src/examples/tdd-orchestrator.ts +65 -0
  95. package/src/examples/test-cycle-workflow.ts +64 -0
  96. package/src/index.ts +140 -0
  97. package/src/reflection/index.ts +5 -0
  98. package/src/reflection/reflection.ts +407 -0
  99. package/src/tools/index.ts +36 -0
  100. package/src/tools/introspection.ts +464 -0
  101. package/src/types/agent.ts +90 -0
  102. package/src/types/decorators.ts +25 -0
  103. package/src/types/error-strategy.ts +13 -0
  104. package/src/types/error.ts +20 -0
  105. package/src/types/events.ts +74 -0
  106. package/src/types/index.ts +55 -0
  107. package/src/types/logging.ts +24 -0
  108. package/src/types/observer.ts +18 -0
  109. package/src/types/prompt.ts +40 -0
  110. package/src/types/reflection.ts +117 -0
  111. package/src/types/sdk-primitives.ts +128 -0
  112. package/src/types/snapshot.ts +14 -0
  113. package/src/types/workflow-context.ts +163 -0
  114. package/src/types/workflow.ts +37 -0
  115. package/src/utils/id.ts +11 -0
  116. package/src/utils/index.ts +3 -0
  117. package/src/utils/observable.ts +77 -0
  118. package/tasks.json +0 -0
  119. package/tsconfig.json +22 -0
  120. package/vitest.config.ts +16 -0
@@ -0,0 +1,667 @@
1
+ /**
2
+ * Example 8: SDK Features Integration
3
+ *
4
+ * Demonstrates:
5
+ * - Custom tool definitions with handlers
6
+ * - MCP server configuration (inprocess)
7
+ * - Pre/Post tool hooks for logging and validation
8
+ * - Skills integration with system prompt content
9
+ * - Environment variable pass-through
10
+ */
11
+
12
+ import { z } from 'zod';
13
+ import {
14
+ Workflow,
15
+ Step,
16
+ ObservedState,
17
+ WorkflowTreeDebugger,
18
+ MCPHandler,
19
+ } from 'groundswell';
20
+ import type {
21
+ Tool,
22
+ AgentHooks,
23
+ PreToolUseContext,
24
+ PostToolUseContext,
25
+ SessionStartContext,
26
+ SessionEndContext,
27
+ } from 'groundswell';
28
+ import { printHeader, printSection, sleep } from '../utils/helpers.js';
29
+
30
+ // ============================================================================
31
+ // Custom Tool Definitions
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Calculator tool - performs basic arithmetic
36
+ */
37
+ const calculatorTool: Tool = {
38
+ name: 'calculate',
39
+ description: 'Performs basic arithmetic operations (add, subtract, multiply, divide)',
40
+ input_schema: {
41
+ type: 'object' as const,
42
+ properties: {
43
+ operation: {
44
+ type: 'string',
45
+ enum: ['add', 'subtract', 'multiply', 'divide'],
46
+ description: 'The arithmetic operation to perform',
47
+ },
48
+ a: {
49
+ type: 'number',
50
+ description: 'The first operand',
51
+ },
52
+ b: {
53
+ type: 'number',
54
+ description: 'The second operand',
55
+ },
56
+ },
57
+ required: ['operation', 'a', 'b'],
58
+ },
59
+ };
60
+
61
+ /**
62
+ * Weather tool - simulates weather lookup
63
+ */
64
+ const weatherTool: Tool = {
65
+ name: 'get_weather',
66
+ description: 'Gets current weather for a location',
67
+ input_schema: {
68
+ type: 'object' as const,
69
+ properties: {
70
+ location: {
71
+ type: 'string',
72
+ description: 'City name or location',
73
+ },
74
+ units: {
75
+ type: 'string',
76
+ enum: ['celsius', 'fahrenheit'],
77
+ description: 'Temperature units',
78
+ },
79
+ },
80
+ required: ['location'],
81
+ },
82
+ };
83
+
84
+ /**
85
+ * Database tool - simulates database queries
86
+ */
87
+ const databaseTool: Tool = {
88
+ name: 'query_database',
89
+ description: 'Executes a database query and returns results',
90
+ input_schema: {
91
+ type: 'object' as const,
92
+ properties: {
93
+ table: {
94
+ type: 'string',
95
+ description: 'Table name to query',
96
+ },
97
+ filter: {
98
+ type: 'object',
99
+ description: 'Filter conditions',
100
+ },
101
+ limit: {
102
+ type: 'number',
103
+ description: 'Maximum results to return',
104
+ },
105
+ },
106
+ required: ['table'],
107
+ },
108
+ };
109
+
110
+ // ============================================================================
111
+ // Tool Handlers
112
+ // ============================================================================
113
+
114
+ interface CalculateInput {
115
+ operation: 'add' | 'subtract' | 'multiply' | 'divide';
116
+ a: number;
117
+ b: number;
118
+ }
119
+
120
+ interface WeatherInput {
121
+ location: string;
122
+ units?: 'celsius' | 'fahrenheit';
123
+ }
124
+
125
+ interface DatabaseInput {
126
+ table: string;
127
+ filter?: Record<string, unknown>;
128
+ limit?: number;
129
+ }
130
+
131
+ /**
132
+ * Handle calculator operations
133
+ */
134
+ async function handleCalculate(input: CalculateInput): Promise<{ result: number; expression: string }> {
135
+ await sleep(50); // Simulate processing time
136
+
137
+ let result: number;
138
+ let expression: string;
139
+
140
+ switch (input.operation) {
141
+ case 'add':
142
+ result = input.a + input.b;
143
+ expression = `${input.a} + ${input.b} = ${result}`;
144
+ break;
145
+ case 'subtract':
146
+ result = input.a - input.b;
147
+ expression = `${input.a} - ${input.b} = ${result}`;
148
+ break;
149
+ case 'multiply':
150
+ result = input.a * input.b;
151
+ expression = `${input.a} × ${input.b} = ${result}`;
152
+ break;
153
+ case 'divide':
154
+ if (input.b === 0) throw new Error('Division by zero');
155
+ result = input.a / input.b;
156
+ expression = `${input.a} ÷ ${input.b} = ${result}`;
157
+ break;
158
+ }
159
+
160
+ return { result, expression };
161
+ }
162
+
163
+ /**
164
+ * Handle weather lookup (simulated)
165
+ */
166
+ async function handleWeather(input: WeatherInput): Promise<{
167
+ location: string;
168
+ temperature: number;
169
+ units: string;
170
+ conditions: string;
171
+ }> {
172
+ await sleep(100); // Simulate API call
173
+
174
+ const weatherData: Record<string, { temp: number; conditions: string }> = {
175
+ 'new york': { temp: 72, conditions: 'Partly cloudy' },
176
+ london: { temp: 58, conditions: 'Rainy' },
177
+ tokyo: { temp: 85, conditions: 'Sunny' },
178
+ sydney: { temp: 68, conditions: 'Clear' },
179
+ };
180
+
181
+ const locationKey = input.location.toLowerCase();
182
+ const data = weatherData[locationKey] ?? { temp: 70, conditions: 'Unknown' };
183
+
184
+ const temp =
185
+ input.units === 'celsius' ? Math.round((data.temp - 32) * (5 / 9)) : data.temp;
186
+
187
+ return {
188
+ location: input.location,
189
+ temperature: temp,
190
+ units: input.units ?? 'fahrenheit',
191
+ conditions: data.conditions,
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Handle database queries (simulated)
197
+ */
198
+ async function handleDatabase(input: DatabaseInput): Promise<{
199
+ table: string;
200
+ rowCount: number;
201
+ results: Array<Record<string, unknown>>;
202
+ }> {
203
+ await sleep(75); // Simulate query time
204
+
205
+ const mockData: Record<string, Array<Record<string, unknown>>> = {
206
+ users: [
207
+ { id: 1, name: 'Alice', role: 'admin' },
208
+ { id: 2, name: 'Bob', role: 'user' },
209
+ { id: 3, name: 'Charlie', role: 'user' },
210
+ ],
211
+ products: [
212
+ { id: 1, name: 'Widget', price: 9.99 },
213
+ { id: 2, name: 'Gadget', price: 19.99 },
214
+ ],
215
+ orders: [
216
+ { id: 1, userId: 1, total: 29.98 },
217
+ { id: 2, userId: 2, total: 9.99 },
218
+ ],
219
+ };
220
+
221
+ const tableData = mockData[input.table] ?? [];
222
+ const limit = input.limit ?? tableData.length;
223
+ const results = tableData.slice(0, limit);
224
+
225
+ return {
226
+ table: input.table,
227
+ rowCount: results.length,
228
+ results,
229
+ };
230
+ }
231
+
232
+ // ============================================================================
233
+ // Lifecycle Hooks
234
+ // ============================================================================
235
+
236
+ /**
237
+ * Create comprehensive agent hooks for logging and validation
238
+ */
239
+ function createLoggingHooks(): AgentHooks {
240
+ const hookLogs: string[] = [];
241
+
242
+ return {
243
+ preToolUse: [
244
+ async (ctx: PreToolUseContext): Promise<void> => {
245
+ const log = `[PRE] Tool: ${ctx.toolName}, Input: ${JSON.stringify(ctx.toolInput)}`;
246
+ hookLogs.push(log);
247
+ console.log(` ${log}`);
248
+ },
249
+ async (ctx: PreToolUseContext): Promise<void> => {
250
+ // Validation hook - could block execution if needed
251
+ if (ctx.toolName === 'calculate') {
252
+ const input = ctx.toolInput as CalculateInput;
253
+ if (input.operation === 'divide' && input.b === 0) {
254
+ console.log(' [PRE] WARNING: Division by zero detected');
255
+ }
256
+ }
257
+ },
258
+ ],
259
+ postToolUse: [
260
+ async (ctx: PostToolUseContext): Promise<void> => {
261
+ const log = `[POST] Tool: ${ctx.toolName}, Duration: ${ctx.duration}ms`;
262
+ hookLogs.push(log);
263
+ console.log(` ${log}`);
264
+ },
265
+ async (ctx: PostToolUseContext): Promise<void> => {
266
+ // Metrics collection hook
267
+ const output = ctx.toolOutput as Record<string, unknown>;
268
+ if (output.result !== undefined) {
269
+ console.log(` [POST] Result: ${output.result}`);
270
+ }
271
+ },
272
+ ],
273
+ sessionStart: [
274
+ async (ctx: SessionStartContext): Promise<void> => {
275
+ console.log(` [SESSION] Started: Agent ${ctx.agentName} (${ctx.agentId})`);
276
+ hookLogs.push(`Session started: ${ctx.agentName}`);
277
+ },
278
+ ],
279
+ sessionEnd: [
280
+ async (ctx: SessionEndContext): Promise<void> => {
281
+ console.log(` [SESSION] Ended: Agent ${ctx.agentName}, Duration: ${ctx.totalDuration}ms`);
282
+ hookLogs.push(`Session ended: ${ctx.agentName} (${ctx.totalDuration}ms)`);
283
+ },
284
+ ],
285
+ };
286
+ }
287
+
288
+ // ============================================================================
289
+ // Workflow Definitions
290
+ // ============================================================================
291
+
292
+ /**
293
+ * Tool demonstration workflow
294
+ */
295
+ class ToolDemoWorkflow extends Workflow {
296
+ @ObservedState()
297
+ toolCalls: Array<{ tool: string; input: unknown; result: unknown }> = [];
298
+
299
+ private mcpHandler: MCPHandler;
300
+
301
+ constructor(name: string) {
302
+ super(name);
303
+ this.mcpHandler = new MCPHandler();
304
+
305
+ // Register MCP server with tools (inprocess transport)
306
+ this.mcpHandler.registerServer({
307
+ name: 'demo',
308
+ transport: 'inprocess',
309
+ tools: [calculatorTool, weatherTool, databaseTool],
310
+ });
311
+
312
+ // Register tool executors
313
+ this.mcpHandler.registerToolExecutor('demo', 'calculate', (input) =>
314
+ handleCalculate(input as CalculateInput)
315
+ );
316
+ this.mcpHandler.registerToolExecutor('demo', 'get_weather', (input) =>
317
+ handleWeather(input as WeatherInput)
318
+ );
319
+ this.mcpHandler.registerToolExecutor('demo', 'query_database', (input) =>
320
+ handleDatabase(input as DatabaseInput)
321
+ );
322
+ }
323
+
324
+ @Step({ trackTiming: true })
325
+ async callTool(toolName: string, input: unknown): Promise<unknown> {
326
+ this.logger.info(`Calling tool: ${toolName}`);
327
+
328
+ // Use full tool name: serverName__toolName
329
+ const fullName = `demo__${toolName}`;
330
+ const result = await this.mcpHandler.executeTool(fullName, input);
331
+
332
+ this.toolCalls.push({ tool: toolName, input, result: result.content });
333
+ return result.content;
334
+ }
335
+
336
+ async run(): Promise<void> {
337
+ this.setStatus('running');
338
+ this.logger.info('Starting tool demonstration');
339
+
340
+ // Demonstrate calculator tool
341
+ await this.callTool('calculate', { operation: 'add', a: 10, b: 5 });
342
+ await this.callTool('calculate', { operation: 'multiply', a: 7, b: 8 });
343
+
344
+ // Demonstrate weather tool
345
+ await this.callTool('get_weather', { location: 'Tokyo', units: 'celsius' });
346
+ await this.callTool('get_weather', { location: 'London' });
347
+
348
+ // Demonstrate database tool
349
+ await this.callTool('query_database', { table: 'users', limit: 2 });
350
+ await this.callTool('query_database', { table: 'products' });
351
+
352
+ this.logger.info(`Total tool calls: ${this.toolCalls.length}`);
353
+ this.setStatus('completed');
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Hook demonstration workflow
359
+ */
360
+ class HookDemoWorkflow extends Workflow {
361
+ @ObservedState()
362
+ hookEvents: string[] = [];
363
+
364
+ private mcpHandler: MCPHandler;
365
+
366
+ constructor(name: string) {
367
+ super(name);
368
+ this.mcpHandler = new MCPHandler();
369
+
370
+ // Register MCP server with calculator tool
371
+ this.mcpHandler.registerServer({
372
+ name: 'calc',
373
+ transport: 'inprocess',
374
+ tools: [calculatorTool],
375
+ });
376
+ this.mcpHandler.registerToolExecutor('calc', 'calculate', (input) =>
377
+ handleCalculate(input as CalculateInput)
378
+ );
379
+ }
380
+
381
+ @Step({ trackTiming: true, logStart: true, logFinish: true })
382
+ async executeWithHooks(): Promise<void> {
383
+ // Simulate hook execution flow
384
+ this.hookEvents.push('preToolUse: calculate');
385
+ const result = await handleCalculate({ operation: 'add', a: 100, b: 200 });
386
+ this.hookEvents.push(`postToolUse: calculate (result=${result.result})`);
387
+ }
388
+
389
+ async run(): Promise<void> {
390
+ this.setStatus('running');
391
+ this.logger.info('Demonstrating lifecycle hooks');
392
+
393
+ this.hookEvents.push('sessionStart');
394
+ await this.executeWithHooks();
395
+ this.hookEvents.push('sessionEnd');
396
+
397
+ this.logger.info(`Hook events: ${this.hookEvents.length}`);
398
+ this.setStatus('completed');
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Skills demonstration workflow
404
+ */
405
+ class SkillsDemoWorkflow extends Workflow {
406
+ @ObservedState()
407
+ skillContent: string = '';
408
+
409
+ @ObservedState()
410
+ systemPrompt: string = '';
411
+
412
+ constructor(name: string) {
413
+ super(name);
414
+ }
415
+
416
+ @Step({ snapshotState: true })
417
+ async loadSkill(): Promise<void> {
418
+ // Simulate loading skill content from SKILL.md
419
+ this.skillContent = `
420
+ # Math Expert Skill
421
+
422
+ You are an expert mathematician. You can:
423
+ - Perform complex calculations
424
+ - Explain mathematical concepts
425
+ - Solve equations step by step
426
+
427
+ ## Usage
428
+ Ask me any math question and I'll provide a detailed solution.
429
+ `.trim();
430
+
431
+ this.logger.info('Loaded skill: Math Expert');
432
+ }
433
+
434
+ @Step({ snapshotState: true })
435
+ async buildSystemPrompt(): Promise<void> {
436
+ const baseSystem = 'You are a helpful assistant.';
437
+
438
+ // Skills inject content into system prompt
439
+ this.systemPrompt = `${baseSystem}
440
+
441
+ ## Available Skills
442
+
443
+ ${this.skillContent}
444
+
445
+ ## Instructions
446
+ Use the loaded skills to assist the user with their requests.`;
447
+
448
+ this.logger.info('Built system prompt with skill content');
449
+ }
450
+
451
+ async run(): Promise<string> {
452
+ this.setStatus('running');
453
+ this.logger.info('Demonstrating skills integration');
454
+
455
+ await this.loadSkill();
456
+ await this.buildSystemPrompt();
457
+
458
+ this.logger.info(`System prompt length: ${this.systemPrompt.length} chars`);
459
+ this.setStatus('completed');
460
+
461
+ return this.systemPrompt;
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Environment variables demonstration workflow
467
+ */
468
+ class EnvVarsDemoWorkflow extends Workflow {
469
+ @ObservedState()
470
+ capturedEnvVars: Record<string, string> = {};
471
+
472
+ @ObservedState({ redact: true })
473
+ sensitiveVars: Record<string, string> = {};
474
+
475
+ constructor(name: string) {
476
+ super(name);
477
+ }
478
+
479
+ @Step({ snapshotState: true })
480
+ async captureEnvironment(): Promise<void> {
481
+ // Capture non-sensitive environment info
482
+ this.capturedEnvVars = {
483
+ NODE_ENV: process.env.NODE_ENV ?? 'development',
484
+ PWD: process.env.PWD ?? '(unknown)',
485
+ SHELL: process.env.SHELL ?? '(unknown)',
486
+ };
487
+
488
+ // Simulate sensitive vars (would be passed to agent)
489
+ this.sensitiveVars = {
490
+ API_KEY: 'demo-key-12345',
491
+ DATABASE_URL: 'postgres://localhost:5432/demo',
492
+ };
493
+
494
+ this.logger.info('Captured environment variables');
495
+ }
496
+
497
+ @Step()
498
+ async demonstratePassThrough(): Promise<void> {
499
+ // In real usage, env vars are passed through to agent execution
500
+ this.logger.info('Environment vars would be set during agent execution');
501
+ this.logger.info(`Non-sensitive vars: ${Object.keys(this.capturedEnvVars).join(', ')}`);
502
+ this.logger.info(`Sensitive vars (redacted): ${Object.keys(this.sensitiveVars).length} vars`);
503
+ }
504
+
505
+ async run(): Promise<void> {
506
+ this.setStatus('running');
507
+ this.logger.info('Demonstrating environment variable handling');
508
+
509
+ await this.captureEnvironment();
510
+ await this.demonstratePassThrough();
511
+
512
+ this.setStatus('completed');
513
+ }
514
+ }
515
+
516
+ // ============================================================================
517
+ // Main Example Runner
518
+ // ============================================================================
519
+
520
+ /**
521
+ * Run the SDK Features example
522
+ */
523
+ export async function runSDKFeaturesExample(): Promise<void> {
524
+ printHeader('Example 8: SDK Features Integration');
525
+
526
+ // Part 1: Custom Tool Definitions
527
+ printSection('Part 1: Custom Tool Definitions & Handlers');
528
+ {
529
+ const workflow = new ToolDemoWorkflow('ToolDemo');
530
+ const debugger_ = new WorkflowTreeDebugger(workflow);
531
+
532
+ console.log('Registered tools:');
533
+ console.log(' - calculate: Basic arithmetic operations');
534
+ console.log(' - get_weather: Weather lookup (simulated)');
535
+ console.log(' - query_database: Database queries (simulated)\n');
536
+
537
+ await workflow.run();
538
+
539
+ console.log('\nTool call results:');
540
+ for (const call of workflow.toolCalls) {
541
+ console.log(` ${call.tool}: ${JSON.stringify(call.result)}`);
542
+ }
543
+
544
+ console.log('\nTree:');
545
+ console.log(debugger_.toTreeString());
546
+ }
547
+
548
+ // Part 2: MCP Server Integration
549
+ printSection('Part 2: MCP Handler / In-Process Server');
550
+ {
551
+ console.log('MCP Handler features:');
552
+ console.log(' - Register servers with tools (registerServer)');
553
+ console.log(' - Register executors for inprocess tools (registerToolExecutor)');
554
+ console.log(' - Execute tools by full name: serverName__toolName');
555
+ console.log(' - Return structured ToolResult objects');
556
+ console.log(' - Error handling with is_error flag\n');
557
+
558
+ const mcpHandler = new MCPHandler();
559
+
560
+ // Register server with tool
561
+ const demoTool: Tool = {
562
+ name: 'demo_tool',
563
+ description: 'A demonstration tool',
564
+ input_schema: {
565
+ type: 'object' as const,
566
+ properties: { test: { type: 'string' } },
567
+ required: [],
568
+ },
569
+ };
570
+
571
+ mcpHandler.registerServer({
572
+ name: 'demo',
573
+ transport: 'inprocess',
574
+ tools: [demoTool],
575
+ });
576
+
577
+ mcpHandler.registerToolExecutor('demo', 'demo_tool', async (input: unknown) => ({
578
+ status: 'success',
579
+ input,
580
+ }));
581
+
582
+ const tools = mcpHandler.getTools();
583
+ console.log(`Registered tools count: ${tools.length}`);
584
+
585
+ // Execute using full name: serverName__toolName
586
+ const result = await mcpHandler.executeTool('demo__demo_tool', { test: 'data' });
587
+ console.log(`Execution result: ${JSON.stringify(result)}`);
588
+ }
589
+
590
+ // Part 3: Lifecycle Hooks
591
+ printSection('Part 3: Lifecycle Hooks (Pre/Post Tool, Session)');
592
+ {
593
+ console.log('Hook types demonstrated:');
594
+ console.log(' - preToolUse: Log input, validate parameters');
595
+ console.log(' - postToolUse: Log duration, collect metrics');
596
+ console.log(' - sessionStart: Initialize session context');
597
+ console.log(' - sessionEnd: Cleanup, final metrics\n');
598
+
599
+ const workflow = new HookDemoWorkflow('HookDemo');
600
+ const debugger_ = new WorkflowTreeDebugger(workflow);
601
+
602
+ await workflow.run();
603
+
604
+ console.log('\nHook events captured:');
605
+ for (const event of workflow.hookEvents) {
606
+ console.log(` → ${event}`);
607
+ }
608
+
609
+ console.log('\nTree:');
610
+ console.log(debugger_.toTreeString());
611
+ }
612
+
613
+ // Part 4: Skills Integration
614
+ printSection('Part 4: Skills Integration');
615
+ {
616
+ console.log('Skills system:');
617
+ console.log(' - Load SKILL.md content from skill directories');
618
+ console.log(' - Inject skill content into system prompt');
619
+ console.log(' - Multiple skills can be combined\n');
620
+
621
+ const workflow = new SkillsDemoWorkflow('SkillsDemo');
622
+ const debugger_ = new WorkflowTreeDebugger(workflow);
623
+
624
+ const systemPrompt = await workflow.run();
625
+
626
+ console.log('Generated system prompt preview:');
627
+ console.log('─'.repeat(50));
628
+ console.log(systemPrompt.slice(0, 300) + '...');
629
+ console.log('─'.repeat(50));
630
+
631
+ console.log('\nTree:');
632
+ console.log(debugger_.toTreeString());
633
+ }
634
+
635
+ // Part 5: Environment Variables
636
+ printSection('Part 5: Environment Variable Pass-Through');
637
+ {
638
+ console.log('Environment handling:');
639
+ console.log(' - Pass env vars to agent execution context');
640
+ console.log(' - Sensitive vars marked with @ObservedState({ redact: true })');
641
+ console.log(' - Vars restored after execution\n');
642
+
643
+ const workflow = new EnvVarsDemoWorkflow('EnvVarsDemo');
644
+ const debugger_ = new WorkflowTreeDebugger(workflow);
645
+
646
+ await workflow.run();
647
+
648
+ console.log('\nCaptured environment:');
649
+ for (const [key, value] of Object.entries(workflow.capturedEnvVars)) {
650
+ console.log(` ${key}: ${value}`);
651
+ }
652
+
653
+ // Get state snapshot to show redaction
654
+ const logs = debugger_.getAllLogs();
655
+ console.log(`\nLog entries: ${logs.length}`);
656
+
657
+ console.log('\nTree:');
658
+ console.log(debugger_.toTreeString());
659
+ }
660
+
661
+ console.log('\n=== Example 8 Complete ===');
662
+ }
663
+
664
+ // Allow direct execution
665
+ if (import.meta.url === `file://${process.argv[1]}`) {
666
+ runSDKFeaturesExample().catch(console.error);
667
+ }