opc-agent 2.0.0 → 2.0.2
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 +545 -365
- package/dist/channels/email.d.ts +32 -26
- package/dist/channels/email.js +239 -62
- package/dist/channels/feishu.d.ts +21 -6
- package/dist/channels/feishu.js +225 -126
- package/dist/channels/websocket.d.ts +46 -3
- package/dist/channels/websocket.js +306 -37
- package/dist/channels/wechat.d.ts +33 -13
- package/dist/channels/wechat.js +229 -42
- package/dist/cli.js +712 -11
- package/dist/core/a2a.d.ts +17 -0
- package/dist/core/a2a.js +43 -1
- package/dist/core/agent.d.ts +16 -0
- package/dist/core/agent.js +108 -0
- package/dist/core/runtime.d.ts +6 -0
- package/dist/core/runtime.js +161 -2
- package/dist/core/sandbox.d.ts +26 -0
- package/dist/core/sandbox.js +117 -0
- package/dist/core/workflow-graph.d.ts +93 -0
- package/dist/core/workflow-graph.js +247 -0
- package/dist/doctor.d.ts +15 -0
- package/dist/doctor.js +183 -0
- package/dist/eval/index.d.ts +65 -0
- package/dist/eval/index.js +191 -0
- package/dist/index.d.ts +32 -6
- package/dist/index.js +63 -4
- package/dist/plugins/content-filter.d.ts +7 -0
- package/dist/plugins/content-filter.js +25 -0
- package/dist/plugins/index.d.ts +42 -0
- package/dist/plugins/index.js +108 -2
- package/dist/plugins/logger.d.ts +6 -0
- package/dist/plugins/logger.js +20 -0
- package/dist/plugins/rate-limiter.d.ts +7 -0
- package/dist/plugins/rate-limiter.js +35 -0
- package/dist/protocols/a2a/client.d.ts +25 -0
- package/dist/protocols/a2a/client.js +115 -0
- package/dist/protocols/a2a/index.d.ts +6 -0
- package/dist/protocols/a2a/index.js +12 -0
- package/dist/protocols/a2a/server.d.ts +41 -0
- package/dist/protocols/a2a/server.js +295 -0
- package/dist/protocols/a2a/types.d.ts +91 -0
- package/dist/protocols/a2a/types.js +15 -0
- package/dist/protocols/a2a/utils.d.ts +6 -0
- package/dist/protocols/a2a/utils.js +47 -0
- package/dist/protocols/agui/client.d.ts +10 -0
- package/dist/protocols/agui/client.js +75 -0
- package/dist/protocols/agui/index.d.ts +4 -0
- package/dist/protocols/agui/index.js +25 -0
- package/dist/protocols/agui/server.d.ts +37 -0
- package/dist/protocols/agui/server.js +191 -0
- package/dist/protocols/agui/types.d.ts +107 -0
- package/dist/protocols/agui/types.js +17 -0
- package/dist/protocols/index.d.ts +2 -0
- package/dist/protocols/index.js +19 -0
- package/dist/protocols/mcp/agent-tools.d.ts +11 -0
- package/dist/protocols/mcp/agent-tools.js +129 -0
- package/dist/protocols/mcp/index.d.ts +5 -0
- package/dist/protocols/mcp/index.js +11 -0
- package/dist/protocols/mcp/server.d.ts +31 -0
- package/dist/protocols/mcp/server.js +248 -0
- package/dist/protocols/mcp/types.d.ts +92 -0
- package/dist/protocols/mcp/types.js +17 -0
- package/dist/publish/index.d.ts +45 -0
- package/dist/publish/index.js +350 -0
- package/dist/schema/oad.d.ts +682 -65
- package/dist/schema/oad.js +36 -3
- package/dist/security/approval.d.ts +36 -0
- package/dist/security/approval.js +113 -0
- package/dist/security/index.d.ts +4 -0
- package/dist/security/index.js +8 -0
- package/dist/security/keys.d.ts +16 -0
- package/dist/security/keys.js +117 -0
- package/dist/studio/server.d.ts +63 -0
- package/dist/studio/server.js +625 -0
- package/dist/studio-ui/index.html +662 -0
- package/dist/telemetry/index.d.ts +93 -0
- package/dist/telemetry/index.js +285 -0
- package/package.json +5 -3
- package/scripts/install.ps1 +31 -0
- package/scripts/install.sh +40 -0
- package/src/channels/email.ts +351 -177
- package/src/channels/feishu.ts +349 -236
- package/src/channels/websocket.ts +399 -87
- package/src/channels/wechat.ts +329 -149
- package/src/cli.ts +783 -12
- package/src/core/a2a.ts +60 -0
- package/src/core/agent.ts +125 -0
- package/src/core/runtime.ts +127 -0
- package/src/core/sandbox.ts +143 -0
- package/src/core/workflow-graph.ts +365 -0
- package/src/doctor.ts +156 -0
- package/src/eval/index.ts +211 -0
- package/src/eval/suites/basic.json +16 -0
- package/src/eval/suites/memory.json +12 -0
- package/src/eval/suites/safety.json +14 -0
- package/src/index.ts +58 -6
- package/src/plugins/content-filter.ts +23 -0
- package/src/plugins/index.ts +133 -2
- package/src/plugins/logger.ts +18 -0
- package/src/plugins/rate-limiter.ts +38 -0
- package/src/protocols/a2a/client.ts +132 -0
- package/src/protocols/a2a/index.ts +8 -0
- package/src/protocols/a2a/server.ts +333 -0
- package/src/protocols/a2a/types.ts +88 -0
- package/src/protocols/a2a/utils.ts +50 -0
- package/src/protocols/agui/client.ts +83 -0
- package/src/protocols/agui/index.ts +4 -0
- package/src/protocols/agui/server.ts +218 -0
- package/src/protocols/agui/types.ts +153 -0
- package/src/protocols/index.ts +2 -0
- package/src/protocols/mcp/agent-tools.ts +134 -0
- package/src/protocols/mcp/index.ts +8 -0
- package/src/protocols/mcp/server.ts +262 -0
- package/src/protocols/mcp/types.ts +69 -0
- package/src/publish/index.ts +376 -0
- package/src/schema/oad.ts +39 -2
- package/src/security/approval.ts +131 -0
- package/src/security/index.ts +3 -0
- package/src/security/keys.ts +87 -0
- package/src/studio/server.ts +629 -0
- package/src/studio-ui/index.html +662 -0
- package/src/telemetry/index.ts +324 -0
- package/src/types/agent-workstation.d.ts +2 -0
- package/tests/a2a-protocol.test.ts +285 -0
- package/tests/agui-protocol.test.ts +246 -0
- package/tests/channels/discord.test.ts +79 -0
- package/tests/channels/email.test.ts +148 -0
- package/tests/channels/feishu.test.ts +123 -0
- package/tests/channels/telegram.test.ts +129 -0
- package/tests/channels/websocket.test.ts +53 -0
- package/tests/channels/wechat.test.ts +170 -0
- package/tests/chat-cli.test.ts +160 -0
- package/tests/daemon.test.ts +135 -0
- package/tests/deepbrain-wire.test.ts +234 -0
- package/tests/doctor.test.ts +38 -0
- package/tests/eval.test.ts +173 -0
- package/tests/init-role.test.ts +124 -0
- package/tests/mcp-client.test.ts +92 -0
- package/tests/mcp-server.test.ts +178 -0
- package/tests/plugin-a2a-enhanced.test.ts +230 -0
- package/tests/publish.test.ts +231 -0
- package/tests/scheduler.test.ts +200 -0
- package/tests/security-enhanced.test.ts +233 -0
- package/tests/skill-learner.test.ts +161 -0
- package/tests/studio.test.ts +229 -0
- package/tests/subagent.test.ts +63 -0
- package/tests/telemetry.test.ts +186 -0
- package/tests/tools/builtin-extended.test.ts +138 -0
- package/tests/workflow-graph.test.ts +279 -0
- package/tutorial/customer-service-agent/README.md +612 -0
- package/tutorial/customer-service-agent/SOUL.md +26 -0
- package/tutorial/customer-service-agent/agent.yaml +63 -0
- package/tutorial/customer-service-agent/package.json +19 -0
- package/tutorial/customer-service-agent/src/index.ts +69 -0
- package/tutorial/customer-service-agent/src/skills/faq.ts +27 -0
- package/tutorial/customer-service-agent/src/skills/ticket.ts +22 -0
- package/tutorial/customer-service-agent/tsconfig.json +14 -0
package/dist/core/a2a.d.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
import { Room } from './room';
|
|
3
3
|
import type { IAgent } from './types';
|
|
4
|
+
export interface AgentCard {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
capabilities: string[];
|
|
8
|
+
endpoint?: string;
|
|
9
|
+
handler?: (message: string) => Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare class AgentCardRegistry {
|
|
12
|
+
private cards;
|
|
13
|
+
private logger;
|
|
14
|
+
register(card: AgentCard): void;
|
|
15
|
+
unregister(name: string): void;
|
|
16
|
+
get(name: string): AgentCard | undefined;
|
|
17
|
+
find(query: string): AgentCard[];
|
|
18
|
+
send(agentName: string, message: string): Promise<string>;
|
|
19
|
+
list(): AgentCard[];
|
|
20
|
+
}
|
|
4
21
|
export interface AgentCapability {
|
|
5
22
|
name: string;
|
|
6
23
|
description: string;
|
package/dist/core/a2a.js
CHANGED
|
@@ -1,9 +1,51 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgentRegistry = void 0;
|
|
3
|
+
exports.AgentRegistry = exports.AgentCardRegistry = void 0;
|
|
4
4
|
const events_1 = require("events");
|
|
5
5
|
const room_1 = require("./room");
|
|
6
6
|
const logger_1 = require("./logger");
|
|
7
|
+
class AgentCardRegistry {
|
|
8
|
+
cards = new Map();
|
|
9
|
+
logger = new logger_1.Logger('a2a:cards');
|
|
10
|
+
register(card) {
|
|
11
|
+
this.cards.set(card.name, card);
|
|
12
|
+
this.logger.info('AgentCard registered', { name: card.name });
|
|
13
|
+
}
|
|
14
|
+
unregister(name) {
|
|
15
|
+
this.cards.delete(name);
|
|
16
|
+
}
|
|
17
|
+
get(name) {
|
|
18
|
+
return this.cards.get(name);
|
|
19
|
+
}
|
|
20
|
+
find(query) {
|
|
21
|
+
const lower = query.toLowerCase();
|
|
22
|
+
return Array.from(this.cards.values()).filter(a => a.name.toLowerCase().includes(lower) ||
|
|
23
|
+
a.description.toLowerCase().includes(lower) ||
|
|
24
|
+
a.capabilities.some(c => c.toLowerCase().includes(lower)));
|
|
25
|
+
}
|
|
26
|
+
async send(agentName, message) {
|
|
27
|
+
const agent = this.cards.get(agentName);
|
|
28
|
+
if (!agent)
|
|
29
|
+
throw new Error(`Agent '${agentName}' not found`);
|
|
30
|
+
if (agent.handler) {
|
|
31
|
+
return agent.handler(message);
|
|
32
|
+
}
|
|
33
|
+
else if (agent.endpoint) {
|
|
34
|
+
const res = await fetch(agent.endpoint, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
body: JSON.stringify({ message }),
|
|
38
|
+
});
|
|
39
|
+
const data = await res.json();
|
|
40
|
+
return data.response || data.content || '';
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`Agent '${agentName}' has no handler or endpoint`);
|
|
43
|
+
}
|
|
44
|
+
list() {
|
|
45
|
+
return Array.from(this.cards.values());
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.AgentCardRegistry = AgentCardRegistry;
|
|
7
49
|
// ── Agent Registry ──────────────────────────────────────────
|
|
8
50
|
class AgentRegistry extends events_1.EventEmitter {
|
|
9
51
|
registrations = new Map();
|
package/dist/core/agent.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { SkillLearner } from '../skills/auto-learn';
|
|
|
5
5
|
import type { MCPTool } from '../tools/mcp';
|
|
6
6
|
import { MCPToolRegistry } from '../tools/mcp';
|
|
7
7
|
import { type SubAgentConfig, type SubAgentResult } from './subagent';
|
|
8
|
+
import { Tracer } from '../telemetry';
|
|
8
9
|
export declare class BaseAgent extends EventEmitter implements IAgent {
|
|
9
10
|
readonly name: string;
|
|
10
11
|
private _state;
|
|
@@ -19,6 +20,9 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
|
|
|
19
20
|
private skillLearner?;
|
|
20
21
|
private autoLearnConfig;
|
|
21
22
|
private _subAgentManager?;
|
|
23
|
+
private longTermMemory?;
|
|
24
|
+
private longTermMemoryConfig;
|
|
25
|
+
private tracer?;
|
|
22
26
|
constructor(options: {
|
|
23
27
|
name: string;
|
|
24
28
|
systemPrompt?: string;
|
|
@@ -33,13 +37,25 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
|
|
|
33
37
|
improveOnUse?: boolean;
|
|
34
38
|
};
|
|
35
39
|
maxToolRounds?: number;
|
|
40
|
+
tracer?: Tracer;
|
|
36
41
|
});
|
|
42
|
+
setLongTermMemory(brain: any, config?: {
|
|
43
|
+
autoLearn?: boolean;
|
|
44
|
+
autoRecall?: boolean;
|
|
45
|
+
}): void;
|
|
46
|
+
getLongTermMemory(): any;
|
|
47
|
+
getLongTermMemoryConfig(): {
|
|
48
|
+
autoLearn: boolean;
|
|
49
|
+
autoRecall: boolean;
|
|
50
|
+
};
|
|
37
51
|
get state(): AgentState;
|
|
38
52
|
get provider(): LLMProvider;
|
|
39
53
|
getSystemPrompt(): string;
|
|
40
54
|
getMemory(): MemoryStore;
|
|
41
55
|
getSkillLearner(): SkillLearner | undefined;
|
|
42
56
|
getToolRegistry(): MCPToolRegistry;
|
|
57
|
+
getTracer(): Tracer | undefined;
|
|
58
|
+
setTracer(tracer: Tracer): void;
|
|
43
59
|
registerTool(tool: MCPTool): void;
|
|
44
60
|
private transition;
|
|
45
61
|
init(): Promise<void>;
|
package/dist/core/agent.js
CHANGED
|
@@ -21,6 +21,9 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
21
21
|
skillLearner;
|
|
22
22
|
autoLearnConfig;
|
|
23
23
|
_subAgentManager;
|
|
24
|
+
longTermMemory;
|
|
25
|
+
longTermMemoryConfig = { autoLearn: true, autoRecall: true };
|
|
26
|
+
tracer;
|
|
24
27
|
constructor(options) {
|
|
25
28
|
super();
|
|
26
29
|
this.name = options.name;
|
|
@@ -37,6 +40,22 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
37
40
|
if (options.skillsDir) {
|
|
38
41
|
this.skillLearner = new auto_learn_1.SkillLearner(options.skillsDir);
|
|
39
42
|
}
|
|
43
|
+
this.tracer = options.tracer;
|
|
44
|
+
}
|
|
45
|
+
setLongTermMemory(brain, config) {
|
|
46
|
+
this.longTermMemory = brain;
|
|
47
|
+
if (config) {
|
|
48
|
+
this.longTermMemoryConfig = {
|
|
49
|
+
autoLearn: config.autoLearn !== false,
|
|
50
|
+
autoRecall: config.autoRecall !== false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
getLongTermMemory() {
|
|
55
|
+
return this.longTermMemory;
|
|
56
|
+
}
|
|
57
|
+
getLongTermMemoryConfig() {
|
|
58
|
+
return this.longTermMemoryConfig;
|
|
40
59
|
}
|
|
41
60
|
get state() {
|
|
42
61
|
return this._state;
|
|
@@ -56,6 +75,12 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
56
75
|
getToolRegistry() {
|
|
57
76
|
return this.toolRegistry;
|
|
58
77
|
}
|
|
78
|
+
getTracer() {
|
|
79
|
+
return this.tracer;
|
|
80
|
+
}
|
|
81
|
+
setTracer(tracer) {
|
|
82
|
+
this.tracer = tracer;
|
|
83
|
+
}
|
|
59
84
|
registerTool(tool) {
|
|
60
85
|
this.toolRegistry.register(tool);
|
|
61
86
|
}
|
|
@@ -109,8 +134,45 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
109
134
|
}
|
|
110
135
|
async handleMessage(message) {
|
|
111
136
|
this.emit('message:in', message);
|
|
137
|
+
// Start root span if tracer is configured
|
|
138
|
+
let rootSpan;
|
|
139
|
+
if (this.tracer) {
|
|
140
|
+
rootSpan = this.tracer.startSpan('handleMessage', {
|
|
141
|
+
kind: 'server',
|
|
142
|
+
attributes: {
|
|
143
|
+
'message.channel': message.metadata?.channel || 'unknown',
|
|
144
|
+
'message.sender': message.metadata?.sender || 'unknown',
|
|
145
|
+
'message.length': message.content.length,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
this.tracer.increment('agent.messages.total', 1, { agent: this.name });
|
|
149
|
+
}
|
|
112
150
|
const sessionId = message.metadata?.sessionId ?? 'default';
|
|
113
151
|
await this.memory.addMessage(sessionId, message);
|
|
152
|
+
// === Recall from long-term memory ===
|
|
153
|
+
let memoryContext = '';
|
|
154
|
+
if (this.longTermMemory && this.longTermMemoryConfig.autoRecall) {
|
|
155
|
+
let memorySpan;
|
|
156
|
+
if (this.tracer && rootSpan) {
|
|
157
|
+
memorySpan = this.tracer.startSpan('memory.recall', { parent: rootSpan, kind: 'client' });
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const recalled = await this.longTermMemory.recall(message.content);
|
|
161
|
+
if (recalled && (Array.isArray(recalled) ? recalled.length > 0 : true)) {
|
|
162
|
+
memoryContext = '\n\n[Relevant memories]\n' +
|
|
163
|
+
(Array.isArray(recalled)
|
|
164
|
+
? recalled.map((r) => typeof r === 'string' ? r : r.content || r.compiled_truth || '').join('\n')
|
|
165
|
+
: String(recalled));
|
|
166
|
+
}
|
|
167
|
+
if (this.tracer && memorySpan)
|
|
168
|
+
this.tracer.endSpan(memorySpan, 'ok');
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
if (this.tracer && memorySpan)
|
|
172
|
+
this.tracer.endSpan(memorySpan, 'error');
|
|
173
|
+
// Silent fail — don't break chat if memory fails
|
|
174
|
+
}
|
|
175
|
+
}
|
|
114
176
|
const context = {
|
|
115
177
|
agentName: this.name,
|
|
116
178
|
sessionId,
|
|
@@ -136,27 +198,58 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
136
198
|
}
|
|
137
199
|
// Check if a learned skill matches — prepend instructions to system prompt
|
|
138
200
|
let effectiveSystemPrompt = this.systemPrompt;
|
|
201
|
+
// Inject long-term memory context
|
|
202
|
+
if (memoryContext) {
|
|
203
|
+
effectiveSystemPrompt = effectiveSystemPrompt + memoryContext;
|
|
204
|
+
}
|
|
139
205
|
const matchedSkill = this.skillLearner?.matchSkill(message.content);
|
|
140
206
|
if (matchedSkill) {
|
|
141
207
|
matchedSkill.usageCount++;
|
|
142
208
|
matchedSkill.lastUsed = new Date();
|
|
143
209
|
effectiveSystemPrompt = `[Learned Skill: ${matchedSkill.name}]\n${matchedSkill.instructions}\n\n${this.systemPrompt}`;
|
|
144
210
|
this.emit('skill:matched', matchedSkill);
|
|
211
|
+
if (this.tracer && rootSpan) {
|
|
212
|
+
this.tracer.addEvent(rootSpan, 'skill.matched', { 'skill.name': matchedSkill.name });
|
|
213
|
+
}
|
|
145
214
|
}
|
|
146
215
|
// Fall back to LLM with tool use loop
|
|
147
216
|
const tools = this.toolRegistry.list();
|
|
148
217
|
const llmMessages = [...context.messages];
|
|
149
218
|
let finalResponse = '';
|
|
150
219
|
for (let round = 0; round <= this.maxToolRounds; round++) {
|
|
220
|
+
let llmSpan;
|
|
221
|
+
if (this.tracer && rootSpan) {
|
|
222
|
+
llmSpan = this.tracer.startSpan('llm.chat', {
|
|
223
|
+
parent: rootSpan,
|
|
224
|
+
kind: 'client',
|
|
225
|
+
attributes: { 'llm.round': round },
|
|
226
|
+
});
|
|
227
|
+
}
|
|
151
228
|
const llmResponse = await this._provider.chat(llmMessages, effectiveSystemPrompt, { tools: tools.length > 0 ? tools : undefined });
|
|
229
|
+
if (this.tracer && llmSpan) {
|
|
230
|
+
llmSpan.attributes['llm.response.length'] = llmResponse.length;
|
|
231
|
+
this.tracer.endSpan(llmSpan, 'ok');
|
|
232
|
+
}
|
|
152
233
|
const toolCall = this.parseToolCall(llmResponse);
|
|
153
234
|
if (!toolCall || tools.length === 0 || round === this.maxToolRounds) {
|
|
154
235
|
finalResponse = llmResponse;
|
|
155
236
|
break;
|
|
156
237
|
}
|
|
157
238
|
// Execute tool
|
|
239
|
+
let toolSpan;
|
|
240
|
+
if (this.tracer && rootSpan) {
|
|
241
|
+
toolSpan = this.tracer.startSpan('tool.execute', {
|
|
242
|
+
parent: rootSpan,
|
|
243
|
+
kind: 'internal',
|
|
244
|
+
attributes: { 'tool.name': toolCall.name },
|
|
245
|
+
});
|
|
246
|
+
}
|
|
158
247
|
const toolResult = await this.toolRegistry.execute(toolCall.name, toolCall.arguments, context);
|
|
159
248
|
this.emit('tool:execute', toolCall.name, toolResult);
|
|
249
|
+
if (this.tracer && toolSpan) {
|
|
250
|
+
toolSpan.attributes['tool.result.length'] = toolResult.content?.length || 0;
|
|
251
|
+
this.tracer.endSpan(toolSpan, 'ok');
|
|
252
|
+
}
|
|
160
253
|
// Add tool call and result to messages for next round
|
|
161
254
|
llmMessages.push({
|
|
162
255
|
id: `tool_call_${Date.now()}`,
|
|
@@ -174,6 +267,21 @@ class BaseAgent extends events_1.EventEmitter {
|
|
|
174
267
|
const response = this.createResponse(finalResponse, message);
|
|
175
268
|
await this.memory.addMessage(sessionId, response);
|
|
176
269
|
this.emit('message:out', response);
|
|
270
|
+
// End root telemetry span
|
|
271
|
+
if (this.tracer && rootSpan) {
|
|
272
|
+
rootSpan.attributes['response.length'] = finalResponse.length;
|
|
273
|
+
this.tracer.endSpan(rootSpan, 'ok');
|
|
274
|
+
this.tracer.histogram('agent.message.duration', rootSpan.endTime - rootSpan.startTime, { agent: this.name });
|
|
275
|
+
}
|
|
276
|
+
// === Learn from interaction ===
|
|
277
|
+
if (this.longTermMemory && this.longTermMemoryConfig.autoLearn) {
|
|
278
|
+
try {
|
|
279
|
+
await this.longTermMemory.learn(`User: ${message.content}\nAssistant: ${finalResponse}`, { tags: ['conversation', message.metadata?.channel || 'unknown'] });
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Silent fail
|
|
283
|
+
}
|
|
284
|
+
}
|
|
177
285
|
// After response, check if we should learn a skill
|
|
178
286
|
if (this.skillLearner &&
|
|
179
287
|
this.autoLearnConfig.enabled &&
|
package/dist/core/runtime.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PluginManager } from '../plugins';
|
|
1
2
|
import { BaseAgent } from './agent';
|
|
2
3
|
import { Analytics } from '../analytics';
|
|
3
4
|
import type { OADDocument } from '../schema/oad';
|
|
@@ -12,6 +13,10 @@ export declare class AgentRuntime {
|
|
|
12
13
|
private isShuttingDown;
|
|
13
14
|
private analytics;
|
|
14
15
|
private scheduler;
|
|
16
|
+
private pluginManager;
|
|
17
|
+
private brain;
|
|
18
|
+
private agentBrain;
|
|
19
|
+
private evolveScheduler;
|
|
15
20
|
loadConfig(filePath: string): Promise<OADDocument>;
|
|
16
21
|
setHistoryLimit(limit: number): void;
|
|
17
22
|
initialize(config?: OADDocument): Promise<BaseAgent>;
|
|
@@ -23,5 +28,6 @@ export declare class AgentRuntime {
|
|
|
23
28
|
getAgent(): BaseAgent | null;
|
|
24
29
|
getAnalytics(): Analytics;
|
|
25
30
|
getConfig(): OADDocument | null;
|
|
31
|
+
getPluginManager(): PluginManager;
|
|
26
32
|
}
|
|
27
33
|
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/core/runtime.js
CHANGED
|
@@ -1,13 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.AgentRuntime = void 0;
|
|
4
37
|
exports.truncateOutput = truncateOutput;
|
|
38
|
+
const plugins_1 = require("../plugins");
|
|
39
|
+
const logger_1 = require("../plugins/logger");
|
|
40
|
+
const rate_limiter_1 = require("../plugins/rate-limiter");
|
|
41
|
+
const content_filter_1 = require("../plugins/content-filter");
|
|
5
42
|
const agent_1 = require("./agent");
|
|
6
43
|
const config_1 = require("./config");
|
|
7
|
-
const
|
|
44
|
+
const logger_2 = require("./logger");
|
|
8
45
|
const web_1 = require("../channels/web");
|
|
9
46
|
const telegram_1 = require("../channels/telegram");
|
|
10
47
|
const websocket_1 = require("../channels/websocket");
|
|
48
|
+
const wechat_1 = require("../channels/wechat");
|
|
49
|
+
const feishu_1 = require("../channels/feishu");
|
|
50
|
+
const email_1 = require("../channels/email");
|
|
11
51
|
const deepbrain_1 = require("../memory/deepbrain");
|
|
12
52
|
const analytics_1 = require("../analytics");
|
|
13
53
|
const scheduler_1 = require("./scheduler");
|
|
@@ -22,12 +62,16 @@ function truncateOutput(output, maxChars = MAX_TOOL_OUTPUT) {
|
|
|
22
62
|
class AgentRuntime {
|
|
23
63
|
agent = null;
|
|
24
64
|
config = null;
|
|
25
|
-
logger = new
|
|
65
|
+
logger = new logger_2.Logger('runtime');
|
|
26
66
|
historyLimit = DEFAULT_HISTORY_LIMIT;
|
|
27
67
|
shutdownHandlers = [];
|
|
28
68
|
isShuttingDown = false;
|
|
29
69
|
analytics = new analytics_1.Analytics();
|
|
30
70
|
scheduler = null;
|
|
71
|
+
pluginManager = new plugins_1.PluginManager();
|
|
72
|
+
brain = null;
|
|
73
|
+
agentBrain = null;
|
|
74
|
+
evolveScheduler = null;
|
|
31
75
|
async loadConfig(filePath) {
|
|
32
76
|
this.config = (0, config_1.loadOAD)(filePath);
|
|
33
77
|
this.logger.info('Config loaded', { name: this.config.metadata.name });
|
|
@@ -105,8 +149,88 @@ class AgentRuntime {
|
|
|
105
149
|
this.agent.bindChannel(new websocket_1.WebSocketChannel(ch.port ?? 3002));
|
|
106
150
|
this.logger.info('Bound websocket channel', { port: ch.port ?? 3002 });
|
|
107
151
|
}
|
|
152
|
+
else if (ch.type === 'wechat') {
|
|
153
|
+
this.agent.bindChannel(new wechat_1.WeChatChannel({
|
|
154
|
+
appId: ch.config?.appId ?? process.env.WECHAT_APP_ID ?? '',
|
|
155
|
+
appSecret: ch.config?.appSecret ?? process.env.WECHAT_APP_SECRET ?? '',
|
|
156
|
+
token: ch.config?.token ?? process.env.WECHAT_TOKEN ?? '',
|
|
157
|
+
encodingAESKey: ch.config?.encodingAESKey,
|
|
158
|
+
port: ch.port,
|
|
159
|
+
}));
|
|
160
|
+
this.logger.info('Bound wechat channel', { port: ch.port ?? 8080 });
|
|
161
|
+
}
|
|
162
|
+
else if (ch.type === 'feishu') {
|
|
163
|
+
this.agent.bindChannel(new feishu_1.FeishuChannel({
|
|
164
|
+
appId: ch.config?.appId ?? process.env.FEISHU_APP_ID,
|
|
165
|
+
appSecret: ch.config?.appSecret ?? process.env.FEISHU_APP_SECRET,
|
|
166
|
+
verificationToken: ch.config?.verificationToken ?? process.env.FEISHU_VERIFICATION_TOKEN,
|
|
167
|
+
encryptKey: ch.config?.encryptKey,
|
|
168
|
+
port: ch.port,
|
|
169
|
+
}));
|
|
170
|
+
this.logger.info('Bound feishu channel', { port: ch.port ?? 8081 });
|
|
171
|
+
}
|
|
172
|
+
else if (ch.type === 'email') {
|
|
173
|
+
this.agent.bindChannel(new email_1.EmailChannel({
|
|
174
|
+
mode: ch.config?.mode ?? 'webhook',
|
|
175
|
+
smtp: ch.config?.smtp,
|
|
176
|
+
imap: ch.config?.imap,
|
|
177
|
+
webhookPort: ch.port,
|
|
178
|
+
filters: ch.config?.filters,
|
|
179
|
+
}));
|
|
180
|
+
this.logger.info('Bound email channel', { mode: ch.config?.mode ?? 'webhook', port: ch.port ?? 8082 });
|
|
181
|
+
}
|
|
108
182
|
}
|
|
109
183
|
await this.agent.init();
|
|
184
|
+
// === Auto-wire DeepBrain long-term memory (Brain/AgentBrain) ===
|
|
185
|
+
const longTermCfg = memCfg && typeof memCfg.longTerm === 'object' ? memCfg.longTerm : null;
|
|
186
|
+
if (longTermCfg?.provider === 'deepbrain') {
|
|
187
|
+
try {
|
|
188
|
+
const deepbrainModule = await Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ 'deepbrain')));
|
|
189
|
+
const BrainClass = deepbrainModule.Brain ?? deepbrainModule.default?.Brain;
|
|
190
|
+
const AgentBrainClass = deepbrainModule.AgentBrain ?? deepbrainModule.default?.AgentBrain;
|
|
191
|
+
if (BrainClass && AgentBrainClass) {
|
|
192
|
+
const dbConfig = longTermCfg.config ?? {};
|
|
193
|
+
const dbPath = dbConfig.database || './data/brain.db';
|
|
194
|
+
const embeddingProvider = dbConfig.embeddingProvider || 'ollama';
|
|
195
|
+
this.brain = new BrainClass({
|
|
196
|
+
database: dbPath,
|
|
197
|
+
embedding_provider: embeddingProvider,
|
|
198
|
+
});
|
|
199
|
+
await this.brain.connect();
|
|
200
|
+
this.agentBrain = new AgentBrainClass(this.brain, cfg.metadata.name);
|
|
201
|
+
this.agent.setLongTermMemory(this.agentBrain, {
|
|
202
|
+
autoLearn: dbConfig.autoLearn !== false,
|
|
203
|
+
autoRecall: dbConfig.autoRecall !== false,
|
|
204
|
+
});
|
|
205
|
+
this.logger.info('DeepBrain Brain/AgentBrain connected', { database: dbPath });
|
|
206
|
+
// Brain seed loading
|
|
207
|
+
const { existsSync, readFileSync, renameSync } = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
208
|
+
const seedPath = './data/brain-seed.md';
|
|
209
|
+
if (existsSync(seedPath)) {
|
|
210
|
+
const seed = readFileSync(seedPath, 'utf-8');
|
|
211
|
+
await this.brain.put('brain-seed', seed, { type: 'seed', tags: ['seed', 'initial'] });
|
|
212
|
+
renameSync(seedPath, './data/brain-seed.loaded.md');
|
|
213
|
+
this.logger.info('Brain seed loaded');
|
|
214
|
+
}
|
|
215
|
+
// Auto-evolve scheduling
|
|
216
|
+
const evolveInterval = dbConfig.evolveInterval;
|
|
217
|
+
if (evolveInterval && evolveInterval > 0) {
|
|
218
|
+
const AutoEvolveSchedulerClass = deepbrainModule.AutoEvolveScheduler ?? deepbrainModule.default?.AutoEvolveScheduler;
|
|
219
|
+
if (AutoEvolveSchedulerClass) {
|
|
220
|
+
this.evolveScheduler = new AutoEvolveSchedulerClass();
|
|
221
|
+
this.evolveScheduler.start(this.agentBrain, evolveInterval);
|
|
222
|
+
this.logger.info('DeepBrain auto-evolve scheduled', { interval: evolveInterval });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.logger.warn('DeepBrain module found but Brain/AgentBrain classes not available');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
this.logger.warn('DeepBrain not available (install with: npm install deepbrain)', { error: e.message });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
110
234
|
// Wire analytics to agent events
|
|
111
235
|
this.agent.on('message:out', () => {
|
|
112
236
|
// responseTime is approximated; real timing is done via skill/llm events
|
|
@@ -118,6 +242,23 @@ class AgentRuntime {
|
|
|
118
242
|
this.analytics.recordError();
|
|
119
243
|
});
|
|
120
244
|
this.logger.info('Agent initialized', { name: cfg.metadata.name });
|
|
245
|
+
// Load enhanced plugins from OAD config
|
|
246
|
+
const pluginsCfg = cfg.spec.plugins;
|
|
247
|
+
if (pluginsCfg && Array.isArray(pluginsCfg)) {
|
|
248
|
+
const builtinPlugins = {
|
|
249
|
+
'logger': () => logger_1.loggerPlugin,
|
|
250
|
+
'rate-limiter': (c) => (0, rate_limiter_1.createRateLimiterPlugin)(c?.maxPerMinute ?? 60),
|
|
251
|
+
'content-filter': (c) => (0, content_filter_1.createContentFilterPlugin)(c?.blocklist ?? []),
|
|
252
|
+
};
|
|
253
|
+
for (const entry of pluginsCfg) {
|
|
254
|
+
const factory = builtinPlugins[entry.name];
|
|
255
|
+
if (factory) {
|
|
256
|
+
this.pluginManager.registerEnhanced(factory(entry.config));
|
|
257
|
+
this.logger.info('Enhanced plugin loaded from config', { name: entry.name });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
await this.pluginManager.initAll(this);
|
|
121
262
|
// Initialize scheduler if jobs are configured
|
|
122
263
|
const schedulerCfg = cfg.spec.scheduler;
|
|
123
264
|
if (schedulerCfg?.jobs && Array.isArray(schedulerCfg.jobs) && schedulerCfg.jobs.length > 0) {
|
|
@@ -169,10 +310,25 @@ class AgentRuntime {
|
|
|
169
310
|
if (!this.agent)
|
|
170
311
|
return;
|
|
171
312
|
this.logger.info('Stopping agent...');
|
|
313
|
+
if (this.evolveScheduler) {
|
|
314
|
+
try {
|
|
315
|
+
this.evolveScheduler.stop();
|
|
316
|
+
}
|
|
317
|
+
catch { /* ignore */ }
|
|
318
|
+
this.logger.info('DeepBrain auto-evolve stopped');
|
|
319
|
+
}
|
|
320
|
+
if (this.brain) {
|
|
321
|
+
try {
|
|
322
|
+
await this.brain.disconnect();
|
|
323
|
+
this.logger.info('DeepBrain disconnected');
|
|
324
|
+
}
|
|
325
|
+
catch { /* ignore */ }
|
|
326
|
+
}
|
|
172
327
|
if (this.scheduler) {
|
|
173
328
|
this.scheduler.stop();
|
|
174
329
|
this.logger.info('Scheduler stopped');
|
|
175
330
|
}
|
|
331
|
+
await this.pluginManager.shutdownAll();
|
|
176
332
|
await this.agent.stop();
|
|
177
333
|
for (const handler of this.shutdownHandlers) {
|
|
178
334
|
await handler();
|
|
@@ -213,6 +369,9 @@ class AgentRuntime {
|
|
|
213
369
|
getConfig() {
|
|
214
370
|
return this.config;
|
|
215
371
|
}
|
|
372
|
+
getPluginManager() {
|
|
373
|
+
return this.pluginManager;
|
|
374
|
+
}
|
|
216
375
|
}
|
|
217
376
|
exports.AgentRuntime = AgentRuntime;
|
|
218
377
|
//# sourceMappingURL=runtime.js.map
|
package/dist/core/sandbox.d.ts
CHANGED
|
@@ -4,6 +4,22 @@ export interface SandboxConfig {
|
|
|
4
4
|
agentDir: string;
|
|
5
5
|
networkAllowlist?: string[];
|
|
6
6
|
shellAllowed?: boolean;
|
|
7
|
+
allowedCommands?: string[];
|
|
8
|
+
blockedCommands?: string[];
|
|
9
|
+
maxFileSize?: number;
|
|
10
|
+
maxFiles?: number;
|
|
11
|
+
networkAccess?: boolean;
|
|
12
|
+
readOnlyPaths?: string[];
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ValidationResult {
|
|
16
|
+
allowed: boolean;
|
|
17
|
+
reason?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SandboxStatus {
|
|
20
|
+
files: number;
|
|
21
|
+
totalSize: number;
|
|
22
|
+
violations: number;
|
|
7
23
|
}
|
|
8
24
|
export interface SandboxRestrictions {
|
|
9
25
|
fileSystem: {
|
|
@@ -18,11 +34,21 @@ export interface SandboxRestrictions {
|
|
|
18
34
|
export declare class Sandbox {
|
|
19
35
|
private config;
|
|
20
36
|
private restrictions;
|
|
37
|
+
private violations;
|
|
38
|
+
private maxFileSize;
|
|
39
|
+
private maxFiles;
|
|
21
40
|
constructor(config: SandboxConfig);
|
|
22
41
|
get trustLevel(): TrustLevelType;
|
|
23
42
|
getRestrictions(): SandboxRestrictions;
|
|
24
43
|
checkFileAccess(filePath: string, mode: 'read' | 'write'): boolean;
|
|
25
44
|
checkNetworkAccess(url: string): boolean;
|
|
26
45
|
checkShellAccess(): boolean;
|
|
46
|
+
validateFileOp(action: 'read' | 'write' | 'delete', filePath: string): ValidationResult;
|
|
47
|
+
validateCommand(command: string): ValidationResult;
|
|
48
|
+
validateNetwork(url: string): ValidationResult;
|
|
49
|
+
getStatus(): SandboxStatus;
|
|
50
|
+
getViolations(): number;
|
|
51
|
+
getMaxFileSize(): number;
|
|
52
|
+
getMaxFiles(): number;
|
|
27
53
|
}
|
|
28
54
|
//# sourceMappingURL=sandbox.d.ts.map
|