@ai-setting/roy-agent-core 1.5.22 → 1.5.24
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/dist/env/event-source/index.js +41 -0
- package/dist/env/index.js +9 -7
- package/dist/index.js +31 -3
- package/dist/shared/@ai-setting/roy-agent-core-2grcjaad.js +0 -0
- package/dist/shared/@ai-setting/{roy-agent-core-rccptwv0.js → roy-agent-core-5ex3za0m.js} +54 -463
- package/dist/shared/@ai-setting/roy-agent-core-j1sr5pk9.js +424 -0
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import"../../shared/@ai-setting/roy-agent-core-2grcjaad.js";
|
|
2
|
+
import {
|
|
3
|
+
EventSourceComponent,
|
|
4
|
+
builtInHandlers,
|
|
5
|
+
getBuiltInHandler,
|
|
6
|
+
larkCliHandler,
|
|
7
|
+
timerHandler,
|
|
8
|
+
websocketHandler
|
|
9
|
+
} from "../../shared/@ai-setting/roy-agent-core-5ex3za0m.js";
|
|
10
|
+
import {
|
|
11
|
+
BUILT_IN_EVENT_SOURCE_TYPES,
|
|
12
|
+
BUILT_IN_EVENT_SOURCE_TYPE_LIST,
|
|
13
|
+
EventSourceInitHooks,
|
|
14
|
+
getDefaultConfigForType,
|
|
15
|
+
isBuiltInEventSourceType,
|
|
16
|
+
isValidEventSourceType,
|
|
17
|
+
validateEventSourceConfig
|
|
18
|
+
} from "../../shared/@ai-setting/roy-agent-core-avq1x4t7.js";
|
|
19
|
+
import"../../shared/@ai-setting/roy-agent-core-qxhq8ven.js";
|
|
20
|
+
import"../../shared/@ai-setting/roy-agent-core-kkbwepqb.js";
|
|
21
|
+
import"../../shared/@ai-setting/roy-agent-core-2dhd60aw.js";
|
|
22
|
+
import"../../shared/@ai-setting/roy-agent-core-gjq1yk68.js";
|
|
23
|
+
import"../../shared/@ai-setting/roy-agent-core-44hnfb02.js";
|
|
24
|
+
import"../../shared/@ai-setting/roy-agent-core-xs5rsgat.js";
|
|
25
|
+
import"../../shared/@ai-setting/roy-agent-core-psv4v63c.js";
|
|
26
|
+
import"../../shared/@ai-setting/roy-agent-core-fs0mn2jk.js";
|
|
27
|
+
export {
|
|
28
|
+
websocketHandler,
|
|
29
|
+
validateEventSourceConfig,
|
|
30
|
+
timerHandler,
|
|
31
|
+
larkCliHandler,
|
|
32
|
+
isValidEventSourceType,
|
|
33
|
+
isBuiltInEventSourceType,
|
|
34
|
+
getDefaultConfigForType,
|
|
35
|
+
getBuiltInHandler,
|
|
36
|
+
builtInHandlers,
|
|
37
|
+
EventSourceInitHooks,
|
|
38
|
+
EventSourceComponent,
|
|
39
|
+
BUILT_IN_EVENT_SOURCE_TYPE_LIST,
|
|
40
|
+
BUILT_IN_EVENT_SOURCE_TYPES
|
|
41
|
+
};
|
package/dist/env/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
BaseEnvironment
|
|
3
|
-
|
|
4
|
-
builtInHandlers,
|
|
5
|
-
larkCliHandler,
|
|
6
|
-
timerHandler,
|
|
7
|
-
websocketHandler
|
|
8
|
-
} from "../shared/@ai-setting/roy-agent-core-rccptwv0.js";
|
|
2
|
+
BaseEnvironment
|
|
3
|
+
} from "../shared/@ai-setting/roy-agent-core-j1sr5pk9.js";
|
|
9
4
|
import {
|
|
10
5
|
XDG_PATHS,
|
|
11
6
|
getXDGPath,
|
|
12
7
|
getXDGPaths
|
|
13
8
|
} from "../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
|
|
9
|
+
import {
|
|
10
|
+
EventSourceComponent,
|
|
11
|
+
builtInHandlers,
|
|
12
|
+
larkCliHandler,
|
|
13
|
+
timerHandler,
|
|
14
|
+
websocketHandler
|
|
15
|
+
} from "../shared/@ai-setting/roy-agent-core-5ex3za0m.js";
|
|
14
16
|
import {
|
|
15
17
|
EventSourceInitHooks,
|
|
16
18
|
getDefaultConfigForType,
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
ConfigComponent
|
|
42
42
|
} from "./shared/@ai-setting/roy-agent-core-vn2bc59q.js";
|
|
43
|
+
import"./shared/@ai-setting/roy-agent-core-2grcjaad.js";
|
|
43
44
|
import {
|
|
44
45
|
MemoryComponent
|
|
45
46
|
} from "./shared/@ai-setting/roy-agent-core-4txzpsbt.js";
|
|
@@ -62,16 +63,31 @@ import {
|
|
|
62
63
|
} from "./shared/@ai-setting/roy-agent-core-rvv6ydff.js";
|
|
63
64
|
import {
|
|
64
65
|
BaseEnvironment,
|
|
65
|
-
EventSourceComponent,
|
|
66
66
|
generateDescendingId,
|
|
67
67
|
generateId
|
|
68
|
-
} from "./shared/@ai-setting/roy-agent-core-
|
|
68
|
+
} from "./shared/@ai-setting/roy-agent-core-j1sr5pk9.js";
|
|
69
69
|
import {
|
|
70
70
|
XDG_PATHS,
|
|
71
71
|
getXDGPath,
|
|
72
72
|
getXDGPaths
|
|
73
73
|
} from "./shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
|
|
74
|
-
import
|
|
74
|
+
import {
|
|
75
|
+
EventSourceComponent,
|
|
76
|
+
builtInHandlers,
|
|
77
|
+
getBuiltInHandler,
|
|
78
|
+
larkCliHandler,
|
|
79
|
+
timerHandler,
|
|
80
|
+
websocketHandler
|
|
81
|
+
} from "./shared/@ai-setting/roy-agent-core-5ex3za0m.js";
|
|
82
|
+
import {
|
|
83
|
+
BUILT_IN_EVENT_SOURCE_TYPES,
|
|
84
|
+
BUILT_IN_EVENT_SOURCE_TYPE_LIST,
|
|
85
|
+
EventSourceInitHooks,
|
|
86
|
+
getDefaultConfigForType,
|
|
87
|
+
isBuiltInEventSourceType,
|
|
88
|
+
isValidEventSourceType,
|
|
89
|
+
validateEventSourceConfig
|
|
90
|
+
} from "./shared/@ai-setting/roy-agent-core-avq1x4t7.js";
|
|
75
91
|
import {
|
|
76
92
|
WorkflowComponent
|
|
77
93
|
} from "./shared/@ai-setting/roy-agent-core-pw7cv1px.js";
|
|
@@ -303,6 +319,9 @@ init_node_registry_helper();
|
|
|
303
319
|
export {
|
|
304
320
|
writeFileTool,
|
|
305
321
|
wrapFunction,
|
|
322
|
+
websocketHandler,
|
|
323
|
+
validateEventSourceConfig,
|
|
324
|
+
timerHandler,
|
|
306
325
|
setQuietMode,
|
|
307
326
|
setConfigComponent as setLoggerConfigComponent,
|
|
308
327
|
setLogDirOverride,
|
|
@@ -311,8 +330,11 @@ export {
|
|
|
311
330
|
readFileTool,
|
|
312
331
|
propagation,
|
|
313
332
|
parseModelString,
|
|
333
|
+
larkCliHandler,
|
|
334
|
+
isValidEventSourceType,
|
|
314
335
|
isRoyError,
|
|
315
336
|
isQuietMode,
|
|
337
|
+
isBuiltInEventSourceType,
|
|
316
338
|
invokeNonStream,
|
|
317
339
|
invoke,
|
|
318
340
|
grepTool,
|
|
@@ -325,9 +347,11 @@ export {
|
|
|
325
347
|
getLogLevel,
|
|
326
348
|
getLogDir,
|
|
327
349
|
getErrorCode,
|
|
350
|
+
getDefaultConfigForType,
|
|
328
351
|
getBuiltInTool,
|
|
329
352
|
getBuiltInPromptNames,
|
|
330
353
|
getBuiltInPrompt,
|
|
354
|
+
getBuiltInHandler,
|
|
331
355
|
getAllBuiltInTools,
|
|
332
356
|
generateId,
|
|
333
357
|
generateDescendingId,
|
|
@@ -339,6 +363,7 @@ export {
|
|
|
339
363
|
createLogger,
|
|
340
364
|
createInvokeConfig,
|
|
341
365
|
createHook,
|
|
366
|
+
builtInHandlers,
|
|
342
367
|
bashTool,
|
|
343
368
|
XDG_PATHS,
|
|
344
369
|
WorkflowEdges,
|
|
@@ -381,6 +406,7 @@ export {
|
|
|
381
406
|
LLMConfigSchema,
|
|
382
407
|
LLMComponent,
|
|
383
408
|
HookManager,
|
|
409
|
+
EventSourceInitHooks,
|
|
384
410
|
EventSourceComponent,
|
|
385
411
|
ErrorCodes,
|
|
386
412
|
Edge,
|
|
@@ -391,6 +417,8 @@ export {
|
|
|
391
417
|
CommandsComponent,
|
|
392
418
|
BaseEnvironment,
|
|
393
419
|
BaseComponent,
|
|
420
|
+
BUILT_IN_EVENT_SOURCE_TYPE_LIST,
|
|
421
|
+
BUILT_IN_EVENT_SOURCE_TYPES,
|
|
394
422
|
AskUserError,
|
|
395
423
|
AgentError,
|
|
396
424
|
AgentComponentConfigSchema,
|
|
File without changes
|
|
@@ -1,452 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ContextError,
|
|
3
|
-
ErrorCodes
|
|
4
|
-
} from "./roy-agent-core-ctdhjv68.js";
|
|
5
1
|
import {
|
|
6
2
|
envKeyToConfigKey
|
|
7
3
|
} from "./roy-agent-core-qxhq8ven.js";
|
|
8
4
|
import {
|
|
9
5
|
BaseComponent
|
|
10
6
|
} from "./roy-agent-core-kkbwepqb.js";
|
|
11
|
-
import {
|
|
12
|
-
TracedAs,
|
|
13
|
-
init_decorator
|
|
14
|
-
} from "./roy-agent-core-zgypchmt.js";
|
|
15
7
|
import {
|
|
16
8
|
createLogger,
|
|
17
9
|
init_logger
|
|
18
10
|
} from "./roy-agent-core-44hnfb02.js";
|
|
19
11
|
import {
|
|
20
|
-
__legacyDecorateClassTS,
|
|
21
12
|
__require
|
|
22
13
|
} from "./roy-agent-core-fs0mn2jk.js";
|
|
23
14
|
|
|
24
|
-
// src/env/environment.ts
|
|
25
|
-
init_logger();
|
|
26
|
-
|
|
27
|
-
// src/utils/id.ts
|
|
28
|
-
function generateId(prefix = "id") {
|
|
29
|
-
const timestamp = Date.now().toString(36);
|
|
30
|
-
const random = Math.random().toString(36).substring(2, 11);
|
|
31
|
-
return `${prefix}_${timestamp}_${random}`;
|
|
32
|
-
}
|
|
33
|
-
function generateDescendingId(prefix = "id") {
|
|
34
|
-
const timestamp = (Number.MAX_SAFE_INTEGER - Date.now()).toString(36);
|
|
35
|
-
const random = Math.random().toString(36).substring(2, 11);
|
|
36
|
-
return `${prefix}_${timestamp}_${random}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// src/env/environment.ts
|
|
40
|
-
init_decorator();
|
|
41
|
-
import * as fsSync from "fs";
|
|
42
|
-
import * as path from "path";
|
|
43
|
-
var logger = createLogger("environment");
|
|
44
|
-
|
|
45
|
-
class BaseEnvironment extends BaseComponent {
|
|
46
|
-
name;
|
|
47
|
-
version;
|
|
48
|
-
components = new Map;
|
|
49
|
-
constructor(config) {
|
|
50
|
-
super();
|
|
51
|
-
this.name = config?.name ?? "base-environment";
|
|
52
|
-
this.version = config?.version ?? "1.0.0";
|
|
53
|
-
this.registerDefaultComponents();
|
|
54
|
-
}
|
|
55
|
-
registerDefaultComponents() {}
|
|
56
|
-
getConfig() {
|
|
57
|
-
return {
|
|
58
|
-
name: this.name,
|
|
59
|
-
version: this.version,
|
|
60
|
-
enabled: true,
|
|
61
|
-
env: this
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
registerComponent(component) {
|
|
65
|
-
this.components.set(component.name, component);
|
|
66
|
-
logger.debug(`Component registered: ${component.name}`);
|
|
67
|
-
}
|
|
68
|
-
unregisterComponent(name) {
|
|
69
|
-
const component = this.components.get(name);
|
|
70
|
-
if (component) {
|
|
71
|
-
this.components.delete(name);
|
|
72
|
-
logger.debug(`Component unregistered: ${name}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
getComponent(name) {
|
|
76
|
-
return this.components.get(name);
|
|
77
|
-
}
|
|
78
|
-
listComponents() {
|
|
79
|
-
return Array.from(this.components.values());
|
|
80
|
-
}
|
|
81
|
-
async handle_query(query, context) {
|
|
82
|
-
const agentComponent = this.getComponent("agent");
|
|
83
|
-
if (!agentComponent) {
|
|
84
|
-
throw new Error("AgentComponent not found. Please register AgentComponent before calling handle_query.");
|
|
85
|
-
}
|
|
86
|
-
let systemPrompt = "You are a helpful assistant.";
|
|
87
|
-
let promptSource = "fallback";
|
|
88
|
-
try {
|
|
89
|
-
const promptComponent = this.getComponent("prompt");
|
|
90
|
-
if (promptComponent) {
|
|
91
|
-
const loadedPrompt = await promptComponent.getPrompt("default");
|
|
92
|
-
if (loadedPrompt) {
|
|
93
|
-
systemPrompt = loadedPrompt;
|
|
94
|
-
promptSource = "PromptComponent";
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
} catch (err) {
|
|
98
|
-
logger.warn(`[handle_query] Failed to get prompt from PromptComponent: ${err}`);
|
|
99
|
-
}
|
|
100
|
-
logger.info(`[handle_query] Using system prompt from ${promptSource}, length: ${systemPrompt.length}`);
|
|
101
|
-
let finalSystemPrompt = systemPrompt;
|
|
102
|
-
if (systemPrompt.includes("{{memory}}")) {
|
|
103
|
-
try {
|
|
104
|
-
const memoryComponent = this.getComponent("memory");
|
|
105
|
-
if (memoryComponent) {
|
|
106
|
-
const memoryContent = await memoryComponent.recallMemory();
|
|
107
|
-
finalSystemPrompt = systemPrompt.replace("{{memory}}", memoryContent || "(No memory)");
|
|
108
|
-
logger.info(`[handle_query] Injected memory content, length: ${memoryContent.length}`);
|
|
109
|
-
} else {
|
|
110
|
-
finalSystemPrompt = systemPrompt.replace("{{memory}}", "(Memory component not available)");
|
|
111
|
-
}
|
|
112
|
-
} catch (err) {
|
|
113
|
-
logger.warn(`[handle_query] Failed to load memory content: ${err}`);
|
|
114
|
-
finalSystemPrompt = systemPrompt.replace("{{memory}}", "(Failed to load memory)");
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
if (finalSystemPrompt.includes("{{workspace_dir}}")) {
|
|
118
|
-
const workspaceDir = process.cwd();
|
|
119
|
-
finalSystemPrompt = finalSystemPrompt.replace("{{workspace_dir}}", workspaceDir);
|
|
120
|
-
logger.debug(`[handle_query] Injected workspace_dir: ${workspaceDir}`);
|
|
121
|
-
}
|
|
122
|
-
const agentName = context?.agentType && context.agentType !== "default" ? context.agentType : "default";
|
|
123
|
-
let agent = agentComponent.getAgent(agentName);
|
|
124
|
-
if (!agent) {
|
|
125
|
-
if (agentName !== "default") {
|
|
126
|
-
logger.warn(`[handle_query] Agent "${agentName}" not found, falling back to "default"`);
|
|
127
|
-
}
|
|
128
|
-
agent = agentComponent.getAgent("default");
|
|
129
|
-
}
|
|
130
|
-
if (!agent) {
|
|
131
|
-
agent = agentComponent.registerAgent("default", {
|
|
132
|
-
type: "primary",
|
|
133
|
-
systemPrompt: finalSystemPrompt
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
const result = await agentComponent.run(agent.name, query, context);
|
|
137
|
-
if (result.error) {
|
|
138
|
-
const errorMsg = result.error.toLowerCase();
|
|
139
|
-
if (errorMsg.includes("context") || errorMsg.includes("threshold") || errorMsg.includes("token") || result.error.includes("CTX_001")) {
|
|
140
|
-
const usageMatch = result.error.match(/(\d+)\/(\d+)\s*\(([\d.]+)%\)/);
|
|
141
|
-
let usage;
|
|
142
|
-
let contextWindow;
|
|
143
|
-
if (usageMatch) {
|
|
144
|
-
const totalTokens = parseInt(usageMatch[1], 10);
|
|
145
|
-
usage = {
|
|
146
|
-
promptTokens: totalTokens,
|
|
147
|
-
completionTokens: 0,
|
|
148
|
-
totalTokens
|
|
149
|
-
};
|
|
150
|
-
contextWindow = parseInt(usageMatch[2], 10);
|
|
151
|
-
}
|
|
152
|
-
const ctxError = new ContextError(result.error, ErrorCodes.CONTEXT_THRESHOLD_EXCEEDED, context?.sessionId, usage, contextWindow);
|
|
153
|
-
throw ctxError;
|
|
154
|
-
}
|
|
155
|
-
throw new Error(result.error);
|
|
156
|
-
}
|
|
157
|
-
return result.finalText || "";
|
|
158
|
-
}
|
|
159
|
-
async handle_action(action, context) {
|
|
160
|
-
throw new Error("handle_action not implemented. Override in subclass.");
|
|
161
|
-
}
|
|
162
|
-
eventHandlers = new Map;
|
|
163
|
-
wildcardHandlers = new Set;
|
|
164
|
-
subscribe(handler) {
|
|
165
|
-
this.wildcardHandlers.add(handler);
|
|
166
|
-
logger.debug(`EnvEvent handler subscribed (wildcard)`);
|
|
167
|
-
return () => {
|
|
168
|
-
this.wildcardHandlers.delete(handler);
|
|
169
|
-
logger.debug(`EnvEvent handler unsubscribed (wildcard)`);
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
subscribeTo(eventType, handler) {
|
|
173
|
-
const types = Array.isArray(eventType) ? eventType : [eventType];
|
|
174
|
-
for (const type of types) {
|
|
175
|
-
if (!this.eventHandlers.has(type)) {
|
|
176
|
-
this.eventHandlers.set(type, new Set);
|
|
177
|
-
}
|
|
178
|
-
this.eventHandlers.get(type).add(handler);
|
|
179
|
-
}
|
|
180
|
-
logger.debug(`EnvEvent handler subscribed for types: ${types.join(", ")}`);
|
|
181
|
-
return () => {
|
|
182
|
-
for (const type of types) {
|
|
183
|
-
this.eventHandlers.get(type)?.delete(handler);
|
|
184
|
-
}
|
|
185
|
-
logger.debug(`EnvEvent handler unsubscribed for types: ${types.join(", ")}`);
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
subscribeAll(handler) {
|
|
189
|
-
return this.subscribe(handler);
|
|
190
|
-
}
|
|
191
|
-
pushEnvEvent(event) {
|
|
192
|
-
const fullEvent = "id" in event && event.id ? event : {
|
|
193
|
-
id: event.id ?? generateId(),
|
|
194
|
-
type: event.type,
|
|
195
|
-
timestamp: event.timestamp ?? Date.now(),
|
|
196
|
-
metadata: {
|
|
197
|
-
...event.metadata,
|
|
198
|
-
env_name: event.metadata?.env_name ?? this.name
|
|
199
|
-
},
|
|
200
|
-
payload: event.payload ?? {}
|
|
201
|
-
};
|
|
202
|
-
for (const handler of this.wildcardHandlers) {
|
|
203
|
-
try {
|
|
204
|
-
handler(fullEvent);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
logger.error(`Error in EnvEvent handler: ${error}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
const handlers = this.eventHandlers.get(fullEvent.type);
|
|
210
|
-
if (handlers) {
|
|
211
|
-
for (const handler of handlers) {
|
|
212
|
-
try {
|
|
213
|
-
handler(fullEvent);
|
|
214
|
-
} catch (error) {
|
|
215
|
-
logger.error(`Error in EnvEvent handler for ${fullEvent.type}: ${error}`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
emit(type, payload, metadata) {
|
|
221
|
-
const event = {
|
|
222
|
-
id: generateId(),
|
|
223
|
-
type,
|
|
224
|
-
timestamp: Date.now(),
|
|
225
|
-
metadata: {
|
|
226
|
-
env_name: this.name,
|
|
227
|
-
...metadata
|
|
228
|
-
},
|
|
229
|
-
payload
|
|
230
|
-
};
|
|
231
|
-
this.pushEnvEvent(event);
|
|
232
|
-
}
|
|
233
|
-
async initializeComponents() {
|
|
234
|
-
logger.debug(`Starting component initialization, total: ${this.components.size}`);
|
|
235
|
-
const configComp = this.components.get("config");
|
|
236
|
-
if (configComp && configComp.getStatus() === "created") {
|
|
237
|
-
logger.debug(`Initializing ConfigComponent first...`);
|
|
238
|
-
await configComp.init({
|
|
239
|
-
name: "config",
|
|
240
|
-
version: configComp.version,
|
|
241
|
-
enabled: true,
|
|
242
|
-
env: this
|
|
243
|
-
});
|
|
244
|
-
logger.debug(`ConfigComponent initialized`);
|
|
245
|
-
} else {
|
|
246
|
-
logger.debug(`No ConfigComponent found, skipping first stage`);
|
|
247
|
-
}
|
|
248
|
-
const otherComponents = Array.from(this.components.values()).filter((c) => c.getStatus() === "created");
|
|
249
|
-
if (otherComponents.length > 0) {
|
|
250
|
-
logger.debug(`Initializing ${otherComponents.length} other components...`);
|
|
251
|
-
for (const component of otherComponents) {
|
|
252
|
-
logger.debug(`Initializing component: ${component.name}`);
|
|
253
|
-
await component.init({
|
|
254
|
-
name: component.name,
|
|
255
|
-
version: component.version,
|
|
256
|
-
enabled: true,
|
|
257
|
-
env: this
|
|
258
|
-
});
|
|
259
|
-
logger.debug(`Component initialized: ${component.name}`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
logger.debug(`All components initialized`);
|
|
263
|
-
}
|
|
264
|
-
async startComponents() {
|
|
265
|
-
const allComponents = Array.from(this.components.values());
|
|
266
|
-
if (allComponents.length > 0) {
|
|
267
|
-
logger.debug(`Starting ${allComponents.length} components...`);
|
|
268
|
-
for (const component of allComponents) {
|
|
269
|
-
logger.debug(`Starting component: ${component.name} (current status: ${component.getStatus()})`);
|
|
270
|
-
await component.start();
|
|
271
|
-
logger.debug(`Component started: ${component.name}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
async stopComponents() {
|
|
276
|
-
const componentsToStop = Array.from(this.components.values()).filter((c) => c.getStatus() !== "stopped");
|
|
277
|
-
if (componentsToStop.length > 0) {
|
|
278
|
-
logger.debug(`Stopping ${componentsToStop.length} components...`);
|
|
279
|
-
for (const component of componentsToStop) {
|
|
280
|
-
logger.debug(`Stopping component: ${component.name}`);
|
|
281
|
-
await component.stop();
|
|
282
|
-
logger.debug(`Component stopped: ${component.name}`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
async onInit() {
|
|
287
|
-
await this.initializeComponents();
|
|
288
|
-
logger.info(`Environment "${this.name}" initialized`);
|
|
289
|
-
}
|
|
290
|
-
async onStart() {
|
|
291
|
-
await this.startComponents();
|
|
292
|
-
logger.info(`Environment "${this.name}" started`);
|
|
293
|
-
}
|
|
294
|
-
async onStop() {
|
|
295
|
-
await this.stopComponents();
|
|
296
|
-
this.eventHandlers.clear();
|
|
297
|
-
this.wildcardHandlers.clear();
|
|
298
|
-
logger.info(`Environment "${this.name}" stopped`);
|
|
299
|
-
}
|
|
300
|
-
async init() {
|
|
301
|
-
Object.defineProperty(this, "env", {
|
|
302
|
-
value: this,
|
|
303
|
-
writable: true,
|
|
304
|
-
enumerable: false,
|
|
305
|
-
configurable: true
|
|
306
|
-
});
|
|
307
|
-
this.setStatus("initializing");
|
|
308
|
-
await this.onInit();
|
|
309
|
-
this.setStatus("running");
|
|
310
|
-
}
|
|
311
|
-
async start() {
|
|
312
|
-
if (this._started)
|
|
313
|
-
return;
|
|
314
|
-
this._started = true;
|
|
315
|
-
await this.onStart();
|
|
316
|
-
this.setStatus("running");
|
|
317
|
-
logger.info(`Environment "${this.name}" started`);
|
|
318
|
-
}
|
|
319
|
-
async stop() {
|
|
320
|
-
this.setStatus("stopping");
|
|
321
|
-
await this.onStop();
|
|
322
|
-
this.setStatus("stopped");
|
|
323
|
-
}
|
|
324
|
-
async loadServiceConfig(configPath) {
|
|
325
|
-
const configComponent = this.getComponent("config");
|
|
326
|
-
if (!configComponent) {
|
|
327
|
-
throw new Error("ConfigComponent not found. Please register ConfigComponent before loading service config.");
|
|
328
|
-
}
|
|
329
|
-
const xdgDataHome = configComponent.getXdgDataHome();
|
|
330
|
-
const fullPath = path.resolve(xdgDataHome, configPath);
|
|
331
|
-
if (!fsSync.existsSync(fullPath)) {
|
|
332
|
-
throw new Error(`Service config file not found: ${fullPath}`);
|
|
333
|
-
}
|
|
334
|
-
const content = fsSync.readFileSync(fullPath, "utf-8");
|
|
335
|
-
let config;
|
|
336
|
-
try {
|
|
337
|
-
config = JSON.parse(content);
|
|
338
|
-
} catch (e) {
|
|
339
|
-
throw new Error(`Failed to parse service config: ${e}`);
|
|
340
|
-
}
|
|
341
|
-
logger.debug(`Service config loaded from: ${fullPath}`);
|
|
342
|
-
return config;
|
|
343
|
-
}
|
|
344
|
-
generateComponentOptions(componentName, configEntry) {
|
|
345
|
-
const configComponent = this.getComponent("config");
|
|
346
|
-
if (!configComponent) {
|
|
347
|
-
throw new Error("ConfigComponent not found. Please register ConfigComponent before generating component options.");
|
|
348
|
-
}
|
|
349
|
-
const options = {
|
|
350
|
-
configComponent,
|
|
351
|
-
configPath: configEntry.configPath,
|
|
352
|
-
envPrefix: configEntry.envPrefix,
|
|
353
|
-
config: configEntry.config
|
|
354
|
-
};
|
|
355
|
-
logger.debug(`Generated options for component: ${componentName}`);
|
|
356
|
-
return options;
|
|
357
|
-
}
|
|
358
|
-
async registerComponentWithConfig(component, configEntry) {
|
|
359
|
-
if (!this.components.has(component.name)) {
|
|
360
|
-
this.registerComponent(component);
|
|
361
|
-
}
|
|
362
|
-
const options = this.generateComponentOptions(component.name, configEntry);
|
|
363
|
-
if (component.getStatus() === "running") {
|
|
364
|
-
logger.debug(`Component ${component.name} already initialized, skipping`);
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
await component.init({
|
|
368
|
-
name: component.name,
|
|
369
|
-
version: component.version,
|
|
370
|
-
enabled: configEntry.enabled ?? true,
|
|
371
|
-
env: this,
|
|
372
|
-
options
|
|
373
|
-
});
|
|
374
|
-
logger.debug(`Component ${component.name} registered and initialized with config`);
|
|
375
|
-
}
|
|
376
|
-
async initFromConfig(configPath) {
|
|
377
|
-
if (!this.env) {
|
|
378
|
-
Object.defineProperty(this, "env", {
|
|
379
|
-
value: this,
|
|
380
|
-
writable: true,
|
|
381
|
-
enumerable: false,
|
|
382
|
-
configurable: true
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
const serviceConfig = await this.loadServiceConfig(configPath);
|
|
386
|
-
if (serviceConfig.environment) {
|
|
387
|
-
if (serviceConfig.environment.name) {
|
|
388
|
-
this.name = serviceConfig.environment.name;
|
|
389
|
-
}
|
|
390
|
-
if (serviceConfig.environment.version) {
|
|
391
|
-
this.version = serviceConfig.environment.version;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
const configComponent = this.getComponent("config");
|
|
395
|
-
if (!configComponent) {
|
|
396
|
-
throw new Error("ConfigComponent not found. Please register ConfigComponent before initFromConfig.");
|
|
397
|
-
}
|
|
398
|
-
if (configComponent.getStatus() === "created") {
|
|
399
|
-
await configComponent.init({
|
|
400
|
-
name: "config",
|
|
401
|
-
version: configComponent.version,
|
|
402
|
-
enabled: true,
|
|
403
|
-
env: this
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
const components = serviceConfig.components || {};
|
|
407
|
-
for (const [componentName, configEntry] of Object.entries(components)) {
|
|
408
|
-
if (configEntry.enabled === false) {
|
|
409
|
-
logger.debug(`Component ${componentName} is disabled, skipping`);
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
const component = this.getComponent(componentName);
|
|
413
|
-
if (!component) {
|
|
414
|
-
logger.warn(`Component ${componentName} not registered, skipping`);
|
|
415
|
-
continue;
|
|
416
|
-
}
|
|
417
|
-
if (component.name === "config")
|
|
418
|
-
continue;
|
|
419
|
-
await this.registerComponentWithConfig(component, configEntry);
|
|
420
|
-
}
|
|
421
|
-
this.setStatus("running");
|
|
422
|
-
logger.info(`Environment "${this.name}" initialized from config: ${configPath}`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
__legacyDecorateClassTS([
|
|
426
|
-
TracedAs("env.handle_query", { recordParams: true, recordResult: true, log: true })
|
|
427
|
-
], BaseEnvironment.prototype, "handle_query", null);
|
|
428
|
-
// src/env/event-source/event-source-component.ts
|
|
429
|
-
import { join } from "path";
|
|
430
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
431
|
-
init_logger();
|
|
432
|
-
|
|
433
|
-
// src/env/event-source/event-source-config-registration.ts
|
|
434
|
-
var EVENT_SOURCE_DEFAULTS = {
|
|
435
|
-
"event-source.enabled": true,
|
|
436
|
-
"event-source.persistenceEnabled": true
|
|
437
|
-
};
|
|
438
|
-
var EVENT_SOURCE_CONFIG_REGISTRATION = {
|
|
439
|
-
name: "event-source",
|
|
440
|
-
sources: [
|
|
441
|
-
{ type: "env", envPrefix: "EVENT_SOURCE", priority: 20, watch: false }
|
|
442
|
-
],
|
|
443
|
-
keys: [
|
|
444
|
-
{ key: "event-source.enabled", sources: ["env", "file"] },
|
|
445
|
-
{ key: "event-source.persistenceEnabled", sources: ["env", "file"] },
|
|
446
|
-
{ key: "event-source.configPath", sources: ["env", "file"] }
|
|
447
|
-
]
|
|
448
|
-
};
|
|
449
|
-
|
|
450
15
|
// src/env/event-source/event-source-handlers.ts
|
|
451
16
|
import { spawn } from "child_process";
|
|
452
17
|
function matchEventType(eventType, patterns) {
|
|
@@ -596,7 +161,7 @@ class LarkCliInstance {
|
|
|
596
161
|
this.status = "error";
|
|
597
162
|
}
|
|
598
163
|
});
|
|
599
|
-
await new Promise((
|
|
164
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
600
165
|
this.status = "running";
|
|
601
166
|
}
|
|
602
167
|
async stop() {
|
|
@@ -789,7 +354,7 @@ class WebSocketInstance {
|
|
|
789
354
|
this.ws.on("close", () => {
|
|
790
355
|
this.status = "stopped";
|
|
791
356
|
});
|
|
792
|
-
await new Promise((
|
|
357
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
793
358
|
}
|
|
794
359
|
async stop() {
|
|
795
360
|
if (this.ws) {
|
|
@@ -865,9 +430,34 @@ var builtInHandlers = [
|
|
|
865
430
|
timerHandler,
|
|
866
431
|
websocketHandler
|
|
867
432
|
];
|
|
433
|
+
function getBuiltInHandler(type) {
|
|
434
|
+
return builtInHandlers.find((h) => h.type === type);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/env/event-source/event-source-component.ts
|
|
438
|
+
import { join } from "path";
|
|
439
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
440
|
+
init_logger();
|
|
441
|
+
|
|
442
|
+
// src/env/event-source/event-source-config-registration.ts
|
|
443
|
+
var EVENT_SOURCE_DEFAULTS = {
|
|
444
|
+
"event-source.enabled": true,
|
|
445
|
+
"event-source.persistenceEnabled": true
|
|
446
|
+
};
|
|
447
|
+
var EVENT_SOURCE_CONFIG_REGISTRATION = {
|
|
448
|
+
name: "event-source",
|
|
449
|
+
sources: [
|
|
450
|
+
{ type: "env", envPrefix: "EVENT_SOURCE", priority: 20, watch: false }
|
|
451
|
+
],
|
|
452
|
+
keys: [
|
|
453
|
+
{ key: "event-source.enabled", sources: ["env", "file"] },
|
|
454
|
+
{ key: "event-source.persistenceEnabled", sources: ["env", "file"] },
|
|
455
|
+
{ key: "event-source.configPath", sources: ["env", "file"] }
|
|
456
|
+
]
|
|
457
|
+
};
|
|
868
458
|
|
|
869
459
|
// src/env/event-source/event-source-component.ts
|
|
870
|
-
var
|
|
460
|
+
var logger = createLogger("event-source");
|
|
871
461
|
|
|
872
462
|
class EventSourceComponent extends BaseComponent {
|
|
873
463
|
name = "event-source";
|
|
@@ -929,7 +519,7 @@ class EventSourceComponent extends BaseComponent {
|
|
|
929
519
|
for (const handler of builtInHandlers) {
|
|
930
520
|
if (!this.handlers.has(handler.type)) {
|
|
931
521
|
this.handlers.set(handler.type, handler);
|
|
932
|
-
|
|
522
|
+
logger.debug(`Registered built-in handler: ${handler.type}`);
|
|
933
523
|
}
|
|
934
524
|
}
|
|
935
525
|
}
|
|
@@ -939,15 +529,15 @@ class EventSourceComponent extends BaseComponent {
|
|
|
939
529
|
}
|
|
940
530
|
registerHandler(handler) {
|
|
941
531
|
if (this.handlers.has(handler.type)) {
|
|
942
|
-
|
|
532
|
+
logger.warn(`Handler already registered for type: ${handler.type}, overwriting`);
|
|
943
533
|
}
|
|
944
534
|
this.handlers.set(handler.type, handler);
|
|
945
|
-
|
|
535
|
+
logger.debug(`Handler registered: ${handler.type}`);
|
|
946
536
|
}
|
|
947
537
|
unregisterHandler(type) {
|
|
948
538
|
const deleted = this.handlers.delete(type);
|
|
949
539
|
if (deleted) {
|
|
950
|
-
|
|
540
|
+
logger.debug(`Handler unregistered: ${type}`);
|
|
951
541
|
}
|
|
952
542
|
return deleted;
|
|
953
543
|
}
|
|
@@ -1037,7 +627,7 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1037
627
|
});
|
|
1038
628
|
}
|
|
1039
629
|
onConfigChange(event) {
|
|
1040
|
-
|
|
630
|
+
logger.info(`EventSource config changed: ${event.key}`, {
|
|
1041
631
|
oldValue: event.oldValue,
|
|
1042
632
|
newValue: event.newValue
|
|
1043
633
|
});
|
|
@@ -1056,9 +646,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1056
646
|
}
|
|
1057
647
|
this.sources.set(config.id, config);
|
|
1058
648
|
this.statuses.set(config.id, "created");
|
|
1059
|
-
|
|
649
|
+
logger.debug(`EventSource registered: ${config.id} (${config.type})`);
|
|
1060
650
|
this.saveConfig().catch((err) => {
|
|
1061
|
-
|
|
651
|
+
logger.error(`Failed to save config after registering ${config.id}:`, err);
|
|
1062
652
|
});
|
|
1063
653
|
}
|
|
1064
654
|
unregister(id) {
|
|
@@ -1073,9 +663,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1073
663
|
this.eventHandlers.delete(id);
|
|
1074
664
|
this.buffers.delete(id);
|
|
1075
665
|
if (existed) {
|
|
1076
|
-
|
|
666
|
+
logger.debug(`EventSource unregistered: ${id}`);
|
|
1077
667
|
this.saveConfig().catch((err) => {
|
|
1078
|
-
|
|
668
|
+
logger.error(`Failed to save config after unregistering ${id}:`, err);
|
|
1079
669
|
});
|
|
1080
670
|
}
|
|
1081
671
|
return existed;
|
|
@@ -1133,18 +723,18 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1133
723
|
type: "event-source.started",
|
|
1134
724
|
payload: { sourceId: id, sourceType: config.type }
|
|
1135
725
|
});
|
|
1136
|
-
|
|
726
|
+
logger.info(`EventSource started: ${id} (${config.type})`);
|
|
1137
727
|
} catch (error) {
|
|
1138
728
|
this.statuses.set(id, "error");
|
|
1139
|
-
|
|
729
|
+
logger.error(`EventSource failed to start: ${id}`, error);
|
|
1140
730
|
throw error;
|
|
1141
731
|
}
|
|
1142
732
|
}
|
|
1143
733
|
async stopSource(id) {
|
|
1144
734
|
const status = this.statuses.get(id);
|
|
1145
|
-
|
|
735
|
+
logger.info(`[EventSource ${id}] stopSource called, current status: ${status}`);
|
|
1146
736
|
if (status === "stopped" || status === "created") {
|
|
1147
|
-
|
|
737
|
+
logger.info(`[EventSource ${id}] already stopped/created, skipping`);
|
|
1148
738
|
return;
|
|
1149
739
|
}
|
|
1150
740
|
this.statuses.set(id, "stopping");
|
|
@@ -1160,10 +750,10 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1160
750
|
type: "event-source.stopped",
|
|
1161
751
|
payload: { sourceId: id, sourceType: config?.type }
|
|
1162
752
|
});
|
|
1163
|
-
|
|
753
|
+
logger.info(`EventSource stopped: ${id}`);
|
|
1164
754
|
} catch (error) {
|
|
1165
755
|
this.statuses.set(id, "error");
|
|
1166
|
-
|
|
756
|
+
logger.error(`EventSource failed to stop: ${id}`, error);
|
|
1167
757
|
throw error;
|
|
1168
758
|
}
|
|
1169
759
|
}
|
|
@@ -1173,7 +763,7 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1173
763
|
}
|
|
1174
764
|
const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
|
|
1175
765
|
const dataDir = join(home, ".roy-agent");
|
|
1176
|
-
if (!
|
|
766
|
+
if (!existsSync(dataDir)) {
|
|
1177
767
|
mkdirSync(dataDir, { recursive: true });
|
|
1178
768
|
}
|
|
1179
769
|
return join(dataDir, "event-sources.json");
|
|
@@ -1188,9 +778,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1188
778
|
sources: Array.from(this.sources.values())
|
|
1189
779
|
};
|
|
1190
780
|
writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1191
|
-
|
|
781
|
+
logger.debug(`Saved ${this.sources.size} event source configurations`);
|
|
1192
782
|
} catch (error) {
|
|
1193
|
-
|
|
783
|
+
logger.error("Failed to save event source configurations:", error);
|
|
1194
784
|
throw error;
|
|
1195
785
|
}
|
|
1196
786
|
}
|
|
@@ -1199,14 +789,14 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1199
789
|
return;
|
|
1200
790
|
try {
|
|
1201
791
|
const configPath = this.getConfigFilePath();
|
|
1202
|
-
if (!
|
|
1203
|
-
|
|
792
|
+
if (!existsSync(configPath)) {
|
|
793
|
+
logger.debug(`No event source config file found at ${configPath}`);
|
|
1204
794
|
return;
|
|
1205
795
|
}
|
|
1206
|
-
const content =
|
|
796
|
+
const content = readFileSync(configPath, "utf-8");
|
|
1207
797
|
const config = JSON.parse(content);
|
|
1208
798
|
if (!config.sources || !Array.isArray(config.sources)) {
|
|
1209
|
-
|
|
799
|
+
logger.warn("Invalid event source config format, skipping load");
|
|
1210
800
|
return;
|
|
1211
801
|
}
|
|
1212
802
|
let loadedCount = 0;
|
|
@@ -1217,10 +807,11 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1217
807
|
loadedCount++;
|
|
1218
808
|
}
|
|
1219
809
|
}
|
|
1220
|
-
|
|
810
|
+
logger.info(`Loaded ${loadedCount} event source configurations`);
|
|
1221
811
|
} catch (error) {
|
|
1222
|
-
|
|
812
|
+
logger.error("Failed to load event source configurations:", error);
|
|
1223
813
|
}
|
|
1224
814
|
}
|
|
1225
815
|
}
|
|
1226
|
-
|
|
816
|
+
|
|
817
|
+
export { larkCliHandler, timerHandler, websocketHandler, builtInHandlers, getBuiltInHandler, EventSourceComponent };
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ContextError,
|
|
3
|
+
ErrorCodes
|
|
4
|
+
} from "./roy-agent-core-ctdhjv68.js";
|
|
5
|
+
import {
|
|
6
|
+
BaseComponent
|
|
7
|
+
} from "./roy-agent-core-kkbwepqb.js";
|
|
8
|
+
import {
|
|
9
|
+
TracedAs,
|
|
10
|
+
init_decorator
|
|
11
|
+
} from "./roy-agent-core-zgypchmt.js";
|
|
12
|
+
import {
|
|
13
|
+
createLogger,
|
|
14
|
+
init_logger
|
|
15
|
+
} from "./roy-agent-core-44hnfb02.js";
|
|
16
|
+
import {
|
|
17
|
+
__legacyDecorateClassTS
|
|
18
|
+
} from "./roy-agent-core-fs0mn2jk.js";
|
|
19
|
+
|
|
20
|
+
// src/env/environment.ts
|
|
21
|
+
init_logger();
|
|
22
|
+
|
|
23
|
+
// src/utils/id.ts
|
|
24
|
+
function generateId(prefix = "id") {
|
|
25
|
+
const timestamp = Date.now().toString(36);
|
|
26
|
+
const random = Math.random().toString(36).substring(2, 11);
|
|
27
|
+
return `${prefix}_${timestamp}_${random}`;
|
|
28
|
+
}
|
|
29
|
+
function generateDescendingId(prefix = "id") {
|
|
30
|
+
const timestamp = (Number.MAX_SAFE_INTEGER - Date.now()).toString(36);
|
|
31
|
+
const random = Math.random().toString(36).substring(2, 11);
|
|
32
|
+
return `${prefix}_${timestamp}_${random}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/env/environment.ts
|
|
36
|
+
init_decorator();
|
|
37
|
+
import * as fsSync from "fs";
|
|
38
|
+
import * as path from "path";
|
|
39
|
+
var logger = createLogger("environment");
|
|
40
|
+
|
|
41
|
+
class BaseEnvironment extends BaseComponent {
|
|
42
|
+
name;
|
|
43
|
+
version;
|
|
44
|
+
components = new Map;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
super();
|
|
47
|
+
this.name = config?.name ?? "base-environment";
|
|
48
|
+
this.version = config?.version ?? "1.0.0";
|
|
49
|
+
this.registerDefaultComponents();
|
|
50
|
+
}
|
|
51
|
+
registerDefaultComponents() {}
|
|
52
|
+
getConfig() {
|
|
53
|
+
return {
|
|
54
|
+
name: this.name,
|
|
55
|
+
version: this.version,
|
|
56
|
+
enabled: true,
|
|
57
|
+
env: this
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
registerComponent(component) {
|
|
61
|
+
this.components.set(component.name, component);
|
|
62
|
+
logger.debug(`Component registered: ${component.name}`);
|
|
63
|
+
}
|
|
64
|
+
unregisterComponent(name) {
|
|
65
|
+
const component = this.components.get(name);
|
|
66
|
+
if (component) {
|
|
67
|
+
this.components.delete(name);
|
|
68
|
+
logger.debug(`Component unregistered: ${name}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
getComponent(name) {
|
|
72
|
+
return this.components.get(name);
|
|
73
|
+
}
|
|
74
|
+
listComponents() {
|
|
75
|
+
return Array.from(this.components.values());
|
|
76
|
+
}
|
|
77
|
+
async handle_query(query, context) {
|
|
78
|
+
const agentComponent = this.getComponent("agent");
|
|
79
|
+
if (!agentComponent) {
|
|
80
|
+
throw new Error("AgentComponent not found. Please register AgentComponent before calling handle_query.");
|
|
81
|
+
}
|
|
82
|
+
let systemPrompt = "You are a helpful assistant.";
|
|
83
|
+
let promptSource = "fallback";
|
|
84
|
+
try {
|
|
85
|
+
const promptComponent = this.getComponent("prompt");
|
|
86
|
+
if (promptComponent) {
|
|
87
|
+
const loadedPrompt = await promptComponent.getPrompt("default");
|
|
88
|
+
if (loadedPrompt) {
|
|
89
|
+
systemPrompt = loadedPrompt;
|
|
90
|
+
promptSource = "PromptComponent";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch (err) {
|
|
94
|
+
logger.warn(`[handle_query] Failed to get prompt from PromptComponent: ${err}`);
|
|
95
|
+
}
|
|
96
|
+
logger.info(`[handle_query] Using system prompt from ${promptSource}, length: ${systemPrompt.length}`);
|
|
97
|
+
let finalSystemPrompt = systemPrompt;
|
|
98
|
+
if (systemPrompt.includes("{{memory}}")) {
|
|
99
|
+
try {
|
|
100
|
+
const memoryComponent = this.getComponent("memory");
|
|
101
|
+
if (memoryComponent) {
|
|
102
|
+
const memoryContent = await memoryComponent.recallMemory();
|
|
103
|
+
finalSystemPrompt = systemPrompt.replace("{{memory}}", memoryContent || "(No memory)");
|
|
104
|
+
logger.info(`[handle_query] Injected memory content, length: ${memoryContent.length}`);
|
|
105
|
+
} else {
|
|
106
|
+
finalSystemPrompt = systemPrompt.replace("{{memory}}", "(Memory component not available)");
|
|
107
|
+
}
|
|
108
|
+
} catch (err) {
|
|
109
|
+
logger.warn(`[handle_query] Failed to load memory content: ${err}`);
|
|
110
|
+
finalSystemPrompt = systemPrompt.replace("{{memory}}", "(Failed to load memory)");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (finalSystemPrompt.includes("{{workspace_dir}}")) {
|
|
114
|
+
const workspaceDir = process.cwd();
|
|
115
|
+
finalSystemPrompt = finalSystemPrompt.replace("{{workspace_dir}}", workspaceDir);
|
|
116
|
+
logger.debug(`[handle_query] Injected workspace_dir: ${workspaceDir}`);
|
|
117
|
+
}
|
|
118
|
+
const agentName = context?.agentType && context.agentType !== "default" ? context.agentType : "default";
|
|
119
|
+
let agent = agentComponent.getAgent(agentName);
|
|
120
|
+
if (!agent) {
|
|
121
|
+
if (agentName !== "default") {
|
|
122
|
+
logger.warn(`[handle_query] Agent "${agentName}" not found, falling back to "default"`);
|
|
123
|
+
}
|
|
124
|
+
agent = agentComponent.getAgent("default");
|
|
125
|
+
}
|
|
126
|
+
if (!agent) {
|
|
127
|
+
agent = agentComponent.registerAgent("default", {
|
|
128
|
+
type: "primary",
|
|
129
|
+
systemPrompt: finalSystemPrompt
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const result = await agentComponent.run(agent.name, query, context);
|
|
133
|
+
if (result.error) {
|
|
134
|
+
const errorMsg = result.error.toLowerCase();
|
|
135
|
+
if (errorMsg.includes("context") || errorMsg.includes("threshold") || errorMsg.includes("token") || result.error.includes("CTX_001")) {
|
|
136
|
+
const usageMatch = result.error.match(/(\d+)\/(\d+)\s*\(([\d.]+)%\)/);
|
|
137
|
+
let usage;
|
|
138
|
+
let contextWindow;
|
|
139
|
+
if (usageMatch) {
|
|
140
|
+
const totalTokens = parseInt(usageMatch[1], 10);
|
|
141
|
+
usage = {
|
|
142
|
+
promptTokens: totalTokens,
|
|
143
|
+
completionTokens: 0,
|
|
144
|
+
totalTokens
|
|
145
|
+
};
|
|
146
|
+
contextWindow = parseInt(usageMatch[2], 10);
|
|
147
|
+
}
|
|
148
|
+
const ctxError = new ContextError(result.error, ErrorCodes.CONTEXT_THRESHOLD_EXCEEDED, context?.sessionId, usage, contextWindow);
|
|
149
|
+
throw ctxError;
|
|
150
|
+
}
|
|
151
|
+
throw new Error(result.error);
|
|
152
|
+
}
|
|
153
|
+
return result.finalText || "";
|
|
154
|
+
}
|
|
155
|
+
async handle_action(action, context) {
|
|
156
|
+
throw new Error("handle_action not implemented. Override in subclass.");
|
|
157
|
+
}
|
|
158
|
+
eventHandlers = new Map;
|
|
159
|
+
wildcardHandlers = new Set;
|
|
160
|
+
subscribe(handler) {
|
|
161
|
+
this.wildcardHandlers.add(handler);
|
|
162
|
+
logger.debug(`EnvEvent handler subscribed (wildcard)`);
|
|
163
|
+
return () => {
|
|
164
|
+
this.wildcardHandlers.delete(handler);
|
|
165
|
+
logger.debug(`EnvEvent handler unsubscribed (wildcard)`);
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
subscribeTo(eventType, handler) {
|
|
169
|
+
const types = Array.isArray(eventType) ? eventType : [eventType];
|
|
170
|
+
for (const type of types) {
|
|
171
|
+
if (!this.eventHandlers.has(type)) {
|
|
172
|
+
this.eventHandlers.set(type, new Set);
|
|
173
|
+
}
|
|
174
|
+
this.eventHandlers.get(type).add(handler);
|
|
175
|
+
}
|
|
176
|
+
logger.debug(`EnvEvent handler subscribed for types: ${types.join(", ")}`);
|
|
177
|
+
return () => {
|
|
178
|
+
for (const type of types) {
|
|
179
|
+
this.eventHandlers.get(type)?.delete(handler);
|
|
180
|
+
}
|
|
181
|
+
logger.debug(`EnvEvent handler unsubscribed for types: ${types.join(", ")}`);
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
subscribeAll(handler) {
|
|
185
|
+
return this.subscribe(handler);
|
|
186
|
+
}
|
|
187
|
+
pushEnvEvent(event) {
|
|
188
|
+
const fullEvent = "id" in event && event.id ? event : {
|
|
189
|
+
id: event.id ?? generateId(),
|
|
190
|
+
type: event.type,
|
|
191
|
+
timestamp: event.timestamp ?? Date.now(),
|
|
192
|
+
metadata: {
|
|
193
|
+
...event.metadata,
|
|
194
|
+
env_name: event.metadata?.env_name ?? this.name
|
|
195
|
+
},
|
|
196
|
+
payload: event.payload ?? {}
|
|
197
|
+
};
|
|
198
|
+
for (const handler of this.wildcardHandlers) {
|
|
199
|
+
try {
|
|
200
|
+
handler(fullEvent);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
logger.error(`Error in EnvEvent handler: ${error}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const handlers = this.eventHandlers.get(fullEvent.type);
|
|
206
|
+
if (handlers) {
|
|
207
|
+
for (const handler of handlers) {
|
|
208
|
+
try {
|
|
209
|
+
handler(fullEvent);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
logger.error(`Error in EnvEvent handler for ${fullEvent.type}: ${error}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
emit(type, payload, metadata) {
|
|
217
|
+
const event = {
|
|
218
|
+
id: generateId(),
|
|
219
|
+
type,
|
|
220
|
+
timestamp: Date.now(),
|
|
221
|
+
metadata: {
|
|
222
|
+
env_name: this.name,
|
|
223
|
+
...metadata
|
|
224
|
+
},
|
|
225
|
+
payload
|
|
226
|
+
};
|
|
227
|
+
this.pushEnvEvent(event);
|
|
228
|
+
}
|
|
229
|
+
async initializeComponents() {
|
|
230
|
+
logger.debug(`Starting component initialization, total: ${this.components.size}`);
|
|
231
|
+
const configComp = this.components.get("config");
|
|
232
|
+
if (configComp && configComp.getStatus() === "created") {
|
|
233
|
+
logger.debug(`Initializing ConfigComponent first...`);
|
|
234
|
+
await configComp.init({
|
|
235
|
+
name: "config",
|
|
236
|
+
version: configComp.version,
|
|
237
|
+
enabled: true,
|
|
238
|
+
env: this
|
|
239
|
+
});
|
|
240
|
+
logger.debug(`ConfigComponent initialized`);
|
|
241
|
+
} else {
|
|
242
|
+
logger.debug(`No ConfigComponent found, skipping first stage`);
|
|
243
|
+
}
|
|
244
|
+
const otherComponents = Array.from(this.components.values()).filter((c) => c.getStatus() === "created");
|
|
245
|
+
if (otherComponents.length > 0) {
|
|
246
|
+
logger.debug(`Initializing ${otherComponents.length} other components...`);
|
|
247
|
+
for (const component of otherComponents) {
|
|
248
|
+
logger.debug(`Initializing component: ${component.name}`);
|
|
249
|
+
await component.init({
|
|
250
|
+
name: component.name,
|
|
251
|
+
version: component.version,
|
|
252
|
+
enabled: true,
|
|
253
|
+
env: this
|
|
254
|
+
});
|
|
255
|
+
logger.debug(`Component initialized: ${component.name}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
logger.debug(`All components initialized`);
|
|
259
|
+
}
|
|
260
|
+
async startComponents() {
|
|
261
|
+
const allComponents = Array.from(this.components.values());
|
|
262
|
+
if (allComponents.length > 0) {
|
|
263
|
+
logger.debug(`Starting ${allComponents.length} components...`);
|
|
264
|
+
for (const component of allComponents) {
|
|
265
|
+
logger.debug(`Starting component: ${component.name} (current status: ${component.getStatus()})`);
|
|
266
|
+
await component.start();
|
|
267
|
+
logger.debug(`Component started: ${component.name}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async stopComponents() {
|
|
272
|
+
const componentsToStop = Array.from(this.components.values()).filter((c) => c.getStatus() !== "stopped");
|
|
273
|
+
if (componentsToStop.length > 0) {
|
|
274
|
+
logger.debug(`Stopping ${componentsToStop.length} components...`);
|
|
275
|
+
for (const component of componentsToStop) {
|
|
276
|
+
logger.debug(`Stopping component: ${component.name}`);
|
|
277
|
+
await component.stop();
|
|
278
|
+
logger.debug(`Component stopped: ${component.name}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async onInit() {
|
|
283
|
+
await this.initializeComponents();
|
|
284
|
+
logger.info(`Environment "${this.name}" initialized`);
|
|
285
|
+
}
|
|
286
|
+
async onStart() {
|
|
287
|
+
await this.startComponents();
|
|
288
|
+
logger.info(`Environment "${this.name}" started`);
|
|
289
|
+
}
|
|
290
|
+
async onStop() {
|
|
291
|
+
await this.stopComponents();
|
|
292
|
+
this.eventHandlers.clear();
|
|
293
|
+
this.wildcardHandlers.clear();
|
|
294
|
+
logger.info(`Environment "${this.name}" stopped`);
|
|
295
|
+
}
|
|
296
|
+
async init() {
|
|
297
|
+
Object.defineProperty(this, "env", {
|
|
298
|
+
value: this,
|
|
299
|
+
writable: true,
|
|
300
|
+
enumerable: false,
|
|
301
|
+
configurable: true
|
|
302
|
+
});
|
|
303
|
+
this.setStatus("initializing");
|
|
304
|
+
await this.onInit();
|
|
305
|
+
this.setStatus("running");
|
|
306
|
+
}
|
|
307
|
+
async start() {
|
|
308
|
+
if (this._started)
|
|
309
|
+
return;
|
|
310
|
+
this._started = true;
|
|
311
|
+
await this.onStart();
|
|
312
|
+
this.setStatus("running");
|
|
313
|
+
logger.info(`Environment "${this.name}" started`);
|
|
314
|
+
}
|
|
315
|
+
async stop() {
|
|
316
|
+
this.setStatus("stopping");
|
|
317
|
+
await this.onStop();
|
|
318
|
+
this.setStatus("stopped");
|
|
319
|
+
}
|
|
320
|
+
async loadServiceConfig(configPath) {
|
|
321
|
+
const configComponent = this.getComponent("config");
|
|
322
|
+
if (!configComponent) {
|
|
323
|
+
throw new Error("ConfigComponent not found. Please register ConfigComponent before loading service config.");
|
|
324
|
+
}
|
|
325
|
+
const xdgDataHome = configComponent.getXdgDataHome();
|
|
326
|
+
const fullPath = path.resolve(xdgDataHome, configPath);
|
|
327
|
+
if (!fsSync.existsSync(fullPath)) {
|
|
328
|
+
throw new Error(`Service config file not found: ${fullPath}`);
|
|
329
|
+
}
|
|
330
|
+
const content = fsSync.readFileSync(fullPath, "utf-8");
|
|
331
|
+
let config;
|
|
332
|
+
try {
|
|
333
|
+
config = JSON.parse(content);
|
|
334
|
+
} catch (e) {
|
|
335
|
+
throw new Error(`Failed to parse service config: ${e}`);
|
|
336
|
+
}
|
|
337
|
+
logger.debug(`Service config loaded from: ${fullPath}`);
|
|
338
|
+
return config;
|
|
339
|
+
}
|
|
340
|
+
generateComponentOptions(componentName, configEntry) {
|
|
341
|
+
const configComponent = this.getComponent("config");
|
|
342
|
+
if (!configComponent) {
|
|
343
|
+
throw new Error("ConfigComponent not found. Please register ConfigComponent before generating component options.");
|
|
344
|
+
}
|
|
345
|
+
const options = {
|
|
346
|
+
configComponent,
|
|
347
|
+
configPath: configEntry.configPath,
|
|
348
|
+
envPrefix: configEntry.envPrefix,
|
|
349
|
+
config: configEntry.config
|
|
350
|
+
};
|
|
351
|
+
logger.debug(`Generated options for component: ${componentName}`);
|
|
352
|
+
return options;
|
|
353
|
+
}
|
|
354
|
+
async registerComponentWithConfig(component, configEntry) {
|
|
355
|
+
if (!this.components.has(component.name)) {
|
|
356
|
+
this.registerComponent(component);
|
|
357
|
+
}
|
|
358
|
+
const options = this.generateComponentOptions(component.name, configEntry);
|
|
359
|
+
if (component.getStatus() === "running") {
|
|
360
|
+
logger.debug(`Component ${component.name} already initialized, skipping`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
await component.init({
|
|
364
|
+
name: component.name,
|
|
365
|
+
version: component.version,
|
|
366
|
+
enabled: configEntry.enabled ?? true,
|
|
367
|
+
env: this,
|
|
368
|
+
options
|
|
369
|
+
});
|
|
370
|
+
logger.debug(`Component ${component.name} registered and initialized with config`);
|
|
371
|
+
}
|
|
372
|
+
async initFromConfig(configPath) {
|
|
373
|
+
if (!this.env) {
|
|
374
|
+
Object.defineProperty(this, "env", {
|
|
375
|
+
value: this,
|
|
376
|
+
writable: true,
|
|
377
|
+
enumerable: false,
|
|
378
|
+
configurable: true
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
const serviceConfig = await this.loadServiceConfig(configPath);
|
|
382
|
+
if (serviceConfig.environment) {
|
|
383
|
+
if (serviceConfig.environment.name) {
|
|
384
|
+
this.name = serviceConfig.environment.name;
|
|
385
|
+
}
|
|
386
|
+
if (serviceConfig.environment.version) {
|
|
387
|
+
this.version = serviceConfig.environment.version;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const configComponent = this.getComponent("config");
|
|
391
|
+
if (!configComponent) {
|
|
392
|
+
throw new Error("ConfigComponent not found. Please register ConfigComponent before initFromConfig.");
|
|
393
|
+
}
|
|
394
|
+
if (configComponent.getStatus() === "created") {
|
|
395
|
+
await configComponent.init({
|
|
396
|
+
name: "config",
|
|
397
|
+
version: configComponent.version,
|
|
398
|
+
enabled: true,
|
|
399
|
+
env: this
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
const components = serviceConfig.components || {};
|
|
403
|
+
for (const [componentName, configEntry] of Object.entries(components)) {
|
|
404
|
+
if (configEntry.enabled === false) {
|
|
405
|
+
logger.debug(`Component ${componentName} is disabled, skipping`);
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
const component = this.getComponent(componentName);
|
|
409
|
+
if (!component) {
|
|
410
|
+
logger.warn(`Component ${componentName} not registered, skipping`);
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
if (component.name === "config")
|
|
414
|
+
continue;
|
|
415
|
+
await this.registerComponentWithConfig(component, configEntry);
|
|
416
|
+
}
|
|
417
|
+
this.setStatus("running");
|
|
418
|
+
logger.info(`Environment "${this.name}" initialized from config: ${configPath}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
__legacyDecorateClassTS([
|
|
422
|
+
TracedAs("env.handle_query", { recordParams: true, recordResult: true, log: true })
|
|
423
|
+
], BaseEnvironment.prototype, "handle_query", null);
|
|
424
|
+
export { generateId, generateDescendingId, BaseEnvironment };
|