@ebowwa/daemons 0.5.0

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 (42) hide show
  1. package/README.md +264 -0
  2. package/dist/bin/discord-cli.js +124118 -0
  3. package/dist/bin/manager.js +143 -0
  4. package/dist/bin/telegram-cli.js +124114 -0
  5. package/dist/index.js +125340 -0
  6. package/package.json +94 -0
  7. package/src/agent.ts +111 -0
  8. package/src/channels/base.ts +573 -0
  9. package/src/channels/discord.ts +306 -0
  10. package/src/channels/index.ts +169 -0
  11. package/src/channels/telegram.ts +315 -0
  12. package/src/daemon.ts +534 -0
  13. package/src/hooks.ts +97 -0
  14. package/src/index.ts +111 -0
  15. package/src/memory.ts +369 -0
  16. package/src/skills/coding/commit.ts +202 -0
  17. package/src/skills/coding/execute-subtask.ts +136 -0
  18. package/src/skills/coding/fix-issues.ts +126 -0
  19. package/src/skills/coding/index.ts +26 -0
  20. package/src/skills/coding/plan-task.ts +158 -0
  21. package/src/skills/coding/quality-check.ts +155 -0
  22. package/src/skills/index.ts +65 -0
  23. package/src/skills/registry.ts +380 -0
  24. package/src/skills/shared/index.ts +21 -0
  25. package/src/skills/shared/reflect.ts +156 -0
  26. package/src/skills/shared/review.ts +201 -0
  27. package/src/skills/shared/trajectory.ts +319 -0
  28. package/src/skills/trading/analyze-market.ts +144 -0
  29. package/src/skills/trading/check-risk.ts +176 -0
  30. package/src/skills/trading/execute-trade.ts +185 -0
  31. package/src/skills/trading/generate-signal.ts +160 -0
  32. package/src/skills/trading/index.ts +26 -0
  33. package/src/skills/trading/monitor-position.ts +179 -0
  34. package/src/skills/types.ts +235 -0
  35. package/src/skills/workflows.ts +340 -0
  36. package/src/state.ts +77 -0
  37. package/src/tools.ts +134 -0
  38. package/src/types.ts +314 -0
  39. package/src/workflow.ts +341 -0
  40. package/src/workflows/coding.ts +580 -0
  41. package/src/workflows/index.ts +61 -0
  42. package/src/workflows/trading.ts +608 -0
@@ -0,0 +1,608 @@
1
+ /**
2
+ * GLM Daemon - Trading Workflow
3
+ *
4
+ * Trading workflow for automated market analysis and execution.
5
+ * Phases: analyzing → signaling → risk_checking → executing → monitoring → complete
6
+ *
7
+ * Key differences from coding workflow:
8
+ * - No git state (trading doesn't need commits/PRs)
9
+ * - Focus on market signals and risk management
10
+ * - Real-time monitoring loops
11
+ */
12
+
13
+ import {
14
+ BaseWorkflow,
15
+ type GLMWorkflowConfig,
16
+ type GLMWorkflowContext,
17
+ type GLMWorkflowPhaseResult,
18
+ type GLMWorkflowPhase,
19
+ type GLMWorkflowTransition,
20
+ } from "../workflow.js";
21
+
22
+ /**
23
+ * Trading workflow phases
24
+ */
25
+ export type TradingPhase =
26
+ | "analyzing"
27
+ | "signaling"
28
+ | "risk_checking"
29
+ | "executing"
30
+ | "monitoring"
31
+ | "reflecting"
32
+ | "complete";
33
+
34
+ /**
35
+ * Trading workflow phases definition
36
+ */
37
+ export const TRADING_PHASES: GLMWorkflowPhase<TradingPhase>[] = [
38
+ {
39
+ name: "analyzing",
40
+ label: "Analyzing",
41
+ description: "Analyze market conditions and identify opportunities",
42
+ skippable: false,
43
+ timeout: 120000, // 2 minutes for analysis
44
+ },
45
+ {
46
+ name: "signaling",
47
+ label: "Signaling",
48
+ description: "Generate trading signals based on analysis",
49
+ skippable: false,
50
+ timeout: 60000,
51
+ },
52
+ {
53
+ name: "risk_checking",
54
+ label: "Risk Checking",
55
+ description: "Evaluate risk and validate signal before execution",
56
+ skippable: false,
57
+ timeout: 30000,
58
+ },
59
+ {
60
+ name: "executing",
61
+ label: "Executing",
62
+ description: "Execute trades according to validated signals",
63
+ skippable: false,
64
+ timeout: 30000, // Quick execution needed
65
+ },
66
+ {
67
+ name: "monitoring",
68
+ label: "Monitoring",
69
+ description: "Monitor open positions and market conditions",
70
+ skippable: false,
71
+ },
72
+ {
73
+ name: "reflecting",
74
+ label: "Reflecting",
75
+ description: "Review performance and lessons learned",
76
+ skippable: true,
77
+ },
78
+ {
79
+ name: "complete",
80
+ label: "Complete",
81
+ description: "Trading session finished",
82
+ skippable: false,
83
+ },
84
+ ];
85
+
86
+ /**
87
+ * Trading workflow transition rules
88
+ */
89
+ export const TRADING_TRANSITIONS: GLMWorkflowTransition<TradingPhase>[] = [
90
+ // Analyzing -> Signaling (always)
91
+ {
92
+ from: "analyzing",
93
+ to: "signaling",
94
+ priority: 100,
95
+ },
96
+ // Signaling -> Risk Checking (always)
97
+ {
98
+ from: "signaling",
99
+ to: "risk_checking",
100
+ priority: 100,
101
+ },
102
+ // Risk Checking -> Executing (if risk approved)
103
+ {
104
+ from: "risk_checking",
105
+ to: "executing",
106
+ priority: 100,
107
+ condition: async (ctx) => {
108
+ return ctx.custom.riskApproved === true;
109
+ },
110
+ },
111
+ // Risk Checking -> Analyzing (if risk rejected - re-analyze)
112
+ {
113
+ from: "risk_checking",
114
+ to: "analyzing",
115
+ priority: 90,
116
+ condition: async (ctx) => {
117
+ return ctx.custom.riskApproved === false;
118
+ },
119
+ },
120
+ // Executing -> Monitoring (always)
121
+ {
122
+ from: "executing",
123
+ to: "monitoring",
124
+ priority: 100,
125
+ },
126
+ // Monitoring -> Complete (if target reached or stop loss)
127
+ {
128
+ from: "monitoring",
129
+ to: "complete",
130
+ priority: 100,
131
+ condition: async (ctx) => {
132
+ return ctx.custom.targetReached === true || ctx.custom.stopLoss === true;
133
+ },
134
+ },
135
+ // Monitoring -> Analyzing (if position closed - look for new opportunities)
136
+ {
137
+ from: "monitoring",
138
+ to: "analyzing",
139
+ priority: 90,
140
+ condition: async (ctx) => {
141
+ return ctx.custom.positionClosed === true;
142
+ },
143
+ },
144
+ // Monitoring -> Reflecting (periodic checkpoint)
145
+ {
146
+ from: "monitoring",
147
+ to: "reflecting",
148
+ priority: 80,
149
+ condition: async (ctx) => {
150
+ // Reflect every N iterations
151
+ return ctx.state.iteration % 10 === 0;
152
+ },
153
+ },
154
+ // Monitoring -> Monitoring (continue monitoring)
155
+ {
156
+ from: "monitoring",
157
+ to: "monitoring",
158
+ priority: 60,
159
+ },
160
+ // Reflecting -> Monitoring
161
+ {
162
+ from: "reflecting",
163
+ to: "monitoring",
164
+ priority: 100,
165
+ },
166
+ ];
167
+
168
+ /**
169
+ * Trading workflow configuration
170
+ */
171
+ export const TRADING_WORKFLOW_CONFIG: GLMWorkflowConfig<TradingPhase> = {
172
+ id: "trading",
173
+ name: "Trading Workflow",
174
+ description: "Trading workflow for automated market analysis and execution",
175
+ phases: TRADING_PHASES,
176
+ initialPhase: "analyzing",
177
+ terminalPhases: ["complete"],
178
+ transitions: TRADING_TRANSITIONS,
179
+ defaultOrder: ["analyzing", "signaling", "risk_checking", "executing", "monitoring", "complete"],
180
+ reflectionPhase: "reflecting",
181
+ systemPromptExtensions: `You are a trading assistant.
182
+ Follow risk management rules strictly.
183
+ Never exceed position size limits.
184
+ Always use stop-loss orders.
185
+ No git operations are needed - focus on market execution.`,
186
+ };
187
+
188
+ /**
189
+ * Trading Workflow implementation
190
+ */
191
+ export class TradingWorkflow extends BaseWorkflow<TradingPhase> {
192
+ constructor() {
193
+ super(TRADING_WORKFLOW_CONFIG);
194
+ }
195
+
196
+ /**
197
+ * Build system prompt for trading context
198
+ */
199
+ buildSystemPrompt(context: GLMWorkflowContext): string {
200
+ const basePrompt = super.buildSystemPrompt(context);
201
+
202
+ // Add trading-specific context
203
+ const tradingContext = `
204
+ Trading Context:
205
+ - Risk Level: ${context.custom.riskLevel || "medium"}
206
+ - Position Limit: ${context.custom.positionLimit || 1}
207
+ - Current P&L: ${context.custom.currentPnL || "N/A"}
208
+ `;
209
+
210
+ return basePrompt + tradingContext;
211
+ }
212
+
213
+ /**
214
+ * Execute a trading phase
215
+ */
216
+ async executePhase(phase: string, context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
217
+ switch (phase as TradingPhase) {
218
+ case "analyzing":
219
+ return this.phaseAnalyzing(context);
220
+ case "signaling":
221
+ return this.phaseSignaling(context);
222
+ case "risk_checking":
223
+ return this.phaseRiskChecking(context);
224
+ case "executing":
225
+ return this.phaseExecuting(context);
226
+ case "monitoring":
227
+ return this.phaseMonitoring(context);
228
+ case "reflecting":
229
+ return this.phaseReflecting(context);
230
+ case "complete":
231
+ return this.phaseComplete(context);
232
+ default:
233
+ throw new Error(`Unknown phase: ${phase}`);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Analyzing phase - analyze market conditions
239
+ */
240
+ private async phaseAnalyzing(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
241
+ console.log("[TradingWorkflow] Phase: Analyzing market conditions");
242
+
243
+ const prompt = `Analyze current market conditions for trading.
244
+
245
+ Task: ${context.state.prompt}
246
+
247
+ Consider:
248
+ - Price action and trends
249
+ - Volume analysis
250
+ - Technical indicators (RSI, MACD, Moving Averages)
251
+ - Market sentiment
252
+ - News and events
253
+ - Support and resistance levels
254
+
255
+ Provide a structured analysis in JSON format:
256
+ {
257
+ "trend": "bullish|bearish|sideways",
258
+ "confidence": 0-100,
259
+ "keyLevels": {
260
+ "support": ["price levels"],
261
+ "resistance": ["price levels"]
262
+ },
263
+ "indicators": {
264
+ "rsi": number,
265
+ "macd": "bullish|bearish|neutral",
266
+ "volume": "high|medium|low"
267
+ },
268
+ "signals": ["list of trading signals"],
269
+ "riskLevel": "low|medium|high",
270
+ "marketCondition": "volatile|ranging|trending"
271
+ }
272
+ `;
273
+
274
+ const response = await context.agent.execute(prompt);
275
+
276
+ // Parse and store analysis
277
+ try {
278
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
279
+ if (jsonMatch) {
280
+ const analysis = JSON.parse(jsonMatch[0]);
281
+ context.custom.analysis = analysis;
282
+ context.custom.riskLevel = analysis.riskLevel || "medium";
283
+ }
284
+ } catch {
285
+ context.custom.analysis = { raw: response };
286
+ }
287
+
288
+ return {
289
+ nextPhase: "signaling",
290
+ continue: true,
291
+ };
292
+ }
293
+
294
+ /**
295
+ * Signaling phase - generate trading signals
296
+ */
297
+ private async phaseSignaling(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
298
+ console.log("[TradingWorkflow] Phase: Generating signals");
299
+
300
+ const analysis = context.custom.analysis || {};
301
+
302
+ const prompt = `Generate trading signals based on the market analysis.
303
+
304
+ Analysis: ${JSON.stringify(analysis, null, 2)}
305
+
306
+ Generate a trading signal with:
307
+ - Direction (long/short)
308
+ - Entry price zone
309
+ - Stop loss level
310
+ - Take profit targets (1, 2, 3)
311
+ - Position size recommendation
312
+ - Risk/reward ratio
313
+ - Confidence level
314
+
315
+ Provide the signal in JSON format:
316
+ {
317
+ "direction": "long|short",
318
+ "entryZone": { "min": number, "max": number },
319
+ "stopLoss": number,
320
+ "takeProfits": {
321
+ "tp1": { "price": number, "size": "percentage of position" },
322
+ "tp2": { "price": number, "size": "percentage of position" },
323
+ "tp3": { "price": number, "size": "percentage of position" }
324
+ },
325
+ "positionSize": { "percentage": number, "reason": "string" },
326
+ "riskReward": number,
327
+ "confidence": 0-100,
328
+ "rationale": "explanation for the signal"
329
+ }
330
+ `;
331
+
332
+ const response = await context.agent.execute(prompt);
333
+
334
+ // Parse and store signal
335
+ try {
336
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
337
+ if (jsonMatch) {
338
+ context.custom.signal = JSON.parse(jsonMatch[0]);
339
+ }
340
+ } catch {
341
+ context.custom.signal = { raw: response };
342
+ }
343
+
344
+ return {
345
+ nextPhase: "risk_checking",
346
+ continue: true,
347
+ };
348
+ }
349
+
350
+ /**
351
+ * Risk Checking phase - evaluate risk before execution
352
+ */
353
+ private async phaseRiskChecking(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
354
+ console.log("[TradingWorkflow] Phase: Risk checking");
355
+
356
+ const analysis = context.custom.analysis || {};
357
+ const signal = context.custom.signal || {};
358
+
359
+ const prompt = `Perform risk assessment for the proposed trade.
360
+
361
+ Analysis: ${JSON.stringify(analysis, null, 2)}
362
+ Signal: ${JSON.stringify(signal, null, 2)}
363
+
364
+ Evaluate:
365
+ 1. Risk/reward ratio (minimum 1:2)
366
+ 2. Position size vs account risk (max 2% per trade)
367
+ 3. Market conditions (avoid high volatility if conservative)
368
+ 4. Correlation with existing positions
369
+ 5. Stop loss placement validity
370
+
371
+ Respond with risk assessment in JSON format:
372
+ {
373
+ "approved": true|false,
374
+ "riskScore": 0-100,
375
+ "concerns": ["list of concerns"],
376
+ "adjustments": ["suggested adjustments"],
377
+ "maxPositionSize": number,
378
+ "reasoning": "detailed explanation"
379
+ }
380
+
381
+ If approved is false, explain why and what conditions would make it acceptable.
382
+ `;
383
+
384
+ const response = await context.agent.execute(prompt);
385
+
386
+ // Parse risk assessment
387
+ try {
388
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
389
+ if (jsonMatch) {
390
+ const riskAssessment = JSON.parse(jsonMatch[0]);
391
+ context.custom.riskAssessment = riskAssessment;
392
+ context.custom.riskApproved = riskAssessment.approved === true;
393
+
394
+ // Adjust position size if suggested
395
+ if (riskAssessment.maxPositionSize && context.custom.signal) {
396
+ (context.custom.signal as any).positionSize = { percentage: riskAssessment.maxPositionSize };
397
+ }
398
+ }
399
+ } catch {
400
+ // Default to not approved on parse failure
401
+ context.custom.riskApproved = false;
402
+ context.custom.riskAssessment = { raw: response, approved: false };
403
+ }
404
+
405
+ const nextPhase = context.custom.riskApproved ? "executing" : "analyzing";
406
+
407
+ return {
408
+ nextPhase,
409
+ continue: true,
410
+ data: { riskApproved: context.custom.riskApproved },
411
+ };
412
+ }
413
+
414
+ /**
415
+ * Executing phase - execute trades
416
+ */
417
+ private async phaseExecuting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
418
+ console.log("[TradingWorkflow] Phase: Executing trade");
419
+
420
+ const signal = context.custom.signal || {};
421
+ const riskAssessment = context.custom.riskAssessment || {};
422
+
423
+ const prompt = `Execute the approved trade signal.
424
+
425
+ Signal: ${JSON.stringify(signal, null, 2)}
426
+ Risk Assessment: ${JSON.stringify(riskAssessment, null, 2)}
427
+
428
+ Use the available trading tools to:
429
+ 1. Place the entry order (limit or market based on conditions)
430
+ 2. Set stop loss order
431
+ 3. Set take profit orders (tp1, tp2, tp3)
432
+ 4. Confirm all orders are placed correctly
433
+
434
+ Report the execution status with order IDs.
435
+ `;
436
+
437
+ const response = await context.agent.execute(prompt);
438
+ context.custom.executionResult = response;
439
+ context.custom.tradeStartTime = new Date().toISOString();
440
+
441
+ return {
442
+ nextPhase: "monitoring",
443
+ continue: true,
444
+ };
445
+ }
446
+
447
+ /**
448
+ * Monitoring phase - monitor positions
449
+ */
450
+ private async phaseMonitoring(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
451
+ console.log("[TradingWorkflow] Phase: Monitoring position");
452
+
453
+ const signal = context.custom.signal || {};
454
+ const executionResult = context.custom.executionResult || "";
455
+
456
+ const prompt = `Monitor the current position.
457
+
458
+ Signal: ${JSON.stringify(signal, null, 2)}
459
+ Execution: ${executionResult}
460
+ Trade Start: ${context.custom.tradeStartTime || "unknown"}
461
+
462
+ Check:
463
+ - Current price vs entry
464
+ - Unrealized P&L
465
+ - Distance to take profit levels
466
+ - Distance to stop loss
467
+ - Market conditions changes
468
+ - Time in trade
469
+
470
+ Report status and current state in JSON format:
471
+ {
472
+ "currentPrice": number,
473
+ "unrealizedPnL": number,
474
+ "pnlPercent": number,
475
+ "tp1Hit": boolean,
476
+ "tp2Hit": boolean,
477
+ "tp3Hit": boolean,
478
+ "stopLossHit": boolean,
479
+ "targetReached": boolean,
480
+ "positionClosed": boolean,
481
+ "status": "open|closed|stopped_out|taken_profit",
482
+ "recommendation": "hold|close|adjust"
483
+ }
484
+ `;
485
+
486
+ const response = await context.agent.execute(prompt);
487
+
488
+ // Parse monitoring result
489
+ try {
490
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
491
+ if (jsonMatch) {
492
+ const monitorStatus = JSON.parse(jsonMatch[0]);
493
+ context.custom.monitorStatus = monitorStatus;
494
+ context.custom.targetReached = monitorStatus.targetReached === true;
495
+ context.custom.stopLoss = monitorStatus.stopLossHit === true;
496
+ context.custom.positionClosed = monitorStatus.positionClosed === true;
497
+ context.custom.currentPnL = monitorStatus.unrealizedPnL;
498
+ }
499
+ } catch {
500
+ // Fallback detection
501
+ const lowerResponse = response.toLowerCase();
502
+ context.custom.targetReached = lowerResponse.includes("target") && lowerResponse.includes("reached");
503
+ context.custom.stopLoss = lowerResponse.includes("stop loss") && lowerResponse.includes("hit");
504
+ context.custom.positionClosed = lowerResponse.includes("position closed");
505
+ }
506
+
507
+ // Determine next phase
508
+ let nextPhase: TradingPhase = "monitoring";
509
+ if (context.custom.targetReached || context.custom.stopLoss) {
510
+ nextPhase = "complete";
511
+ } else if (context.custom.positionClosed) {
512
+ nextPhase = "analyzing"; // Look for new opportunities
513
+ } else if (context.state.iteration % 10 === 0 && context.state.iteration > 0) {
514
+ nextPhase = "reflecting";
515
+ }
516
+
517
+ return {
518
+ nextPhase,
519
+ continue: true,
520
+ };
521
+ }
522
+
523
+ /**
524
+ * Reflecting phase - review performance
525
+ */
526
+ private async phaseReflecting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
527
+ console.log(`[TradingWorkflow] Phase: Reflecting (checkpoint #${context.state.reflection.checkpointCount + 1})`);
528
+
529
+ const prompt = `Reflect on trading performance so far.
530
+
531
+ Iteration: ${context.state.iteration}
532
+ Current P&L: ${context.custom.currentPnL || "unknown"}
533
+ Risk Level: ${context.custom.riskLevel || "medium"}
534
+
535
+ Review:
536
+ - What trades were taken?
537
+ - What signals were generated but not executed?
538
+ - What's the win rate?
539
+ - Are risk parameters being followed?
540
+
541
+ Provide a brief performance summary:
542
+ {
543
+ "totalSignals": number,
544
+ "signalsExecuted": number,
545
+ "winRate": number,
546
+ "currentDrawdown": number,
547
+ "lessonsLearned": ["insights"],
548
+ "adjustmentsNeeded": ["suggested adjustments"]
549
+ }
550
+ `;
551
+
552
+ const response = await context.agent.execute(prompt);
553
+
554
+ // Parse reflection
555
+ try {
556
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
557
+ if (jsonMatch) {
558
+ context.custom.reflection = JSON.parse(jsonMatch[0]);
559
+ }
560
+ } catch {
561
+ context.custom.reflection = { raw: response };
562
+ }
563
+
564
+ return {
565
+ nextPhase: "monitoring",
566
+ continue: true,
567
+ };
568
+ }
569
+
570
+ /**
571
+ * Complete phase - trading session finished
572
+ */
573
+ private async phaseComplete(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
574
+ console.log("[TradingWorkflow] Trading session complete!");
575
+
576
+ const prompt = `Final summary of trading session.
577
+
578
+ Session Summary:
579
+ - Total Iterations: ${context.state.iteration}
580
+ - Final P&L: ${context.custom.currentPnL || "unknown"}
581
+ - Target Reached: ${context.custom.targetReached ? "Yes" : "No"}
582
+ - Stop Loss Hit: ${context.custom.stopLoss ? "Yes" : "No"}
583
+
584
+ Report:
585
+ - Total signals generated
586
+ - Trades executed
587
+ - Win/loss ratio
588
+ - Total P&L
589
+ - Maximum drawdown
590
+ - Key lessons learned
591
+ - Recommendations for future sessions
592
+
593
+ Format as a trading journal entry.
594
+ `;
595
+
596
+ await context.agent.execute(prompt);
597
+
598
+ await context.executeHook("onSessionEnd", context.state);
599
+
600
+ return {
601
+ nextPhase: "complete",
602
+ continue: false,
603
+ };
604
+ }
605
+ }
606
+
607
+ // Export singleton instance
608
+ export const tradingWorkflow = new TradingWorkflow();