skyloom 1.4.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/.github/workflows/ci.yml +36 -0
- package/CONVERSION_PLAN.md +191 -0
- package/README.md +67 -0
- package/dist/agents/dew.d.ts +15 -0
- package/dist/agents/dew.d.ts.map +1 -0
- package/dist/agents/dew.js +74 -0
- package/dist/agents/dew.js.map +1 -0
- package/dist/agents/fair.d.ts +15 -0
- package/dist/agents/fair.d.ts.map +1 -0
- package/dist/agents/fair.js +106 -0
- package/dist/agents/fair.js.map +1 -0
- package/dist/agents/fog.d.ts +15 -0
- package/dist/agents/fog.d.ts.map +1 -0
- package/dist/agents/fog.js +52 -0
- package/dist/agents/fog.js.map +1 -0
- package/dist/agents/frost.d.ts +15 -0
- package/dist/agents/frost.d.ts.map +1 -0
- package/dist/agents/frost.js +54 -0
- package/dist/agents/frost.js.map +1 -0
- package/dist/agents/rain.d.ts +15 -0
- package/dist/agents/rain.d.ts.map +1 -0
- package/dist/agents/rain.js +54 -0
- package/dist/agents/rain.js.map +1 -0
- package/dist/agents/snow.d.ts +27 -0
- package/dist/agents/snow.d.ts.map +1 -0
- package/dist/agents/snow.js +226 -0
- package/dist/agents/snow.js.map +1 -0
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +402 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/mode.d.ts +17 -0
- package/dist/cli/mode.d.ts.map +1 -0
- package/dist/cli/mode.js +56 -0
- package/dist/cli/mode.js.map +1 -0
- package/dist/core/agent.d.ts +174 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +1332 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/agent_helpers.d.ts +51 -0
- package/dist/core/agent_helpers.d.ts.map +1 -0
- package/dist/core/agent_helpers.js +477 -0
- package/dist/core/agent_helpers.js.map +1 -0
- package/dist/core/bus.d.ts +99 -0
- package/dist/core/bus.d.ts.map +1 -0
- package/dist/core/bus.js +191 -0
- package/dist/core/bus.js.map +1 -0
- package/dist/core/cache.d.ts +63 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +121 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/checkpoint.d.ts +19 -0
- package/dist/core/checkpoint.d.ts.map +1 -0
- package/dist/core/checkpoint.js +120 -0
- package/dist/core/checkpoint.js.map +1 -0
- package/dist/core/circuit_breaker.d.ts +46 -0
- package/dist/core/circuit_breaker.d.ts.map +1 -0
- package/dist/core/circuit_breaker.js +99 -0
- package/dist/core/circuit_breaker.js.map +1 -0
- package/dist/core/config.d.ts +97 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +281 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/constants.d.ts +78 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +84 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/factory.d.ts +63 -0
- package/dist/core/factory.d.ts.map +1 -0
- package/dist/core/factory.js +537 -0
- package/dist/core/factory.js.map +1 -0
- package/dist/core/icons.d.ts +28 -0
- package/dist/core/icons.d.ts.map +1 -0
- package/dist/core/icons.js +86 -0
- package/dist/core/icons.js.map +1 -0
- package/dist/core/index.d.ts +29 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +54 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/llm.d.ts +121 -0
- package/dist/core/llm.d.ts.map +1 -0
- package/dist/core/llm.js +532 -0
- package/dist/core/llm.js.map +1 -0
- package/dist/core/logger.d.ts +57 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +122 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mcp.d.ts +190 -0
- package/dist/core/mcp.d.ts.map +1 -0
- package/dist/core/mcp.js +822 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/mcp_server.d.ts +26 -0
- package/dist/core/mcp_server.d.ts.map +1 -0
- package/dist/core/mcp_server.js +211 -0
- package/dist/core/mcp_server.js.map +1 -0
- package/dist/core/memory.d.ts +190 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +988 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/middleware.d.ts +114 -0
- package/dist/core/middleware.d.ts.map +1 -0
- package/dist/core/middleware.js +248 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/pipelines.d.ts +87 -0
- package/dist/core/pipelines.d.ts.map +1 -0
- package/dist/core/pipelines.js +301 -0
- package/dist/core/pipelines.js.map +1 -0
- package/dist/core/profile.d.ts +23 -0
- package/dist/core/profile.d.ts.map +1 -0
- package/dist/core/profile.js +289 -0
- package/dist/core/profile.js.map +1 -0
- package/dist/core/router.d.ts +24 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +111 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/schemas.d.ts +82 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +200 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/semantic.d.ts +92 -0
- package/dist/core/semantic.d.ts.map +1 -0
- package/dist/core/semantic.js +175 -0
- package/dist/core/semantic.js.map +1 -0
- package/dist/core/skill.d.ts +68 -0
- package/dist/core/skill.d.ts.map +1 -0
- package/dist/core/skill.js +350 -0
- package/dist/core/skill.js.map +1 -0
- package/dist/core/tool.d.ts +99 -0
- package/dist/core/tool.d.ts.map +1 -0
- package/dist/core/tool.js +341 -0
- package/dist/core/tool.js.map +1 -0
- package/dist/core/tool_router.d.ts +29 -0
- package/dist/core/tool_router.d.ts.map +1 -0
- package/dist/core/tool_router.js +172 -0
- package/dist/core/tool_router.js.map +1 -0
- package/dist/core/workspace.d.ts +48 -0
- package/dist/core/workspace.d.ts.map +1 -0
- package/dist/core/workspace.js +179 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/plugins/loader.d.ts +17 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +96 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/skills/loader.d.ts +9 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +78 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/tools/builtin.d.ts +10 -0
- package/dist/tools/builtin.d.ts.map +1 -0
- package/dist/tools/builtin.js +414 -0
- package/dist/tools/builtin.js.map +1 -0
- package/dist/tools/computer.d.ts +12 -0
- package/dist/tools/computer.d.ts.map +1 -0
- package/dist/tools/computer.js +326 -0
- package/dist/tools/computer.js.map +1 -0
- package/dist/tools/delegate.d.ts +10 -0
- package/dist/tools/delegate.d.ts.map +1 -0
- package/dist/tools/delegate.js +45 -0
- package/dist/tools/delegate.js.map +1 -0
- package/dist/web/server.d.ts +5 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +647 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web/tts.d.ts +33 -0
- package/dist/web/tts.d.ts.map +1 -0
- package/dist/web/tts.js +69 -0
- package/dist/web/tts.js.map +1 -0
- package/package.json +60 -0
- package/scripts/install.js +48 -0
- package/scripts/link.js +10 -0
- package/setup.bat +79 -0
- package/skill-test-ty2fOA/test.md +10 -0
- package/src/agents/dew.ts +70 -0
- package/src/agents/fair.ts +102 -0
- package/src/agents/fog.ts +48 -0
- package/src/agents/frost.ts +50 -0
- package/src/agents/rain.ts +50 -0
- package/src/agents/snow.ts +239 -0
- package/src/cli/main.ts +405 -0
- package/src/cli/mode.ts +58 -0
- package/src/core/agent.ts +1506 -0
- package/src/core/agent_helpers.ts +461 -0
- package/src/core/bus.ts +221 -0
- package/src/core/cache.ts +153 -0
- package/src/core/checkpoint.ts +94 -0
- package/src/core/circuit_breaker.ts +119 -0
- package/src/core/config.ts +341 -0
- package/src/core/constants.ts +95 -0
- package/src/core/factory.ts +627 -0
- package/src/core/icons.ts +53 -0
- package/src/core/index.ts +31 -0
- package/src/core/llm.ts +724 -0
- package/src/core/logger.ts +144 -0
- package/src/core/mcp.ts +953 -0
- package/src/core/mcp_server.ts +176 -0
- package/src/core/memory.ts +1169 -0
- package/src/core/middleware.ts +350 -0
- package/src/core/pipelines.ts +424 -0
- package/src/core/profile.ts +255 -0
- package/src/core/router.ts +124 -0
- package/src/core/schemas.ts +282 -0
- package/src/core/semantic.ts +211 -0
- package/src/core/skill.ts +342 -0
- package/src/core/tool.ts +427 -0
- package/src/core/tool_router.ts +193 -0
- package/src/core/workspace.ts +150 -0
- package/src/plugins/loader.ts +66 -0
- package/src/skills/loader.ts +46 -0
- package/src/sql.js.d.ts +29 -0
- package/src/tools/builtin.ts +382 -0
- package/src/tools/computer.ts +269 -0
- package/src/tools/delegate.ts +49 -0
- package/src/web/server.ts +634 -0
- package/src/web/tts.ts +93 -0
- package/tests/bus.test.ts +121 -0
- package/tests/icons.test.ts +45 -0
- package/tests/router.test.ts +86 -0
- package/tests/schemas.test.ts +51 -0
- package/tests/semantic.test.ts +83 -0
- package/tests/setup.ts +10 -0
- package/tests/skill.test.ts +172 -0
- package/tests/tool.test.ts +108 -0
- package/tests/tool_router.test.ts +71 -0
- package/tsconfig.json +37 -0
- package/vitest.config.ts +17 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System factory — unified Agent creation and task orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Avoids duplication between CLI and web entry points.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { BaseAgent, Task as AgentTask, TaskState } from './agent';
|
|
8
|
+
import { MessageBus } from './bus';
|
|
9
|
+
import { loadConfig } from './config';
|
|
10
|
+
import { LLMClient } from './llm';
|
|
11
|
+
import { getLogger } from './logger';
|
|
12
|
+
import { SkillRegistry } from './skill';
|
|
13
|
+
import { ToolRegistry } from './tool';
|
|
14
|
+
|
|
15
|
+
const log = getLogger('factory');
|
|
16
|
+
|
|
17
|
+
export class SystemContext {
|
|
18
|
+
config: ReturnType<typeof loadConfig>;
|
|
19
|
+
bus: MessageBus;
|
|
20
|
+
llm: LLMClient;
|
|
21
|
+
agentMap: Map<string, BaseAgent>;
|
|
22
|
+
toolRegistry: ToolRegistry;
|
|
23
|
+
workspacePath: string = '';
|
|
24
|
+
mcp: any = null;
|
|
25
|
+
mcpStatus: string[] = [];
|
|
26
|
+
|
|
27
|
+
constructor(opts: {
|
|
28
|
+
config: ReturnType<typeof loadConfig>;
|
|
29
|
+
bus: MessageBus;
|
|
30
|
+
llm: LLMClient;
|
|
31
|
+
agentMap: Map<string, BaseAgent>;
|
|
32
|
+
toolRegistry: ToolRegistry;
|
|
33
|
+
workspacePath?: string;
|
|
34
|
+
mcp?: any;
|
|
35
|
+
mcpStatus?: string[];
|
|
36
|
+
}) {
|
|
37
|
+
this.config = opts.config;
|
|
38
|
+
this.bus = opts.bus;
|
|
39
|
+
this.llm = opts.llm;
|
|
40
|
+
this.agentMap = opts.agentMap;
|
|
41
|
+
this.toolRegistry = opts.toolRegistry;
|
|
42
|
+
this.workspacePath = opts.workspacePath || '';
|
|
43
|
+
this.mcp = opts.mcp || null;
|
|
44
|
+
this.mcpStatus = opts.mcpStatus || [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async initAll(): Promise<void> {
|
|
48
|
+
if (this.mcp) {
|
|
49
|
+
try {
|
|
50
|
+
this.mcpStatus = await this.mcp.connectAll();
|
|
51
|
+
if (this.mcpStatus.length > 0) {
|
|
52
|
+
log.info('mcp_connected', { servers: this.mcpStatus.join(', ') });
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
log.warn('mcp_connect_all_failed', { error: String(e) });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const agent of this.agentMap.values()) {
|
|
59
|
+
await agent.init();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async closeAll(): Promise<void> {
|
|
64
|
+
for (const agent of this.agentMap.values()) {
|
|
65
|
+
await agent.close();
|
|
66
|
+
}
|
|
67
|
+
if (this.mcp) {
|
|
68
|
+
try { await this.mcp.closeAll(); } catch (e) { log.warn('mcp_close_failed', { error: String(e) }); }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Bootstrap the full system: config, bus, LLM, tools, skills, plugins, agents.
|
|
75
|
+
*/
|
|
76
|
+
export function createSystemContext(): SystemContext {
|
|
77
|
+
const config = loadConfig();
|
|
78
|
+
|
|
79
|
+
let workspacePath = '';
|
|
80
|
+
try {
|
|
81
|
+
const { resolveWorkspacePath, initWorkspace } = require('./workspace');
|
|
82
|
+
const wsRoot = resolveWorkspacePath((config as any).workspace?.path || 'auto');
|
|
83
|
+
initWorkspace(wsRoot);
|
|
84
|
+
workspacePath = wsRoot;
|
|
85
|
+
log.info('workspace', { path: workspacePath });
|
|
86
|
+
} catch { /* ignore */ }
|
|
87
|
+
|
|
88
|
+
const bus = new MessageBus();
|
|
89
|
+
|
|
90
|
+
// Shared registries
|
|
91
|
+
const baseToolRegistry = new ToolRegistry();
|
|
92
|
+
const baseSkillRegistry = new SkillRegistry();
|
|
93
|
+
|
|
94
|
+
// Register builtin tools
|
|
95
|
+
try {
|
|
96
|
+
const { registerBuiltinTools } = require('../tools/builtin');
|
|
97
|
+
registerBuiltinTools(baseToolRegistry);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
log.warn('builtin_tools_not_available', { error: String(e) });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Register all skills
|
|
103
|
+
try {
|
|
104
|
+
const { registerAllSkills } = require('../skills/loader');
|
|
105
|
+
registerAllSkills(baseSkillRegistry);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
log.warn('skills_not_available', { error: String(e) });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Load plugins
|
|
111
|
+
try {
|
|
112
|
+
const { PluginLoader } = require('../plugins/loader');
|
|
113
|
+
const pluginLoader = new PluginLoader(baseToolRegistry);
|
|
114
|
+
const pluginConfig = (config as any).plugins;
|
|
115
|
+
const pluginDirs = pluginConfig?.enabled ? (pluginConfig.directories || []) : [];
|
|
116
|
+
pluginLoader.loadFromDirectories(pluginDirs);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
log.warn('plugins_not_available', { error: String(e) });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Configure MCP manager
|
|
122
|
+
let mcpManager: any = null;
|
|
123
|
+
try {
|
|
124
|
+
const { MCPManager, loadPersistedServers } = require('./mcp');
|
|
125
|
+
mcpManager = new MCPManager(baseToolRegistry);
|
|
126
|
+
const persisted = loadPersistedServers();
|
|
127
|
+
const mcpServers = (config as any).mcp?.servers || [];
|
|
128
|
+
const allServers = [...mcpServers, ...persisted];
|
|
129
|
+
if (allServers.length > 0) {
|
|
130
|
+
mcpManager.configure(allServers);
|
|
131
|
+
}
|
|
132
|
+
} catch (e) {
|
|
133
|
+
log.warn('mcp_not_available', { error: String(e) });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Shared LLM client
|
|
137
|
+
const llm = new LLMClient(config as any, baseToolRegistry);
|
|
138
|
+
|
|
139
|
+
// Per-agent registries
|
|
140
|
+
const agents = new Map<string, BaseAgent>();
|
|
141
|
+
|
|
142
|
+
// Try to dynamically load agent classes
|
|
143
|
+
const agentNames = ['fog', 'rain', 'frost', 'snow', 'dew', 'fair'];
|
|
144
|
+
|
|
145
|
+
for (const name of agentNames) {
|
|
146
|
+
const agentRegistry = new ToolRegistry();
|
|
147
|
+
agentRegistry.merge(baseToolRegistry);
|
|
148
|
+
const agentSkills = new SkillRegistry();
|
|
149
|
+
agentSkills.merge(baseSkillRegistry);
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
// Try dynamic import
|
|
153
|
+
const clsName = name.charAt(0).toUpperCase() + name.slice(1) + 'Agent';
|
|
154
|
+
// Use require for now since dynamic imports are async
|
|
155
|
+
let AgentClass: any = null;
|
|
156
|
+
try {
|
|
157
|
+
const mod = require(`../agents/${name}`);
|
|
158
|
+
AgentClass = mod[clsName];
|
|
159
|
+
} catch {
|
|
160
|
+
log.warn('agent_class_missing', { agent: name });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!AgentClass) {
|
|
165
|
+
log.warn('agent_class_not_found', { agent: name, class: clsName });
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const agent = new AgentClass(
|
|
170
|
+
config,
|
|
171
|
+
llm,
|
|
172
|
+
bus,
|
|
173
|
+
agentRegistry,
|
|
174
|
+
agentSkills
|
|
175
|
+
) as BaseAgent;
|
|
176
|
+
|
|
177
|
+
// Register delegate_to tool
|
|
178
|
+
try {
|
|
179
|
+
const { createDelegateTool } = require('../tools/delegate');
|
|
180
|
+
agentRegistry.register(createDelegateTool(agents, agent));
|
|
181
|
+
} catch (e) {
|
|
182
|
+
log.warn('delegate_tool_not_available', { agent: name, error: String(e) });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
agents.set(name, agent);
|
|
186
|
+
} catch (e) {
|
|
187
|
+
log.warn('agent_creation_failed', { agent: name, error: String(e) });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Bind agents to MCP
|
|
192
|
+
if (mcpManager) {
|
|
193
|
+
try {
|
|
194
|
+
mcpManager.bindAgents(agents);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
log.warn('mcp_bind_failed', { error: String(e) });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return new SystemContext({
|
|
201
|
+
config,
|
|
202
|
+
bus,
|
|
203
|
+
llm,
|
|
204
|
+
agentMap: agents,
|
|
205
|
+
toolRegistry: baseToolRegistry,
|
|
206
|
+
workspacePath,
|
|
207
|
+
mcp: mcpManager,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ── Task orchestration ──
|
|
212
|
+
|
|
213
|
+
export class TaskExecutionResult {
|
|
214
|
+
id: string;
|
|
215
|
+
agent: string;
|
|
216
|
+
description: string;
|
|
217
|
+
success: boolean;
|
|
218
|
+
content: string;
|
|
219
|
+
|
|
220
|
+
constructor(opts: {
|
|
221
|
+
id: string;
|
|
222
|
+
agent: string;
|
|
223
|
+
description: string;
|
|
224
|
+
success: boolean;
|
|
225
|
+
content: string;
|
|
226
|
+
}) {
|
|
227
|
+
this.id = opts.id;
|
|
228
|
+
this.agent = opts.agent;
|
|
229
|
+
this.description = opts.description;
|
|
230
|
+
this.success = opts.success;
|
|
231
|
+
this.content = opts.content;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Placeholder phrases that mean the LLM gave up
|
|
236
|
+
const PLACEHOLDER_PATTERNS = [
|
|
237
|
+
'done', 'ok', 'completed', 'task completed', 'task done', 'task finished',
|
|
238
|
+
'finished', '已完成', '完成了', '好的', '好了', 'ok!',
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
const STATUS_REPORT_KEYWORDS = [
|
|
242
|
+
'已完成', '完成了', '已成功', '已经完成', '工作已', '任务已',
|
|
243
|
+
'task complete', 'task is complete', 'i have completed', "i've completed",
|
|
244
|
+
'successfully completed', 'finished the', 'i finished',
|
|
245
|
+
'已经写好', '已经写完', '已经做好', '写完了', '做完了',
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
const DELIVERABLE_MARKERS = [
|
|
249
|
+
'```', 'http://', 'https://', '|', '## ', '###', '- [ ]', '1.', '/', '\\',
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
function isThinContent(content: string): boolean {
|
|
253
|
+
if (!content) return true;
|
|
254
|
+
const stripped = content.trim();
|
|
255
|
+
if (!stripped) return true;
|
|
256
|
+
const lowered = stripped.toLowerCase();
|
|
257
|
+
if (lowered.startsWith('[truncated]') || lowered.startsWith('[error:')) return true;
|
|
258
|
+
const bare = lowered.replace(/[.!?。!?\s]+$/, '').trim();
|
|
259
|
+
if (PLACEHOLDER_PATTERNS.includes(bare)) return true;
|
|
260
|
+
return (
|
|
261
|
+
stripped.length <= 200 &&
|
|
262
|
+
STATUS_REPORT_KEYWORDS.some(k => lowered.includes(k)) &&
|
|
263
|
+
!DELIVERABLE_MARKERS.some(m => stripped.includes(m))
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const RESULT_FAILURE_MARKERS = [
|
|
268
|
+
'[truncated]', '[stuck]', '[Error', 'Error:',
|
|
269
|
+
'未能完成', '无法完成', '[cycle detected]', '[CircuitBreakerOpen]',
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
function looksObviouslyComplete(results: TaskExecutionResult[]): boolean {
|
|
273
|
+
if (!results.length) return false;
|
|
274
|
+
return results.every(r => {
|
|
275
|
+
if (!r.success) return false;
|
|
276
|
+
const body = (r.content || '').trim();
|
|
277
|
+
if (body.length < 400) return false;
|
|
278
|
+
return !RESULT_FAILURE_MARKERS.some(m => body.includes(m));
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function executeWithRetry(
|
|
283
|
+
agent: BaseAgent,
|
|
284
|
+
aTask: any,
|
|
285
|
+
maxAttempts: number,
|
|
286
|
+
onStatus?: ((status: string) => void) | null
|
|
287
|
+
): Promise<any> {
|
|
288
|
+
let lastResult: any = null;
|
|
289
|
+
const originalDescription = aTask.description;
|
|
290
|
+
|
|
291
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
292
|
+
try {
|
|
293
|
+
const result = await agent.executeTask(aTask, onStatus);
|
|
294
|
+
const content = (result.content || '').trim();
|
|
295
|
+
const truncated = (result as any).truncated === true;
|
|
296
|
+
const ok = result.success && !isThinContent(content);
|
|
297
|
+
|
|
298
|
+
if (ok && !truncated) return result;
|
|
299
|
+
lastResult = result;
|
|
300
|
+
|
|
301
|
+
if (attempt < maxAttempts) {
|
|
302
|
+
const reason = truncated
|
|
303
|
+
? 'previous attempt was truncated'
|
|
304
|
+
: 'previous attempt was empty or a placeholder ack';
|
|
305
|
+
aTask.description = `${originalDescription}\n\n[retry ${attempt + 1}/${maxAttempts}] ${reason}. You MUST produce the actual deliverable.`;
|
|
306
|
+
}
|
|
307
|
+
} catch (e) {
|
|
308
|
+
lastResult = { success: false, content: `Attempt ${attempt} threw: ${e}` };
|
|
309
|
+
}
|
|
310
|
+
if (attempt < maxAttempts) {
|
|
311
|
+
await new Promise(r => setTimeout(r, Math.min(500 * Math.pow(2, attempt - 1), 2000)));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
aTask.description = originalDescription;
|
|
316
|
+
return lastResult || { success: false, content: `All ${maxAttempts} attempts failed` };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function executePending(
|
|
320
|
+
pending: any[],
|
|
321
|
+
agentMap: Map<string, BaseAgent>,
|
|
322
|
+
results: TaskExecutionResult[],
|
|
323
|
+
resultsById: Map<string, TaskExecutionResult>,
|
|
324
|
+
fullContentsById: Map<string, string>,
|
|
325
|
+
completed: Set<string>,
|
|
326
|
+
options: {
|
|
327
|
+
onTaskStart?: ((task: any) => Promise<void>) | null;
|
|
328
|
+
onTaskDone?: ((task: any, result: TaskExecutionResult) => Promise<void>) | null;
|
|
329
|
+
onToolStatus?: ((status: string) => void) | null;
|
|
330
|
+
resultTruncate?: number | null;
|
|
331
|
+
maxTaskRetries: number;
|
|
332
|
+
}
|
|
333
|
+
): Promise<void> {
|
|
334
|
+
while (pending.length > 0) {
|
|
335
|
+
const ready = pending.filter(t => t.allDeps.every((dep: string) => completed.has(dep)));
|
|
336
|
+
if (ready.length === 0) {
|
|
337
|
+
for (const t of pending) {
|
|
338
|
+
const missing = t.allDeps.filter((d: string) => !completed.has(d));
|
|
339
|
+
t.transitionTo(TaskState.FAILED);
|
|
340
|
+
const r = new TaskExecutionResult({
|
|
341
|
+
id: t.id, agent: t.assignedTo || '',
|
|
342
|
+
description: t.description, success: false,
|
|
343
|
+
content: `[dependency missing] task ${t.id} requires ${missing.join(', ')} which never completed`,
|
|
344
|
+
});
|
|
345
|
+
results.push(r);
|
|
346
|
+
resultsById.set(r.id, r);
|
|
347
|
+
completed.add(r.id);
|
|
348
|
+
if (options.onTaskDone) await options.onTaskDone(t, r);
|
|
349
|
+
}
|
|
350
|
+
pending.length = 0;
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
for (const t of ready) t.transitionTo(TaskState.RUNNING);
|
|
355
|
+
|
|
356
|
+
const batchResults = await Promise.all(
|
|
357
|
+
ready.map(async (t: any) => {
|
|
358
|
+
const agent = agentMap.get(t.assignedTo);
|
|
359
|
+
if (!agent) {
|
|
360
|
+
return new TaskExecutionResult({
|
|
361
|
+
id: t.id, agent: t.assignedTo || '',
|
|
362
|
+
description: t.description, success: false,
|
|
363
|
+
content: `Agent '${t.assignedTo}' not found`,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
if (options.onTaskStart) await options.onTaskStart(t);
|
|
367
|
+
|
|
368
|
+
let description = t.description;
|
|
369
|
+
const upstreamSections: string[] = [];
|
|
370
|
+
const thinUpstreamIds: string[] = [];
|
|
371
|
+
|
|
372
|
+
for (const depId of t.allDeps) {
|
|
373
|
+
if (resultsById.has(depId)) {
|
|
374
|
+
const parent = resultsById.get(depId)!;
|
|
375
|
+
const fullContent = fullContentsById.get(depId) || parent.content || '';
|
|
376
|
+
if (isThinContent(fullContent)) {
|
|
377
|
+
thinUpstreamIds.push(parent.id);
|
|
378
|
+
upstreamSections.push(
|
|
379
|
+
`## 上游产出缺失 (task ${parent.id} · ${parent.agent})\n` +
|
|
380
|
+
`⚠ 上游任务声称完成但未产出实际内容。\n` +
|
|
381
|
+
`原始回复:\n${fullContent}`
|
|
382
|
+
);
|
|
383
|
+
} else {
|
|
384
|
+
upstreamSections.push(
|
|
385
|
+
`## 上游产出 (task ${parent.id} · ${parent.agent})\n${fullContent}`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (upstreamSections.length > 0) {
|
|
391
|
+
description = `${t.description}\n\n${upstreamSections.join('\n\n')}`;
|
|
392
|
+
}
|
|
393
|
+
if (thinUpstreamIds.length > 0) {
|
|
394
|
+
log.warn('thin_upstream', { task: t.id, thin_upstream: thinUpstreamIds });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const aTask = new AgentTask({
|
|
398
|
+
id: t.id,
|
|
399
|
+
description,
|
|
400
|
+
assignedTo: t.assignedTo,
|
|
401
|
+
parentId: t.parentId,
|
|
402
|
+
metadata: t.metadata,
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const result = await executeWithRetry(agent, aTask, options.maxTaskRetries, options.onToolStatus);
|
|
406
|
+
|
|
407
|
+
if (result.success) t.transitionTo(TaskState.COMPLETED);
|
|
408
|
+
else t.transitionTo(TaskState.FAILED);
|
|
409
|
+
|
|
410
|
+
const full = result.content || '';
|
|
411
|
+
fullContentsById.set(t.id, full);
|
|
412
|
+
const tr = options.resultTruncate != null && full.length > options.resultTruncate
|
|
413
|
+
? full.slice(0, options.resultTruncate) : full;
|
|
414
|
+
|
|
415
|
+
const r = new TaskExecutionResult({
|
|
416
|
+
id: t.id, agent: t.assignedTo || '',
|
|
417
|
+
description: t.description, success: result.success,
|
|
418
|
+
content: tr,
|
|
419
|
+
});
|
|
420
|
+
if (options.onTaskDone) await options.onTaskDone(t, r);
|
|
421
|
+
return r;
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
for (const r of batchResults) {
|
|
426
|
+
results.push(r);
|
|
427
|
+
resultsById.set(r.id, r);
|
|
428
|
+
completed.add(r.id);
|
|
429
|
+
}
|
|
430
|
+
for (const t of ready) {
|
|
431
|
+
const idx = pending.indexOf(t);
|
|
432
|
+
if (idx >= 0) pending.splice(idx, 1);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
async function judgeGoalAchievement(
|
|
438
|
+
snow: BaseAgent,
|
|
439
|
+
goal: string,
|
|
440
|
+
results: TaskExecutionResult[]
|
|
441
|
+
): Promise<[boolean, string]> {
|
|
442
|
+
const bullets = results.map(r => {
|
|
443
|
+
const status = r.success ? '成功' : '失败';
|
|
444
|
+
const excerpt = (r.content || '').slice(0, 800);
|
|
445
|
+
return `- [task ${r.id} · agent=${r.agent} · status=${status}] len=${(r.content || '').length}chars\n ${excerpt}`;
|
|
446
|
+
}).join('\n');
|
|
447
|
+
|
|
448
|
+
const prompt = `你是一名极严格的项目验收员。验证 sub-task 真的产出了可验证的交付物。
|
|
449
|
+
|
|
450
|
+
## 验收规则(严格执行)
|
|
451
|
+
|
|
452
|
+
1. **「调研/搜集/查询」类**:必须列出具体对象名称和数据/特性/链接。
|
|
453
|
+
2. **「撰写/生成/写作」类**:必须包含实际的文本/代码/markdown。
|
|
454
|
+
3. **「审查/审计/对比」类**:必须列出具体问题点。
|
|
455
|
+
4. **核心交付物缺失绝不容忍**。
|
|
456
|
+
|
|
457
|
+
## 用户原目标
|
|
458
|
+
${goal}
|
|
459
|
+
|
|
460
|
+
## 子任务执行结果
|
|
461
|
+
${bullets}
|
|
462
|
+
|
|
463
|
+
严格按下列 JSON 格式输出(除 JSON 之外不要任何其他字符):
|
|
464
|
+
{"achieved": true/false, "missing": "若未达成,逐项列出缺什么"}`;
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
const raw = await snow.chatOneshot(prompt);
|
|
468
|
+
let text = raw.trim();
|
|
469
|
+
if (text.startsWith('```')) {
|
|
470
|
+
text = text.replace(/```/g, '').replace(/^json/i, '').trim();
|
|
471
|
+
}
|
|
472
|
+
const start = text.indexOf('{');
|
|
473
|
+
const end = text.lastIndexOf('}');
|
|
474
|
+
if (start < 0 || end <= start) return [true, ''];
|
|
475
|
+
const parsed = JSON.parse(text.slice(start, end + 1));
|
|
476
|
+
return [!!parsed.achieved, (parsed.missing || '').trim()];
|
|
477
|
+
} catch {
|
|
478
|
+
return [true, ''];
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export async function orchestrateTask(
|
|
483
|
+
goal: string,
|
|
484
|
+
agentMap: Map<string, BaseAgent>,
|
|
485
|
+
snow: BaseAgent | null = null,
|
|
486
|
+
options?: {
|
|
487
|
+
onTaskStart?: ((task: any) => Promise<void>) | null;
|
|
488
|
+
onTaskDone?: ((task: any, result: TaskExecutionResult) => Promise<void>) | null;
|
|
489
|
+
onPlanned?: ((tasks: any[]) => Promise<boolean | null>) | null;
|
|
490
|
+
onToolStatus?: ((status: string) => void) | null;
|
|
491
|
+
resultTruncate?: number | null;
|
|
492
|
+
summaryPromptTemplate?: string;
|
|
493
|
+
maxTaskRetries?: number;
|
|
494
|
+
maxReplanRounds?: number;
|
|
495
|
+
maxTotalTasks?: number;
|
|
496
|
+
resume?: boolean;
|
|
497
|
+
}
|
|
498
|
+
): Promise<[any[], TaskExecutionResult[], string]> {
|
|
499
|
+
const snowAgent = snow || agentMap.get('snow') || null;
|
|
500
|
+
if (!snowAgent) {
|
|
501
|
+
return [[], [], 'Snow agent not available'];
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const maxTaskRetries = options?.maxTaskRetries ?? 3;
|
|
505
|
+
const maxReplanRounds = options?.maxReplanRounds ?? 1;
|
|
506
|
+
const maxTotalTasks = options?.maxTotalTasks ?? 6;
|
|
507
|
+
const resultTruncate = options?.resultTruncate ?? 500;
|
|
508
|
+
|
|
509
|
+
// Try pipeline match first
|
|
510
|
+
let tasks: any[];
|
|
511
|
+
try {
|
|
512
|
+
const { matchPipeline, buildTasksFromPipeline } = require('./pipelines');
|
|
513
|
+
const matched = matchPipeline(goal);
|
|
514
|
+
if (matched) {
|
|
515
|
+
tasks = buildTasksFromPipeline(matched, goal);
|
|
516
|
+
} else {
|
|
517
|
+
tasks = await (snowAgent as any).orchestrate(goal);
|
|
518
|
+
}
|
|
519
|
+
} catch {
|
|
520
|
+
tasks = await (snowAgent as any).orchestrate(goal);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (!tasks || tasks.length === 0) {
|
|
524
|
+
return [[], [], 'No tasks were planned'];
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Notify caller of the plan
|
|
528
|
+
if (options?.onPlanned) {
|
|
529
|
+
const proceed = await options.onPlanned(tasks);
|
|
530
|
+
if (proceed === false) {
|
|
531
|
+
return [tasks, [], '[CANCELLED] plan rejected before execution'];
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const completed = new Set<string>();
|
|
536
|
+
const results: TaskExecutionResult[] = [];
|
|
537
|
+
const resultsById = new Map<string, TaskExecutionResult>();
|
|
538
|
+
const fullContentsById = new Map<string, string>();
|
|
539
|
+
let pending = tasks.filter((t: any) => t.assignedTo && t.assignedTo !== 'snow');
|
|
540
|
+
let replanRound = 0;
|
|
541
|
+
|
|
542
|
+
// Cycle detection
|
|
543
|
+
function hasCycle(t: any, path: Set<string>): boolean {
|
|
544
|
+
if (path.has(t.id)) return true;
|
|
545
|
+
path.add(t.id);
|
|
546
|
+
for (const depId of t.allDeps || []) {
|
|
547
|
+
const dep = tasks.find((x: any) => x.id === depId);
|
|
548
|
+
if (dep && hasCycle(dep, new Set(path))) return true;
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
pending = pending.filter((t: any) => {
|
|
554
|
+
if (hasCycle(t, new Set())) {
|
|
555
|
+
results.push(new TaskExecutionResult({
|
|
556
|
+
id: t.id, agent: t.assignedTo || '',
|
|
557
|
+
description: t.description, success: false,
|
|
558
|
+
content: `[cycle detected] task ${t.id} has circular dependency`,
|
|
559
|
+
}));
|
|
560
|
+
completed.add(t.id);
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
return true;
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
while (true) {
|
|
567
|
+
await executePending(pending, agentMap, results, resultsById, fullContentsById, completed, {
|
|
568
|
+
onTaskStart: options?.onTaskStart || null,
|
|
569
|
+
onTaskDone: options?.onTaskDone || null,
|
|
570
|
+
onToolStatus: options?.onToolStatus || null,
|
|
571
|
+
resultTruncate,
|
|
572
|
+
maxTaskRetries,
|
|
573
|
+
});
|
|
574
|
+
pending = [];
|
|
575
|
+
|
|
576
|
+
if (!results.length || replanRound >= maxReplanRounds) break;
|
|
577
|
+
if (results.length === 1 && results[0].success) break;
|
|
578
|
+
if (looksObviouslyComplete(results)) break;
|
|
579
|
+
|
|
580
|
+
const [achieved, missing] = await judgeGoalAchievement(snowAgent, goal, results);
|
|
581
|
+
if (achieved) break;
|
|
582
|
+
|
|
583
|
+
replanRound++;
|
|
584
|
+
try {
|
|
585
|
+
const extraTasks = await (snowAgent as any).replanForMissing(goal, results, missing,
|
|
586
|
+
new Set(tasks.map((t: any) => t.id)));
|
|
587
|
+
if (!extraTasks || extraTasks.length === 0) break;
|
|
588
|
+
if (tasks.length + extraTasks.length > maxTotalTasks) break;
|
|
589
|
+
tasks.push(...extraTasks);
|
|
590
|
+
if (options?.onPlanned) {
|
|
591
|
+
const proceed = await options.onPlanned(tasks);
|
|
592
|
+
if (proceed === false) break;
|
|
593
|
+
}
|
|
594
|
+
pending = extraTasks.filter((t: any) => t.assignedTo && t.assignedTo !== 'snow');
|
|
595
|
+
} catch {
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Generate summary
|
|
601
|
+
let summary: string;
|
|
602
|
+
if (!results.length) {
|
|
603
|
+
summary = '没有需要执行的任务。';
|
|
604
|
+
} else if (results.length === 1) {
|
|
605
|
+
summary = results[0].content;
|
|
606
|
+
} else {
|
|
607
|
+
const tpl = options?.summaryPromptTemplate || '请汇总以下所有子任务的执行结果:\n\n';
|
|
608
|
+
let summaryPrompt = tpl;
|
|
609
|
+
for (const r of results) {
|
|
610
|
+
const status = r.success ? '成功' : '失败';
|
|
611
|
+
summaryPrompt += `### 任务 ${r.id} (${r.agent}) - ${status}\n${(r.content || '').slice(0, 300)}\n\n`;
|
|
612
|
+
}
|
|
613
|
+
summary = await snowAgent.chatOneshot(summaryPrompt);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Check if we hit the replan budget without full completion
|
|
617
|
+
if (replanRound >= maxReplanRounds && results.length > 1) {
|
|
618
|
+
try {
|
|
619
|
+
const [achieved, missing] = await judgeGoalAchievement(snowAgent, goal, results);
|
|
620
|
+
if (!achieved && missing) {
|
|
621
|
+
summary = `[INCOMPLETE] 经过 ${maxReplanRounds + 1} 轮规划仍未完全达成目标。\n剩余缺口:${missing}\n\n${summary}`;
|
|
622
|
+
}
|
|
623
|
+
} catch { /* ignore */ }
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return [tasks, results, summary];
|
|
627
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent icon system — dynamic status indicators.
|
|
3
|
+
*
|
|
4
|
+
* Each agent is identified by its display name with color styling.
|
|
5
|
+
* During processing, agent spinners provide dynamic status.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
|
|
10
|
+
const ICONS_DIR = path.resolve(__dirname, '..', 'assets', 'icons');
|
|
11
|
+
|
|
12
|
+
export const AGENT_COLORS: Record<string, string> = {
|
|
13
|
+
fog: 'bright_white',
|
|
14
|
+
rain: 'blue',
|
|
15
|
+
frost: 'cyan',
|
|
16
|
+
snow: 'bright_white',
|
|
17
|
+
dew: 'green',
|
|
18
|
+
fair: '#FFD700',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const AGENT_EMOJI: Record<string, string> = {
|
|
22
|
+
fog: '≋',
|
|
23
|
+
rain: '⸽',
|
|
24
|
+
frost: '✱',
|
|
25
|
+
snow: '❉',
|
|
26
|
+
dew: '∘',
|
|
27
|
+
fair: '☼',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Return the filesystem path to an agent's SVG icon file.
|
|
32
|
+
*/
|
|
33
|
+
export function svgPath(name: string): string {
|
|
34
|
+
return path.join(ICONS_DIR, `${name}.svg`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Return the plain-text icon for an agent.
|
|
39
|
+
*
|
|
40
|
+
* Used in dashboards, prompts, logs, and any UI where SVG can't render.
|
|
41
|
+
* The glyphs are deliberately chosen from Unicode blocks that render
|
|
42
|
+
* as monochrome text on virtually every terminal.
|
|
43
|
+
*
|
|
44
|
+
* fog ≋ three wavy lines — drifting mist
|
|
45
|
+
* rain ⸽ six vertical dots — falling rain streaks
|
|
46
|
+
* frost ✱ pointed asterisk — frost crystal
|
|
47
|
+
* snow ❉ balloon-spoked star — snowflake
|
|
48
|
+
* dew ∘ ring — dewdrop
|
|
49
|
+
* fair ☼ sun with rays — clear sky
|
|
50
|
+
*/
|
|
51
|
+
export function iconText(name: string): string {
|
|
52
|
+
return AGENT_EMOJI[name] ?? name;
|
|
53
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skyloom Core Module Exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export * from './constants';
|
|
6
|
+
export * from './schemas';
|
|
7
|
+
export * from './logger';
|
|
8
|
+
export * from './config';
|
|
9
|
+
export * from './tool';
|
|
10
|
+
export * from './circuit_breaker';
|
|
11
|
+
export * from './bus';
|
|
12
|
+
export * from './cache';
|
|
13
|
+
export * from './memory';
|
|
14
|
+
export * from './middleware';
|
|
15
|
+
export * from './llm';
|
|
16
|
+
export * from './mcp';
|
|
17
|
+
export { matchPipeline, buildTasksFromPipeline, listPipelines, getPipelineByName, matchAllPipelines, validateDAG, topologicalSort, type Pipeline, type PipelineStep } from './pipelines';
|
|
18
|
+
export * from './semantic';
|
|
19
|
+
export * from './icons';
|
|
20
|
+
export * from './checkpoint';
|
|
21
|
+
export * from './workspace';
|
|
22
|
+
export * from './profile';
|
|
23
|
+
export * from './tool_router';
|
|
24
|
+
export * from './agent_helpers';
|
|
25
|
+
export * from './skill';
|
|
26
|
+
export * from './router';
|
|
27
|
+
export * from './agent';
|
|
28
|
+
export * from './factory';
|
|
29
|
+
|
|
30
|
+
// Version
|
|
31
|
+
export const VERSION = '1.4.0';
|