@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.
- package/README.md +264 -0
- package/dist/bin/discord-cli.js +124118 -0
- package/dist/bin/manager.js +143 -0
- package/dist/bin/telegram-cli.js +124114 -0
- package/dist/index.js +125340 -0
- package/package.json +94 -0
- package/src/agent.ts +111 -0
- package/src/channels/base.ts +573 -0
- package/src/channels/discord.ts +306 -0
- package/src/channels/index.ts +169 -0
- package/src/channels/telegram.ts +315 -0
- package/src/daemon.ts +534 -0
- package/src/hooks.ts +97 -0
- package/src/index.ts +111 -0
- package/src/memory.ts +369 -0
- package/src/skills/coding/commit.ts +202 -0
- package/src/skills/coding/execute-subtask.ts +136 -0
- package/src/skills/coding/fix-issues.ts +126 -0
- package/src/skills/coding/index.ts +26 -0
- package/src/skills/coding/plan-task.ts +158 -0
- package/src/skills/coding/quality-check.ts +155 -0
- package/src/skills/index.ts +65 -0
- package/src/skills/registry.ts +380 -0
- package/src/skills/shared/index.ts +21 -0
- package/src/skills/shared/reflect.ts +156 -0
- package/src/skills/shared/review.ts +201 -0
- package/src/skills/shared/trajectory.ts +319 -0
- package/src/skills/trading/analyze-market.ts +144 -0
- package/src/skills/trading/check-risk.ts +176 -0
- package/src/skills/trading/execute-trade.ts +185 -0
- package/src/skills/trading/generate-signal.ts +160 -0
- package/src/skills/trading/index.ts +26 -0
- package/src/skills/trading/monitor-position.ts +179 -0
- package/src/skills/types.ts +235 -0
- package/src/skills/workflows.ts +340 -0
- package/src/state.ts +77 -0
- package/src/tools.ts +134 -0
- package/src/types.ts +314 -0
- package/src/workflow.ts +341 -0
- package/src/workflows/coding.ts +580 -0
- package/src/workflows/index.ts +61 -0
- package/src/workflows/trading.ts +608 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - Core Types
|
|
3
|
+
*
|
|
4
|
+
* Autonomous AI daemon powered by GLM 4.7 with hooks, tools, and teammates.
|
|
5
|
+
* Based on Ralph Iterative's SLAM pattern (State → Loop → Action → Memory).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Team } from "@ebowwa/teammates";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* GLM Daemon state phases (SLAM pattern)
|
|
12
|
+
* @deprecated Skills now use string IDs directly (e.g., "/plan-task")
|
|
13
|
+
*/
|
|
14
|
+
export const GLM_PHASES = {
|
|
15
|
+
planning: "planning",
|
|
16
|
+
executing: "executing",
|
|
17
|
+
reflecting: "reflecting", // Checkpoint after N tools
|
|
18
|
+
paranoid: "paranoid",
|
|
19
|
+
reviewing: "reviewing",
|
|
20
|
+
fixing: "fixing",
|
|
21
|
+
committing: "committing",
|
|
22
|
+
complete: "complete",
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Legacy phase type for backwards compatibility
|
|
27
|
+
* @deprecated Skills now use string IDs (e.g., "/plan-task", "/execute-subtask")
|
|
28
|
+
*/
|
|
29
|
+
export type GLMPhase = keyof typeof GLM_PHASES;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* GLM Daemon configuration
|
|
33
|
+
*/
|
|
34
|
+
export interface GLMDaemonConfig {
|
|
35
|
+
/** Team name for multi-agent coordination */
|
|
36
|
+
teamName: string;
|
|
37
|
+
|
|
38
|
+
/** GLM model to use */
|
|
39
|
+
model?: string;
|
|
40
|
+
|
|
41
|
+
/** Working directory */
|
|
42
|
+
cwd: string;
|
|
43
|
+
|
|
44
|
+
/** Enable automatic commits */
|
|
45
|
+
autoCommit?: boolean;
|
|
46
|
+
|
|
47
|
+
/** Enable automatic PR creation */
|
|
48
|
+
autoPR?: boolean;
|
|
49
|
+
|
|
50
|
+
/** Base branch for PRs */
|
|
51
|
+
baseBranch?: string;
|
|
52
|
+
|
|
53
|
+
/** Maximum iterations (0 = unlimited) */
|
|
54
|
+
maxIterations?: number;
|
|
55
|
+
|
|
56
|
+
/** Completion promise text */
|
|
57
|
+
completionPromise?: string;
|
|
58
|
+
|
|
59
|
+
/** Hooks configuration */
|
|
60
|
+
hooks?: GLMHooksConfig;
|
|
61
|
+
|
|
62
|
+
/** Tools configuration */
|
|
63
|
+
tools?: GLMToolsConfig;
|
|
64
|
+
|
|
65
|
+
/** Reflection checkpoint configuration */
|
|
66
|
+
reflection?: GLMReflectionConfig;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* GLM Daemon state (persisted to disk)
|
|
71
|
+
*/
|
|
72
|
+
export interface GLMDaemonState {
|
|
73
|
+
/** Original prompt/task */
|
|
74
|
+
prompt: string;
|
|
75
|
+
|
|
76
|
+
/** Completion promise (when to stop) */
|
|
77
|
+
promise: string;
|
|
78
|
+
|
|
79
|
+
/** Current iteration */
|
|
80
|
+
iteration: number;
|
|
81
|
+
|
|
82
|
+
/** Maximum iterations */
|
|
83
|
+
maxIterations: number;
|
|
84
|
+
|
|
85
|
+
/** Start timestamp */
|
|
86
|
+
startTime: string;
|
|
87
|
+
|
|
88
|
+
/** Last update timestamp */
|
|
89
|
+
lastUpdate: string;
|
|
90
|
+
|
|
91
|
+
/** Token usage tracking */
|
|
92
|
+
tokens: {
|
|
93
|
+
totalInput: number;
|
|
94
|
+
totalOutput: number;
|
|
95
|
+
byIteration: Array<{
|
|
96
|
+
iteration: number;
|
|
97
|
+
input: number;
|
|
98
|
+
output: number;
|
|
99
|
+
}>;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** Files changed in this session */
|
|
103
|
+
filesChanged: string[];
|
|
104
|
+
|
|
105
|
+
/** Working memory */
|
|
106
|
+
workMemory: {
|
|
107
|
+
completedFiles: string[];
|
|
108
|
+
fileChecksums: Record<string, string>;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** SLAM state */
|
|
112
|
+
slam: {
|
|
113
|
+
enabled: boolean;
|
|
114
|
+
/** Current skill ID (e.g., "/plan-task", "/execute-subtask") or legacy phase */
|
|
115
|
+
phase: string;
|
|
116
|
+
/** Previous phase/skill (used to return after reflection) */
|
|
117
|
+
previousPhase?: string;
|
|
118
|
+
state: {
|
|
119
|
+
currentTask: string;
|
|
120
|
+
beliefs: Record<string, unknown>;
|
|
121
|
+
goals: string[];
|
|
122
|
+
};
|
|
123
|
+
subtasks: GLMSubtask[];
|
|
124
|
+
currentSubtask: string | null;
|
|
125
|
+
completedSubtasks: string[];
|
|
126
|
+
memory: {
|
|
127
|
+
actionsTaken: string[];
|
|
128
|
+
outcomes: Record<string, unknown>;
|
|
129
|
+
patterns: Record<string, unknown>;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/** Git configuration */
|
|
134
|
+
git: {
|
|
135
|
+
enabled: boolean;
|
|
136
|
+
autoCommit: boolean;
|
|
137
|
+
autoPR: boolean;
|
|
138
|
+
baseBranch: string;
|
|
139
|
+
branchName: string;
|
|
140
|
+
branchCreated: boolean;
|
|
141
|
+
currentCommit: string;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/** Reflection checkpoint state */
|
|
145
|
+
reflection: {
|
|
146
|
+
/** Current tool call count in this chunk */
|
|
147
|
+
toolCount: number;
|
|
148
|
+
/** Total tool calls across all chunks */
|
|
149
|
+
totalToolCount: number;
|
|
150
|
+
/** Number of reflection checkpoints completed */
|
|
151
|
+
checkpointCount: number;
|
|
152
|
+
/** Timestamp of last reflection */
|
|
153
|
+
lastReflection: string | null;
|
|
154
|
+
/** Accumulated TL;DR summaries */
|
|
155
|
+
summaries: GLMReflectionSummary[];
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Machine info */
|
|
159
|
+
machine?: {
|
|
160
|
+
cpu: { count: number; model: string; tier: string };
|
|
161
|
+
memory: { total: number; free: number; tier: string };
|
|
162
|
+
disk: { total: number; available: number; tier: string };
|
|
163
|
+
platform: { os: string; arch: string; isContainer: boolean };
|
|
164
|
+
capacity: string;
|
|
165
|
+
score: number;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* GLM Subtask (for SLAM coordination)
|
|
171
|
+
*/
|
|
172
|
+
export interface GLMSubtask {
|
|
173
|
+
id: string;
|
|
174
|
+
title: string;
|
|
175
|
+
description: string;
|
|
176
|
+
status: "pending" | "in_progress" | "completed" | "blocked" | "failed";
|
|
177
|
+
assignedTo?: string;
|
|
178
|
+
dependencies?: string[];
|
|
179
|
+
result?: unknown;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* GLM Hooks configuration
|
|
184
|
+
*/
|
|
185
|
+
export interface GLMHooksConfig {
|
|
186
|
+
onSessionStart?: (state: GLMDaemonState) => Promise<void>;
|
|
187
|
+
onSessionEnd?: (state: GLMDaemonState) => Promise<void>;
|
|
188
|
+
onPreToolUse?: (tool: string, args: unknown) => Promise<boolean>;
|
|
189
|
+
onPostToolUse?: (tool: string, args: unknown, result: unknown) => Promise<void>;
|
|
190
|
+
onSubagentStart?: (subagentId: string) => Promise<void>;
|
|
191
|
+
onSubagentStop?: (subagentId: string, result: unknown) => Promise<void>;
|
|
192
|
+
onIterationStart?: (iteration: number) => Promise<void>;
|
|
193
|
+
onIterationEnd?: (iteration: number, result: unknown) => Promise<void>;
|
|
194
|
+
/** Called at each reflection checkpoint */
|
|
195
|
+
onReflection?: (state: GLMDaemonState, summary: GLMReflectionSummary) => Promise<void>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* GLM Tools configuration
|
|
200
|
+
*/
|
|
201
|
+
export interface GLMToolsConfig {
|
|
202
|
+
/** Enable MCP tool access */
|
|
203
|
+
enableMCP?: boolean;
|
|
204
|
+
|
|
205
|
+
/** Allowed tools (whitelist) */
|
|
206
|
+
allowedTools?: string[];
|
|
207
|
+
|
|
208
|
+
/** Blocked tools (blacklist) */
|
|
209
|
+
blockedTools?: string[];
|
|
210
|
+
|
|
211
|
+
/** Tool timeout in ms */
|
|
212
|
+
toolTimeout?: number;
|
|
213
|
+
|
|
214
|
+
/** Max retries for failed tools */
|
|
215
|
+
maxRetries?: number;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Reflection checkpoint configuration
|
|
220
|
+
* Triggers TL;DR summary after N tool calls
|
|
221
|
+
*/
|
|
222
|
+
export interface GLMReflectionConfig {
|
|
223
|
+
/** Enable reflection checkpoints */
|
|
224
|
+
enabled: boolean;
|
|
225
|
+
|
|
226
|
+
/** Number of tools before reflection (default: 50) */
|
|
227
|
+
toolLimit: number;
|
|
228
|
+
|
|
229
|
+
/** Auto-continue after reflection (default: true) */
|
|
230
|
+
autoContinue: boolean;
|
|
231
|
+
|
|
232
|
+
/** Save reflection summaries to file */
|
|
233
|
+
saveToFile?: string;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* GLM Agent (individual GLM-powered agent)
|
|
238
|
+
*/
|
|
239
|
+
export interface GLMAgentConfig {
|
|
240
|
+
/** Agent ID */
|
|
241
|
+
agentId: string;
|
|
242
|
+
|
|
243
|
+
/** Agent name */
|
|
244
|
+
name: string;
|
|
245
|
+
|
|
246
|
+
/** System prompt */
|
|
247
|
+
prompt: string;
|
|
248
|
+
|
|
249
|
+
/** Model to use */
|
|
250
|
+
model?: string;
|
|
251
|
+
|
|
252
|
+
/** Temperature (0-1) */
|
|
253
|
+
temperature?: number;
|
|
254
|
+
|
|
255
|
+
/** Max tokens */
|
|
256
|
+
maxTokens?: number;
|
|
257
|
+
|
|
258
|
+
/** Tools this agent can use */
|
|
259
|
+
tools?: string[];
|
|
260
|
+
|
|
261
|
+
/** Assigned subtasks */
|
|
262
|
+
assignedSubtasks?: string[];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* GLM Tool execution result
|
|
267
|
+
* @deprecated Use ToolExecutionResult from @ebowwa/codespaces-types/runtime/tools
|
|
268
|
+
*/
|
|
269
|
+
export interface GLMToolResult {
|
|
270
|
+
success: boolean;
|
|
271
|
+
result?: unknown;
|
|
272
|
+
error?: string;
|
|
273
|
+
duration: number;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Reflection summary generated at checkpoint
|
|
278
|
+
*/
|
|
279
|
+
export interface GLMReflectionSummary {
|
|
280
|
+
/** Checkpoint number */
|
|
281
|
+
checkpoint: number;
|
|
282
|
+
/** Timestamp */
|
|
283
|
+
timestamp: string;
|
|
284
|
+
/** Tools used in this chunk */
|
|
285
|
+
toolsUsed: number;
|
|
286
|
+
/** Phase/skill when reflection occurred */
|
|
287
|
+
phase: string;
|
|
288
|
+
/** TL;DR summary */
|
|
289
|
+
summary: string;
|
|
290
|
+
/** Key accomplishments */
|
|
291
|
+
accomplishments: string[];
|
|
292
|
+
/** Next steps identified */
|
|
293
|
+
nextSteps: string[];
|
|
294
|
+
/** Issues/blockers found */
|
|
295
|
+
issues: string[];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* GLM Daemon status
|
|
300
|
+
*/
|
|
301
|
+
export interface GLMDaemonStatus {
|
|
302
|
+
id: string;
|
|
303
|
+
status: "starting" | "running" | "complete" | "error" | "stopped";
|
|
304
|
+
/** Current skill ID or phase */
|
|
305
|
+
phase: string;
|
|
306
|
+
iteration: number;
|
|
307
|
+
prompt: string;
|
|
308
|
+
currentTask?: string;
|
|
309
|
+
totalSubtasks: number;
|
|
310
|
+
completedSubtasks: number;
|
|
311
|
+
startedAt: string;
|
|
312
|
+
lastUpdate: string;
|
|
313
|
+
processId?: number;
|
|
314
|
+
}
|
package/src/workflow.ts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - Workflow System
|
|
3
|
+
*
|
|
4
|
+
* Pluggable workflow architecture for domain-agnostic daemon operations.
|
|
5
|
+
* Supports multiple workflows: coding, trading, research, etc.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { GLMAgent } from "./agent.js";
|
|
9
|
+
import type { GLMDaemonState, GLMReflectionSummary } from "./types.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Workflow phase definition
|
|
13
|
+
*/
|
|
14
|
+
export interface GLMWorkflowPhase<P extends string = string> {
|
|
15
|
+
/** Phase identifier */
|
|
16
|
+
name: P;
|
|
17
|
+
|
|
18
|
+
/** Human-readable phase name */
|
|
19
|
+
label: string;
|
|
20
|
+
|
|
21
|
+
/** Phase description for system prompts */
|
|
22
|
+
description: string;
|
|
23
|
+
|
|
24
|
+
/** Optional timeout for this phase (ms) */
|
|
25
|
+
timeout?: number;
|
|
26
|
+
|
|
27
|
+
/** Whether this phase can be skipped */
|
|
28
|
+
skippable?: boolean;
|
|
29
|
+
|
|
30
|
+
/** Hooks to run before phase execution */
|
|
31
|
+
beforeHooks?: string[];
|
|
32
|
+
|
|
33
|
+
/** Hooks to run after phase execution */
|
|
34
|
+
afterHooks?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Workflow execution context
|
|
39
|
+
*/
|
|
40
|
+
export interface GLMWorkflowContext {
|
|
41
|
+
/** Current daemon state */
|
|
42
|
+
state: GLMDaemonState;
|
|
43
|
+
|
|
44
|
+
/** Agent instance for executing prompts */
|
|
45
|
+
agent: GLMAgent;
|
|
46
|
+
|
|
47
|
+
/** Reflection summary if in reflecting phase */
|
|
48
|
+
reflectionSummary?: GLMReflectionSummary;
|
|
49
|
+
|
|
50
|
+
/** Custom data for workflow-specific use */
|
|
51
|
+
custom: Record<string, unknown>;
|
|
52
|
+
|
|
53
|
+
/** Tool count increment callback */
|
|
54
|
+
incrementToolCount: () => boolean;
|
|
55
|
+
|
|
56
|
+
/** Hook execution callback */
|
|
57
|
+
executeHook: (event: string, ...args: unknown[]) => Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Phase execution result
|
|
62
|
+
*/
|
|
63
|
+
export interface GLMWorkflowPhaseResult {
|
|
64
|
+
/** Next phase to transition to */
|
|
65
|
+
nextPhase: string;
|
|
66
|
+
|
|
67
|
+
/** Whether to continue the loop */
|
|
68
|
+
continue: boolean;
|
|
69
|
+
|
|
70
|
+
/** Optional result data */
|
|
71
|
+
data?: unknown;
|
|
72
|
+
|
|
73
|
+
/** Optional error */
|
|
74
|
+
error?: Error;
|
|
75
|
+
|
|
76
|
+
/** State updates to apply */
|
|
77
|
+
stateUpdates?: Partial<GLMDaemonState>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Workflow transition rule
|
|
82
|
+
*/
|
|
83
|
+
export interface GLMWorkflowTransition<P extends string = string> {
|
|
84
|
+
/** From phase */
|
|
85
|
+
from: P | "*";
|
|
86
|
+
|
|
87
|
+
/** Condition for transition */
|
|
88
|
+
condition?: (context: GLMWorkflowContext) => boolean | Promise<boolean>;
|
|
89
|
+
|
|
90
|
+
/** Target phase */
|
|
91
|
+
to: P;
|
|
92
|
+
|
|
93
|
+
/** Priority (higher = checked first) */
|
|
94
|
+
priority?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Workflow configuration
|
|
99
|
+
*/
|
|
100
|
+
export interface GLMWorkflowConfig<P extends string = string> {
|
|
101
|
+
/** Workflow identifier */
|
|
102
|
+
id: string;
|
|
103
|
+
|
|
104
|
+
/** Human-readable name */
|
|
105
|
+
name: string;
|
|
106
|
+
|
|
107
|
+
/** Workflow description */
|
|
108
|
+
description: string;
|
|
109
|
+
|
|
110
|
+
/** All phases in this workflow */
|
|
111
|
+
phases: GLMWorkflowPhase<P>[];
|
|
112
|
+
|
|
113
|
+
/** Initial phase */
|
|
114
|
+
initialPhase: P;
|
|
115
|
+
|
|
116
|
+
/** Terminal phases (end states) */
|
|
117
|
+
terminalPhases: P[];
|
|
118
|
+
|
|
119
|
+
/** Transition rules */
|
|
120
|
+
transitions: GLMWorkflowTransition<P>[];
|
|
121
|
+
|
|
122
|
+
/** Default phase execution order if no transitions match */
|
|
123
|
+
defaultOrder?: P[];
|
|
124
|
+
|
|
125
|
+
/** Workflow-specific system prompt additions */
|
|
126
|
+
systemPromptExtensions?: string;
|
|
127
|
+
|
|
128
|
+
/** Reflection phase name (if supported) */
|
|
129
|
+
reflectionPhase?: P;
|
|
130
|
+
|
|
131
|
+
/** Custom completion check */
|
|
132
|
+
isComplete?: (context: GLMWorkflowContext) => boolean | Promise<boolean>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Workflow executor interface
|
|
137
|
+
*/
|
|
138
|
+
export interface GLMWorkflowExecutor {
|
|
139
|
+
/** Get workflow configuration */
|
|
140
|
+
getConfig(): GLMWorkflowConfig;
|
|
141
|
+
|
|
142
|
+
/** Execute a specific phase */
|
|
143
|
+
executePhase(phase: string, context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult>;
|
|
144
|
+
|
|
145
|
+
/** Determine next phase based on current state */
|
|
146
|
+
getNextPhase(context: GLMWorkflowContext): Promise<string>;
|
|
147
|
+
|
|
148
|
+
/** Check if workflow is complete */
|
|
149
|
+
isComplete(context: GLMWorkflowContext): Promise<boolean>;
|
|
150
|
+
|
|
151
|
+
/** Get phase definition */
|
|
152
|
+
getPhase(phase: string): GLMWorkflowPhase | undefined;
|
|
153
|
+
|
|
154
|
+
/** Get all phases */
|
|
155
|
+
getPhases(): GLMWorkflowPhase[];
|
|
156
|
+
|
|
157
|
+
/** Build system prompt for current state */
|
|
158
|
+
buildSystemPrompt(context: GLMWorkflowContext): string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Base workflow class with common functionality
|
|
163
|
+
*/
|
|
164
|
+
export abstract class BaseWorkflow<P extends string = string> implements GLMWorkflowExecutor {
|
|
165
|
+
protected config: GLMWorkflowConfig<P>;
|
|
166
|
+
protected phaseMap: Map<string, GLMWorkflowPhase<P>>;
|
|
167
|
+
|
|
168
|
+
constructor(config: GLMWorkflowConfig<P>) {
|
|
169
|
+
this.config = config;
|
|
170
|
+
this.phaseMap = new Map(config.phases.map(p => [p.name, p]));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getConfig(): GLMWorkflowConfig {
|
|
174
|
+
return this.config;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
getPhase(phase: string): GLMWorkflowPhase | undefined {
|
|
178
|
+
return this.phaseMap.get(phase);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
getPhases(): GLMWorkflowPhase[] {
|
|
182
|
+
return this.config.phases;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Execute a phase - must be implemented by subclasses
|
|
187
|
+
*/
|
|
188
|
+
abstract executePhase(phase: string, context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult>;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Determine next phase based on transitions
|
|
192
|
+
*/
|
|
193
|
+
async getNextPhase(context: GLMWorkflowContext): Promise<string> {
|
|
194
|
+
const currentPhase = context.state.slam.phase;
|
|
195
|
+
|
|
196
|
+
// Sort transitions by priority (descending)
|
|
197
|
+
const sortedTransitions = [...this.config.transitions].sort(
|
|
198
|
+
(a, b) => (b.priority || 0) - (a.priority || 0)
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Check each transition
|
|
202
|
+
for (const transition of sortedTransitions) {
|
|
203
|
+
if (transition.from === "*" || transition.from === currentPhase) {
|
|
204
|
+
if (!transition.condition) {
|
|
205
|
+
return transition.to;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const shouldTransition = await transition.condition(context);
|
|
209
|
+
if (shouldTransition) {
|
|
210
|
+
return transition.to;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Fall back to default order
|
|
216
|
+
if (this.config.defaultOrder) {
|
|
217
|
+
const currentIndex = this.config.defaultOrder.indexOf(currentPhase as P);
|
|
218
|
+
if (currentIndex >= 0 && currentIndex < this.config.defaultOrder.length - 1) {
|
|
219
|
+
return this.config.defaultOrder[currentIndex + 1];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Stay in current phase if no transition matches
|
|
224
|
+
return currentPhase;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Check if workflow is complete
|
|
229
|
+
*/
|
|
230
|
+
async isComplete(context: GLMWorkflowContext): Promise<boolean> {
|
|
231
|
+
// Check if in terminal phase
|
|
232
|
+
if (this.config.terminalPhases.includes(context.state.slam.phase as P)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Check custom completion condition
|
|
237
|
+
if (this.config.isComplete) {
|
|
238
|
+
return await this.config.isComplete(context);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Build system prompt with workflow context
|
|
246
|
+
*/
|
|
247
|
+
buildSystemPrompt(context: GLMWorkflowContext): string {
|
|
248
|
+
const phase = this.getPhase(context.state.slam.phase);
|
|
249
|
+
const phaseInfo = phase
|
|
250
|
+
? `${phase.label}: ${phase.description}`
|
|
251
|
+
: context.state.slam.phase;
|
|
252
|
+
|
|
253
|
+
let prompt = `You are an autonomous AI agent.
|
|
254
|
+
|
|
255
|
+
Your task: ${context.state.prompt}
|
|
256
|
+
|
|
257
|
+
You work in phases:
|
|
258
|
+
${this.config.phases.map(p => `- ${p.label}: ${p.description}`).join("\n")}
|
|
259
|
+
|
|
260
|
+
Current phase: ${phaseInfo}
|
|
261
|
+
Iteration: ${context.state.iteration}
|
|
262
|
+
`;
|
|
263
|
+
|
|
264
|
+
if (this.config.systemPromptExtensions) {
|
|
265
|
+
prompt += `\n${this.config.systemPromptExtensions}`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return prompt;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Workflow registry for managing multiple workflows
|
|
274
|
+
*/
|
|
275
|
+
export class WorkflowRegistry {
|
|
276
|
+
private workflows: Map<string, GLMWorkflowExecutor> = new Map();
|
|
277
|
+
private defaultWorkflow: string | null = null;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Register a workflow
|
|
281
|
+
*/
|
|
282
|
+
register(workflow: GLMWorkflowExecutor, setDefault = false): void {
|
|
283
|
+
const config = workflow.getConfig();
|
|
284
|
+
this.workflows.set(config.id, workflow);
|
|
285
|
+
|
|
286
|
+
if (setDefault || this.workflows.size === 1) {
|
|
287
|
+
this.defaultWorkflow = config.id;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get a workflow by ID
|
|
293
|
+
*/
|
|
294
|
+
get(id: string): GLMWorkflowExecutor | undefined {
|
|
295
|
+
return this.workflows.get(id);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get the default workflow
|
|
300
|
+
*/
|
|
301
|
+
getDefault(): GLMWorkflowExecutor | undefined {
|
|
302
|
+
if (!this.defaultWorkflow) {
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
return this.workflows.get(this.defaultWorkflow);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Set the default workflow
|
|
310
|
+
*/
|
|
311
|
+
setDefault(id: string): void {
|
|
312
|
+
if (!this.workflows.has(id)) {
|
|
313
|
+
throw new Error(`Workflow not found: ${id}`);
|
|
314
|
+
}
|
|
315
|
+
this.defaultWorkflow = id;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* List all registered workflows
|
|
320
|
+
*/
|
|
321
|
+
list(): Array<{ id: string; name: string; description: string }> {
|
|
322
|
+
return Array.from(this.workflows.values()).map(w => {
|
|
323
|
+
const config = w.getConfig();
|
|
324
|
+
return {
|
|
325
|
+
id: config.id,
|
|
326
|
+
name: config.name,
|
|
327
|
+
description: config.description,
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Check if a workflow exists
|
|
334
|
+
*/
|
|
335
|
+
has(id: string): boolean {
|
|
336
|
+
return this.workflows.has(id);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Global registry instance
|
|
341
|
+
export const workflowRegistry = new WorkflowRegistry();
|