@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,179 @@
1
+ /**
2
+ * GLM Daemon - Monitor Position Skill
3
+ *
4
+ * Monitor open positions and market conditions.
5
+ */
6
+
7
+ import { z } from "zod";
8
+ import type { Skill, SkillContext, SkillResult } from "../types.js";
9
+ import { skillRegistry } from "../registry.js";
10
+
11
+ /**
12
+ * Trade execution result
13
+ */
14
+ interface TradeExecution {
15
+ orderId: string;
16
+ direction: string;
17
+ entryPrice: number;
18
+ size: number;
19
+ stopLoss?: number;
20
+ takeProfits?: {
21
+ tp1?: { price: number; size: string };
22
+ tp2?: { price: number; size: string };
23
+ tp3?: { price: number; size: string };
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Monitor position parameters
29
+ */
30
+ const MonitorPositionParams = z.object({
31
+ /** Check interval hint (ms) */
32
+ interval: z.number().optional(),
33
+ /** Maximum hold time (ms) */
34
+ maxHoldTime: z.number().optional(),
35
+ });
36
+
37
+ /**
38
+ * Monitor position result data
39
+ */
40
+ interface MonitorPositionData {
41
+ currentPrice: number;
42
+ unrealizedPnL: number;
43
+ pnlPercent: number;
44
+ tp1Hit: boolean;
45
+ tp2Hit: boolean;
46
+ tp3Hit: boolean;
47
+ stopLossHit: boolean;
48
+ targetReached: boolean;
49
+ positionClosed: boolean;
50
+ status: "open" | "closed" | "stopped_out" | "taken_profit";
51
+ recommendation: "hold" | "close" | "adjust";
52
+ }
53
+
54
+ /**
55
+ * Monitor position skill
56
+ */
57
+ export const monitorPositionSkill: Skill<z.infer<typeof MonitorPositionParams>, MonitorPositionData> = {
58
+ id: "/monitor-position",
59
+ name: "Monitor Position",
60
+ description: "Monitor open positions and check for target/stop hits.",
61
+ paramsSchema: MonitorPositionParams,
62
+ tags: ["trading", "monitoring"],
63
+ parallelizable: false,
64
+ requires: ["position"],
65
+
66
+ async execute(params, context): Promise<SkillResult<MonitorPositionData>> {
67
+ const position = (context.custom.position || {}) as TradeExecution;
68
+ const tradeStartTime = context.custom.tradeStartTime as number | undefined;
69
+
70
+ console.log("[/monitor-position] Checking position status");
71
+
72
+ const prompt = `Monitor the current position.
73
+
74
+ Position: ${JSON.stringify(position, null, 2)}
75
+ Trade Start: ${tradeStartTime || "unknown"}
76
+ Current Iteration: ${context.state.iteration}
77
+
78
+ Check:
79
+ - Current price vs entry
80
+ - Unrealized P&L
81
+ - Distance to take profit levels (TP1: ${position.takeProfits?.tp1?.price}, TP2: ${position.takeProfits?.tp2?.price}, TP3: ${position.takeProfits?.tp3?.price})
82
+ - Distance to stop loss (${position.stopLoss})
83
+ - Market conditions changes
84
+ - Time in trade
85
+
86
+ Report status in JSON format:
87
+ {
88
+ "currentPrice": number,
89
+ "unrealizedPnL": number,
90
+ "pnlPercent": number,
91
+ "tp1Hit": boolean,
92
+ "tp2Hit": boolean,
93
+ "tp3Hit": boolean,
94
+ "stopLossHit": boolean,
95
+ "targetReached": boolean,
96
+ "positionClosed": boolean,
97
+ "status": "open|closed|stopped_out|taken_profit",
98
+ "recommendation": "hold|close|adjust"
99
+ }`;
100
+
101
+ try {
102
+ const response = await context.agent.execute(prompt);
103
+
104
+ // Parse JSON from response
105
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
106
+ let data: MonitorPositionData;
107
+
108
+ if (jsonMatch) {
109
+ const parsed = JSON.parse(jsonMatch[0]);
110
+ data = {
111
+ currentPrice: parsed.currentPrice || position.entryPrice || 0,
112
+ unrealizedPnL: parsed.unrealizedPnL || 0,
113
+ pnlPercent: parsed.pnlPercent || 0,
114
+ tp1Hit: parsed.tp1Hit || false,
115
+ tp2Hit: parsed.tp2Hit || false,
116
+ tp3Hit: parsed.tp3Hit || false,
117
+ stopLossHit: parsed.stopLossHit || false,
118
+ targetReached: parsed.targetReached || false,
119
+ positionClosed: parsed.positionClosed || false,
120
+ status: parsed.status || "open",
121
+ recommendation: parsed.recommendation || "hold",
122
+ };
123
+ } else {
124
+ // Fallback: detect from response
125
+ const lower = response.toLowerCase();
126
+ data = {
127
+ currentPrice: position.entryPrice || 0,
128
+ unrealizedPnL: 0,
129
+ pnlPercent: 0,
130
+ tp1Hit: lower.includes("tp1") && lower.includes("hit"),
131
+ tp2Hit: lower.includes("tp2") && lower.includes("hit"),
132
+ tp3Hit: lower.includes("tp3") && lower.includes("hit"),
133
+ stopLossHit: lower.includes("stop loss") && lower.includes("hit"),
134
+ targetReached: lower.includes("target") && lower.includes("reached"),
135
+ positionClosed: lower.includes("position closed"),
136
+ status: "open",
137
+ recommendation: "hold",
138
+ };
139
+ }
140
+
141
+ console.log(`[/monitor-position] P&L: ${data.pnlPercent.toFixed(2)}%`);
142
+ console.log(`[/monitor-position] Status: ${data.status}`);
143
+ console.log(`[/monitor-position] TP hits: ${[data.tp1Hit, data.tp2Hit, data.tp3Hit].filter(Boolean).length}/3`);
144
+
145
+ // Determine next phase
146
+ let nextSkill: string | undefined;
147
+ if (data.targetReached || data.stopLossHit || data.status === "closed") {
148
+ nextSkill = "/complete";
149
+ } else if (data.positionClosed) {
150
+ nextSkill = "/analyze-market"; // Look for new opportunities
151
+ } else if (context.state.iteration % 10 === 0 && context.state.iteration > 0) {
152
+ nextSkill = "/reflect";
153
+ }
154
+
155
+ return {
156
+ success: true,
157
+ data,
158
+ contextUpdates: {
159
+ monitorStatus: data,
160
+ targetReached: data.targetReached,
161
+ stopLoss: data.stopLossHit,
162
+ positionClosed: data.positionClosed,
163
+ currentPnL: data.unrealizedPnL,
164
+ },
165
+ nextSkill,
166
+ };
167
+ } catch (error) {
168
+ return {
169
+ success: false,
170
+ error: error instanceof Error ? error.message : String(error),
171
+ };
172
+ }
173
+ },
174
+ };
175
+
176
+ skillRegistry.register(monitorPositionSkill);
177
+
178
+ export { MonitorPositionParams };
179
+ export type { MonitorPositionData };
@@ -0,0 +1,235 @@
1
+ /**
2
+ * GLM Daemon - Skill Types
3
+ *
4
+ * Composable skill system for workflow phases.
5
+ * Skills are reusable units of work that can be shared across workflows.
6
+ */
7
+
8
+ import type { z } from "zod";
9
+ import type { GLMDaemonState } from "../types.js";
10
+ import type { GLMAgent } from "../agent.js";
11
+
12
+ /**
13
+ * Skill parameter schema type
14
+ */
15
+ export type SkillParams = z.ZodType<unknown>;
16
+
17
+ /**
18
+ * Skill result data type
19
+ * Flexible type for skill result data - can be any non-null value
20
+ */
21
+ export type SkillData = unknown;
22
+
23
+ /**
24
+ * Context passed to skill execution
25
+ */
26
+ export interface SkillContext {
27
+ /** Current daemon state */
28
+ state: GLMDaemonState;
29
+
30
+ /** Agent instance for AI calls */
31
+ agent: GLMAgent;
32
+
33
+ /** Workflow-specific custom data */
34
+ custom: Record<string, unknown>;
35
+
36
+ /** Increment tool count and check for reflection trigger */
37
+ incrementToolCount: () => boolean;
38
+
39
+ /** Execute a lifecycle hook */
40
+ executeHook: (event: string, ...args: unknown[]) => Promise<void>;
41
+
42
+ /** Call another skill by ID */
43
+ callSkill: (id: string, params?: unknown) => Promise<SkillResult>;
44
+
45
+ /** Workflow configuration (contains skill params) */
46
+ workflowConfig?: Record<string, unknown>;
47
+ }
48
+
49
+ /**
50
+ * Result returned by skill execution
51
+ */
52
+ export interface SkillResult<T = SkillData> {
53
+ /** Whether the skill executed successfully */
54
+ success: boolean;
55
+
56
+ /** Result data from skill execution */
57
+ data?: T;
58
+
59
+ /** Error message if failed */
60
+ error?: string;
61
+
62
+ /** Updates to apply to context.custom */
63
+ contextUpdates?: Record<string, unknown>;
64
+
65
+ /** Updates to apply to daemon state */
66
+ stateUpdates?: Partial<GLMDaemonState>;
67
+
68
+ /** Next skill to execute (overrides workflow transition) */
69
+ nextSkill?: string;
70
+
71
+ /** Whether to stop the workflow */
72
+ stop?: boolean;
73
+ }
74
+
75
+ /**
76
+ * Skill configuration (static definition)
77
+ */
78
+ export interface SkillConfig<P = unknown> {
79
+ /** Unique skill identifier (e.g., "analyze-market" → "/analyze-market") */
80
+ id: string;
81
+
82
+ /** Human-readable name */
83
+ name: string;
84
+
85
+ /** Description for AI to understand skill purpose */
86
+ description: string;
87
+
88
+ /** Parameter schema (Zod) for validation */
89
+ paramsSchema?: z.ZodType<P>;
90
+
91
+ /** Default parameters from workflow config */
92
+ defaultParams?: P;
93
+
94
+ /** Context keys required before execution */
95
+ requires?: string[];
96
+
97
+ /** Context keys produced after execution */
98
+ produces?: string[];
99
+
100
+ /** Tags for categorization */
101
+ tags?: string[];
102
+
103
+ /** Whether this skill can run in parallel with others */
104
+ parallelizable?: boolean;
105
+
106
+ /** Max retry attempts on failure (default: 3) */
107
+ maxRetries?: number;
108
+
109
+ /** Base delay for retry backoff in ms (default: 1000) */
110
+ retryBaseDelay?: number;
111
+ }
112
+
113
+ /**
114
+ * Skill interface - combines config and execution
115
+ */
116
+ export interface Skill<P = unknown, T = SkillData> extends SkillConfig<P> {
117
+ /** Execute the skill */
118
+ execute(params: P | undefined, context: SkillContext): Promise<SkillResult<T>>;
119
+ }
120
+
121
+ /**
122
+ * Skill factory function type
123
+ */
124
+ export type SkillFactory<P = unknown, T = SkillData> = (
125
+ config?: Partial<SkillConfig<P>>
126
+ ) => Skill<P, T>;
127
+
128
+ /**
129
+ * Transition rule between skills
130
+ */
131
+ export interface SkillTransition {
132
+ /** Source skill ID or "*" for any */
133
+ from: string;
134
+
135
+ /** Target skill ID */
136
+ to: string;
137
+
138
+ /** Condition for transition */
139
+ condition?: SkillTransitionCondition;
140
+
141
+ /** Priority (higher = checked first) */
142
+ priority?: number;
143
+
144
+ /** Description of when this transition applies */
145
+ description?: string;
146
+ }
147
+
148
+ /**
149
+ * Transition condition function
150
+ */
151
+ export type SkillTransitionCondition = (
152
+ context: SkillContext,
153
+ result: SkillResult
154
+ ) => boolean | Promise<boolean>;
155
+
156
+ /**
157
+ * Workflow configuration using skill sequences
158
+ */
159
+ export interface SkillWorkflowConfig {
160
+ /** Workflow identifier */
161
+ id: string;
162
+
163
+ /** Human-readable name */
164
+ name: string;
165
+
166
+ /** Description */
167
+ description: string;
168
+
169
+ /** Skills to execute (in order, unless transitions override) */
170
+ skills: string[];
171
+
172
+ /** Initial skill to start with */
173
+ initialSkill: string;
174
+
175
+ /** Skills that terminate the workflow */
176
+ terminalSkills: string[];
177
+
178
+ /** Transition rules between skills */
179
+ transitions: SkillTransition[];
180
+
181
+ /** Default skill parameters */
182
+ skillParams?: Record<string, unknown>;
183
+
184
+ /** System prompt extensions for this workflow */
185
+ systemPromptExtensions?: string;
186
+
187
+ /** Reflection skill ID (if supported) */
188
+ reflectionSkill?: string;
189
+
190
+ /** Custom completion check */
191
+ isComplete?: (context: SkillContext) => boolean | Promise<boolean>;
192
+ }
193
+
194
+ /**
195
+ * Skill execution metadata
196
+ */
197
+ export interface SkillExecutionMeta {
198
+ /** Skill ID */
199
+ skillId: string;
200
+
201
+ /** Execution start time */
202
+ startTime: string;
203
+
204
+ /** Execution end time */
205
+ endTime?: string;
206
+
207
+ /** Duration in ms */
208
+ duration?: number;
209
+
210
+ /** Attempt number (for retries) */
211
+ attempt: number;
212
+
213
+ /** Whether execution succeeded */
214
+ success: boolean;
215
+
216
+ /** Error message if failed */
217
+ error?: string;
218
+ }
219
+
220
+ /**
221
+ * Skill execution options
222
+ */
223
+ export interface SkillExecutionOptions {
224
+ /** Override max retries */
225
+ maxRetries?: number;
226
+
227
+ /** Skip parameter validation */
228
+ skipValidation?: boolean;
229
+
230
+ /** Custom timeout in ms */
231
+ timeout?: number;
232
+
233
+ /** Whether to update context after execution */
234
+ updateContext?: boolean;
235
+ }