@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,580 @@
1
+ /**
2
+ * GLM Daemon - Coding Workflow
3
+ *
4
+ * Default coding workflow extracted from hardcoded daemon phases.
5
+ * Phases: planning → executing → reflecting → paranoid → reviewing → fixing → committing → complete
6
+ */
7
+
8
+ import {
9
+ BaseWorkflow,
10
+ type GLMWorkflowConfig,
11
+ type GLMWorkflowContext,
12
+ type GLMWorkflowPhaseResult,
13
+ type GLMWorkflowPhase,
14
+ type GLMWorkflowTransition,
15
+ } from "../workflow.js";
16
+ import type { GLMReflectionSummary } from "../types.js";
17
+
18
+ /**
19
+ * Coding workflow phases
20
+ */
21
+ export type CodingPhase =
22
+ | "planning"
23
+ | "executing"
24
+ | "reflecting"
25
+ | "paranoid"
26
+ | "reviewing"
27
+ | "fixing"
28
+ | "committing"
29
+ | "complete";
30
+
31
+ /**
32
+ * Coding workflow phases definition
33
+ */
34
+ export const CODING_PHASES: GLMWorkflowPhase<CodingPhase>[] = [
35
+ {
36
+ name: "planning",
37
+ label: "Planning",
38
+ description: "Break down the task into subtasks",
39
+ skippable: false,
40
+ },
41
+ {
42
+ name: "executing",
43
+ label: "Executing",
44
+ description: "Work on the current subtask",
45
+ skippable: false,
46
+ },
47
+ {
48
+ name: "reflecting",
49
+ label: "Reflecting",
50
+ description: "Checkpoint after N tools - summarize progress",
51
+ skippable: true,
52
+ timeout: 60000,
53
+ },
54
+ {
55
+ name: "paranoid",
56
+ label: "Paranoid",
57
+ description: "Quality check after every edit",
58
+ skippable: false,
59
+ },
60
+ {
61
+ name: "reviewing",
62
+ label: "Reviewing",
63
+ description: "Final quality review",
64
+ skippable: false,
65
+ },
66
+ {
67
+ name: "fixing",
68
+ label: "Fixing",
69
+ description: "Fix issues found in review",
70
+ skippable: true,
71
+ },
72
+ {
73
+ name: "committing",
74
+ label: "Committing",
75
+ description: "Commit changes",
76
+ skippable: true,
77
+ },
78
+ {
79
+ name: "complete",
80
+ label: "Complete",
81
+ description: "Task is finished",
82
+ skippable: false,
83
+ },
84
+ ];
85
+
86
+ /**
87
+ * Coding workflow transition rules
88
+ */
89
+ export const CODING_TRANSITIONS: GLMWorkflowTransition<CodingPhase>[] = [
90
+ // Planning -> Executing (always)
91
+ {
92
+ from: "planning",
93
+ to: "executing",
94
+ priority: 100,
95
+ },
96
+ // Executing -> Paranoid (when all subtasks complete)
97
+ {
98
+ from: "executing",
99
+ to: "paranoid",
100
+ priority: 90,
101
+ condition: (ctx) => {
102
+ const subtasks = ctx.state.slam.subtasks;
103
+ const completed = ctx.state.slam.completedSubtasks;
104
+ return subtasks.length > 0 && subtasks.every((s) => completed.includes(s.id));
105
+ },
106
+ },
107
+ // Executing -> Executing (continue with next subtask)
108
+ {
109
+ from: "executing",
110
+ to: "executing",
111
+ priority: 80,
112
+ },
113
+ // Paranoid -> Fixing (if issues found)
114
+ {
115
+ from: "paranoid",
116
+ to: "fixing",
117
+ priority: 90,
118
+ condition: async (ctx) => {
119
+ // This will be set by the phase execution
120
+ return ctx.custom.hasIssues === true;
121
+ },
122
+ },
123
+ // Paranoid -> Reviewing (if no issues)
124
+ {
125
+ from: "paranoid",
126
+ to: "reviewing",
127
+ priority: 80,
128
+ },
129
+ // Reviewing -> Fixing (if not approved)
130
+ {
131
+ from: "reviewing",
132
+ to: "fixing",
133
+ priority: 90,
134
+ condition: async (ctx) => {
135
+ return ctx.custom.approved !== true;
136
+ },
137
+ },
138
+ // Reviewing -> Committing (if approved)
139
+ {
140
+ from: "reviewing",
141
+ to: "committing",
142
+ priority: 80,
143
+ },
144
+ // Fixing -> Paranoid (re-check after fixes)
145
+ {
146
+ from: "fixing",
147
+ to: "paranoid",
148
+ priority: 100,
149
+ },
150
+ // Committing -> Complete
151
+ {
152
+ from: "committing",
153
+ to: "complete",
154
+ priority: 100,
155
+ },
156
+ // Reflecting -> previous phase (handled specially)
157
+ {
158
+ from: "reflecting",
159
+ to: "executing", // Default, will be overridden
160
+ priority: 100,
161
+ condition: async (ctx) => {
162
+ // Return to previous phase
163
+ const prev = ctx.state.slam.previousPhase;
164
+ if (prev) {
165
+ ctx.custom.nextPhase = prev;
166
+ }
167
+ return true;
168
+ },
169
+ },
170
+ ];
171
+
172
+ /**
173
+ * Coding workflow configuration
174
+ */
175
+ export const CODING_WORKFLOW_CONFIG: GLMWorkflowConfig<CodingPhase> = {
176
+ id: "coding",
177
+ name: "Coding Workflow",
178
+ description: "Default coding workflow for software development tasks",
179
+ phases: CODING_PHASES,
180
+ initialPhase: "planning",
181
+ terminalPhases: ["complete"],
182
+ transitions: CODING_TRANSITIONS,
183
+ defaultOrder: ["planning", "executing", "paranoid", "reviewing", "fixing", "committing", "complete"],
184
+ reflectionPhase: "reflecting",
185
+ systemPromptExtensions: `Use tools when available. Be thorough but efficient.
186
+ Focus on code changes, testing, and verification.`,
187
+ };
188
+
189
+ /**
190
+ * Coding Workflow implementation
191
+ */
192
+ export class CodingWorkflow extends BaseWorkflow<CodingPhase> {
193
+ constructor() {
194
+ super(CODING_WORKFLOW_CONFIG);
195
+ }
196
+
197
+ /**
198
+ * Execute a coding phase
199
+ */
200
+ async executePhase(phase: string, context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
201
+ switch (phase as CodingPhase) {
202
+ case "planning":
203
+ return this.phasePlanning(context);
204
+ case "executing":
205
+ return this.phaseExecuting(context);
206
+ case "reflecting":
207
+ return this.phaseReflecting(context);
208
+ case "paranoid":
209
+ return this.phaseParanoid(context);
210
+ case "reviewing":
211
+ return this.phaseReviewing(context);
212
+ case "fixing":
213
+ return this.phaseFixing(context);
214
+ case "committing":
215
+ return this.phaseCommitting(context);
216
+ case "complete":
217
+ return this.phaseComplete(context);
218
+ default:
219
+ throw new Error(`Unknown phase: ${phase}`);
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Planning phase - break down task into subtasks
225
+ */
226
+ private async phasePlanning(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
227
+ console.log("[CodingWorkflow] Phase: Planning");
228
+
229
+ const prompt = `${context.state.prompt}
230
+
231
+ Break this task down into 3-7 concrete subtasks.
232
+ For each subtask, specify:
233
+ - Title (short description)
234
+ - Description (what needs to be done)
235
+ - Dependencies (which subtasks must come first)
236
+
237
+ Respond with a JSON array of subtasks.
238
+ `;
239
+
240
+ const response = await context.agent.execute(prompt);
241
+ const subtasks = this.parseSubtasks(response, context);
242
+
243
+ return {
244
+ nextPhase: "executing",
245
+ continue: true,
246
+ stateUpdates: {
247
+ slam: {
248
+ ...context.state.slam,
249
+ subtasks,
250
+ currentSubtask: subtasks[0]?.id || null,
251
+ phase: "executing",
252
+ },
253
+ } as any,
254
+ };
255
+ }
256
+
257
+ /**
258
+ * Executing phase - work on current subtask
259
+ */
260
+ private async phaseExecuting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
261
+ const currentSubtaskId = context.state.slam.currentSubtask;
262
+
263
+ if (!currentSubtaskId) {
264
+ return {
265
+ nextPhase: "reviewing",
266
+ continue: true,
267
+ };
268
+ }
269
+
270
+ const subtask = context.state.slam.subtasks.find((st) => st.id === currentSubtaskId);
271
+ if (!subtask) {
272
+ return {
273
+ nextPhase: "reviewing",
274
+ continue: true,
275
+ };
276
+ }
277
+
278
+ console.log(`[CodingWorkflow] Executing subtask: ${subtask.title}`);
279
+
280
+ const prompt = `Work on this subtask: ${subtask.title}
281
+
282
+ ${subtask.description}
283
+
284
+ Use available tools to complete the work.
285
+ Focus on code changes, testing, and verification.
286
+ `;
287
+
288
+ const response = await context.agent.execute(prompt);
289
+
290
+ // Find next subtask
291
+ const completedSubtasks = [...context.state.slam.completedSubtasks, currentSubtaskId];
292
+ const nextSubtask = context.state.slam.subtasks.find(
293
+ (st) => !completedSubtasks.includes(st.id)
294
+ );
295
+
296
+ // Update subtask status
297
+ const updatedSubtasks = context.state.slam.subtasks.map((st) =>
298
+ st.id === currentSubtaskId
299
+ ? { ...st, status: "completed" as const, result: response }
300
+ : st
301
+ );
302
+
303
+ // Determine next phase
304
+ const nextPhase = nextSubtask ? "executing" : "paranoid";
305
+
306
+ return {
307
+ nextPhase,
308
+ continue: true,
309
+ stateUpdates: {
310
+ slam: {
311
+ ...context.state.slam,
312
+ subtasks: updatedSubtasks,
313
+ completedSubtasks,
314
+ currentSubtask: nextSubtask?.id || null,
315
+ phase: nextPhase,
316
+ },
317
+ } as any,
318
+ };
319
+ }
320
+
321
+ /**
322
+ * Reflecting phase - TL;DR checkpoint after N tools
323
+ */
324
+ private async phaseReflecting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
325
+ console.log(`[CodingWorkflow] Phase: Reflecting (checkpoint #${context.state.reflection.checkpointCount + 1})`);
326
+ console.log(`[CodingWorkflow] Tools used this chunk: ${context.state.reflection.toolCount}`);
327
+
328
+ const previousPhase = context.state.slam.previousPhase || "executing";
329
+
330
+ const prompt = `REFLECTION CHECKPOINT #${context.state.reflection.checkpointCount + 1}
331
+
332
+ You have used ${context.state.reflection.toolCount} tools. Pause and reflect.
333
+
334
+ Task: ${context.state.prompt}
335
+ Current Phase (before reflection): ${previousPhase}
336
+ Iteration: ${context.state.iteration}
337
+ Subtasks: ${context.state.slam.completedSubtasks.length}/${context.state.slam.subtasks.length} complete
338
+
339
+ Files changed: ${context.state.filesChanged.length > 0 ? context.state.filesChanged.join(", ") : "none"}
340
+
341
+ Generate a TL;DR summary in this JSON format:
342
+ {
343
+ "summary": "1-2 sentence summary of progress",
344
+ "accomplishments": ["what was done"],
345
+ "nextSteps": ["what needs to be done next"],
346
+ "issues": ["any blockers or problems"]
347
+ }
348
+
349
+ Be concise. Focus on what matters for continuing the task.
350
+ `;
351
+
352
+ const response = await context.agent.execute(prompt);
353
+ const summary = this.parseReflectionSummary(response, previousPhase, context);
354
+
355
+ // Run reflection hook
356
+ await context.executeHook("onReflection", context.state, summary);
357
+
358
+ // Log the reflection
359
+ console.log(`[CodingWorkflow] TL;DR: ${summary.summary}`);
360
+ console.log(`[CodingWorkflow] Accomplishments: ${summary.accomplishments.join(", ")}`);
361
+ console.log(`[CodingWorkflow] Next: ${summary.nextSteps.join(", ")}`);
362
+
363
+ return {
364
+ nextPhase: previousPhase,
365
+ continue: true,
366
+ data: { summary },
367
+ };
368
+ }
369
+
370
+ /**
371
+ * Paranoid phase - quality check after every edit
372
+ */
373
+ private async phaseParanoid(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
374
+ console.log("[CodingWorkflow] Phase: Paranoid (quality check)");
375
+
376
+ const prompt = `Review the changes made in this session for:
377
+ - Bugs or errors
378
+ - Edge cases not handled
379
+ - Security vulnerabilities
380
+ - Performance issues
381
+ - Breaking changes
382
+
383
+ Task: ${context.state.prompt}
384
+
385
+ Changes made:
386
+ ${context.state.filesChanged.map((f) => `- ${f}`).join("\n")}
387
+
388
+ Be thorough. If issues found, we'll fix them. If clean, we proceed to review.
389
+ `;
390
+
391
+ const response = await context.agent.execute(prompt);
392
+ const hasIssues = this.detectIssues(response);
393
+
394
+ // Store result in context for transition condition
395
+ context.custom.hasIssues = hasIssues;
396
+
397
+ return {
398
+ nextPhase: hasIssues ? "fixing" : "reviewing",
399
+ continue: true,
400
+ };
401
+ }
402
+
403
+ /**
404
+ * Reviewing phase - final quality review
405
+ */
406
+ private async phaseReviewing(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
407
+ console.log("[CodingWorkflow] Phase: Reviewing");
408
+
409
+ const prompt = `Final review of the completed work.
410
+
411
+ Task: ${context.state.prompt}
412
+ Completion promise: ${context.state.promise}
413
+
414
+ Does the implementation fully satisfy the completion promise?
415
+ Are there any remaining issues or TODOs?
416
+
417
+ If complete and clean, respond with "APPROVED".
418
+ Otherwise, list remaining issues.
419
+ `;
420
+
421
+ const response = await context.agent.execute(prompt);
422
+ const approved = response.includes("APPROVED");
423
+
424
+ // Store result in context for transition condition
425
+ context.custom.approved = approved;
426
+
427
+ return {
428
+ nextPhase: approved ? "committing" : "fixing",
429
+ continue: true,
430
+ };
431
+ }
432
+
433
+ /**
434
+ * Fixing phase - fix issues found
435
+ */
436
+ private async phaseFixing(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
437
+ console.log("[CodingWorkflow] Phase: Fixing");
438
+
439
+ const prompt = `Fix the issues identified in the review.
440
+
441
+ Use tools to make necessary changes.
442
+ Test your fixes thoroughly.
443
+ `;
444
+
445
+ await context.agent.execute(prompt);
446
+
447
+ // Reset approval state
448
+ context.custom.approved = false;
449
+ context.custom.hasIssues = false;
450
+
451
+ return {
452
+ nextPhase: "paranoid", // Re-check after fixes
453
+ continue: true,
454
+ };
455
+ }
456
+
457
+ /**
458
+ * Committing phase - commit changes
459
+ */
460
+ private async phaseCommitting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
461
+ console.log("[CodingWorkflow] Phase: Committing");
462
+
463
+ if (context.state.git.autoCommit) {
464
+ // TODO: Use MCP git tools for commits
465
+ console.log("[CodingWorkflow] Auto-commit would happen here via MCP git tools");
466
+ }
467
+
468
+ return {
469
+ nextPhase: "complete",
470
+ continue: true,
471
+ };
472
+ }
473
+
474
+ /**
475
+ * Complete phase - task is finished
476
+ */
477
+ private async phaseComplete(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
478
+ console.log("[CodingWorkflow] Task complete!");
479
+
480
+ await context.executeHook("onSessionEnd", context.state);
481
+
482
+ return {
483
+ nextPhase: "complete",
484
+ continue: false, // Stop the loop
485
+ };
486
+ }
487
+
488
+ /**
489
+ * Parse subtasks from agent response
490
+ */
491
+ private parseSubtasks(
492
+ response: string,
493
+ context: GLMWorkflowContext
494
+ ): Array<{
495
+ id: string;
496
+ title: string;
497
+ description: string;
498
+ status: "pending" | "in_progress" | "completed" | "blocked" | "failed";
499
+ dependencies?: string[];
500
+ }> {
501
+ try {
502
+ const jsonMatch = response.match(/\[[\s\S]*\]/);
503
+ if (jsonMatch) {
504
+ const parsed = JSON.parse(jsonMatch[0]);
505
+ return parsed.map((st: any, idx: number) => ({
506
+ id: st.id || `subtask-${idx}`,
507
+ title: st.title || st.task || `Subtask ${idx + 1}`,
508
+ description: st.description || "",
509
+ status: "pending" as const,
510
+ dependencies: st.dependencies || [],
511
+ }));
512
+ }
513
+ } catch {
514
+ // Fallback: create single subtask from prompt
515
+ return [{
516
+ id: "subtask-0",
517
+ title: context.state.prompt.substring(0, 50),
518
+ description: context.state.prompt,
519
+ status: "pending",
520
+ }];
521
+ }
522
+
523
+ return [];
524
+ }
525
+
526
+ /**
527
+ * Parse reflection summary from agent response
528
+ */
529
+ private parseReflectionSummary(
530
+ response: string,
531
+ phase: string,
532
+ context: GLMWorkflowContext
533
+ ): GLMReflectionSummary {
534
+ try {
535
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
536
+ if (jsonMatch) {
537
+ const parsed = JSON.parse(jsonMatch[0]);
538
+ return {
539
+ checkpoint: context.state.reflection.checkpointCount + 1,
540
+ timestamp: new Date().toISOString(),
541
+ toolsUsed: context.state.reflection.toolCount,
542
+ phase: phase as any,
543
+ summary: parsed.summary || "Progress made",
544
+ accomplishments: parsed.accomplishments || [],
545
+ nextSteps: parsed.nextSteps || [],
546
+ issues: parsed.issues || [],
547
+ };
548
+ }
549
+ } catch {
550
+ // Fallback
551
+ }
552
+
553
+ return {
554
+ checkpoint: context.state.reflection.checkpointCount + 1,
555
+ timestamp: new Date().toISOString(),
556
+ toolsUsed: context.state.reflection.toolCount,
557
+ phase: phase as any,
558
+ summary: response.substring(0, 200),
559
+ accomplishments: [],
560
+ nextSteps: [],
561
+ issues: [],
562
+ };
563
+ }
564
+
565
+ /**
566
+ * Detect issues in paranoid check response
567
+ */
568
+ private detectIssues(response: string): boolean {
569
+ const issueKeywords = [
570
+ "bug", "error", "issue", "problem", "vulnerability",
571
+ "fix", "improve", "missing", "incomplete", "broken"
572
+ ];
573
+
574
+ const lower = response.toLowerCase();
575
+ return issueKeywords.some((kw) => lower.includes(kw));
576
+ }
577
+ }
578
+
579
+ // Export singleton instance
580
+ export const codingWorkflow = new CodingWorkflow();
@@ -0,0 +1,61 @@
1
+ /**
2
+ * GLM Daemon - Workflows Index
3
+ *
4
+ * Export all available workflows and register them with the registry.
5
+ */
6
+
7
+ import { workflowRegistry } from "../workflow.js";
8
+ import { CodingWorkflow, codingWorkflow } from "./coding.js";
9
+ import { TradingWorkflow, tradingWorkflow } from "./trading.js";
10
+
11
+ // Re-export workflow types
12
+ export type {
13
+ GLMWorkflowPhase,
14
+ GLMWorkflowContext,
15
+ GLMWorkflowPhaseResult,
16
+ GLMWorkflowTransition,
17
+ GLMWorkflowConfig,
18
+ GLMWorkflowExecutor,
19
+ } from "../workflow.js";
20
+
21
+ export { BaseWorkflow, WorkflowRegistry, workflowRegistry } from "../workflow.js";
22
+
23
+ // Re-export coding workflow
24
+ export { CodingWorkflow, CODING_PHASES, CODING_TRANSITIONS, CODING_WORKFLOW_CONFIG, codingWorkflow } from "./coding.js";
25
+
26
+ // Re-export trading workflow
27
+ export { TradingWorkflow, TRADING_PHASES, TRADING_TRANSITIONS, TRADING_WORKFLOW_CONFIG, tradingWorkflow } from "./trading.js";
28
+
29
+ // Export phase types
30
+ export type { CodingPhase } from "./coding.js";
31
+ export type { TradingPhase } from "./trading.js";
32
+
33
+ /**
34
+ * Initialize all built-in workflows
35
+ */
36
+ export function initializeWorkflows(): void {
37
+ // Register coding workflow as default
38
+ workflowRegistry.register(codingWorkflow, true);
39
+
40
+ // Register trading workflow
41
+ workflowRegistry.register(tradingWorkflow);
42
+
43
+ console.log("[Workflows] Initialized workflows:", workflowRegistry.list().map(w => w.id).join(", "));
44
+ }
45
+
46
+ /**
47
+ * Get a workflow by ID
48
+ */
49
+ export function getWorkflow(id: string) {
50
+ return workflowRegistry.get(id);
51
+ }
52
+
53
+ /**
54
+ * Get the default workflow
55
+ */
56
+ export function getDefaultWorkflow() {
57
+ return workflowRegistry.getDefault();
58
+ }
59
+
60
+ // Auto-initialize on import
61
+ initializeWorkflows();