opc-agent 1.4.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +91 -32
  3. package/dist/channels/email.d.ts +32 -26
  4. package/dist/channels/email.js +239 -62
  5. package/dist/channels/feishu.d.ts +21 -6
  6. package/dist/channels/feishu.js +225 -126
  7. package/dist/channels/telegram.d.ts +30 -9
  8. package/dist/channels/telegram.js +125 -33
  9. package/dist/channels/websocket.d.ts +46 -3
  10. package/dist/channels/websocket.js +306 -37
  11. package/dist/channels/wechat.d.ts +33 -13
  12. package/dist/channels/wechat.js +229 -42
  13. package/dist/cli.js +1127 -19
  14. package/dist/core/a2a.d.ts +17 -0
  15. package/dist/core/a2a.js +43 -1
  16. package/dist/core/agent.d.ts +39 -0
  17. package/dist/core/agent.js +228 -3
  18. package/dist/core/runtime.d.ts +7 -0
  19. package/dist/core/runtime.js +205 -2
  20. package/dist/core/sandbox.d.ts +26 -0
  21. package/dist/core/sandbox.js +117 -0
  22. package/dist/core/scheduler.d.ts +52 -0
  23. package/dist/core/scheduler.js +168 -0
  24. package/dist/core/subagent.d.ts +28 -0
  25. package/dist/core/subagent.js +65 -0
  26. package/dist/core/workflow-graph.d.ts +93 -0
  27. package/dist/core/workflow-graph.js +247 -0
  28. package/dist/daemon.d.ts +3 -0
  29. package/dist/daemon.js +134 -0
  30. package/dist/doctor.d.ts +15 -0
  31. package/dist/doctor.js +183 -0
  32. package/dist/eval/index.d.ts +65 -0
  33. package/dist/eval/index.js +191 -0
  34. package/dist/index.d.ts +37 -6
  35. package/dist/index.js +75 -3
  36. package/dist/plugins/content-filter.d.ts +7 -0
  37. package/dist/plugins/content-filter.js +25 -0
  38. package/dist/plugins/index.d.ts +42 -0
  39. package/dist/plugins/index.js +108 -2
  40. package/dist/plugins/logger.d.ts +6 -0
  41. package/dist/plugins/logger.js +20 -0
  42. package/dist/plugins/rate-limiter.d.ts +7 -0
  43. package/dist/plugins/rate-limiter.js +35 -0
  44. package/dist/protocols/a2a/client.d.ts +25 -0
  45. package/dist/protocols/a2a/client.js +115 -0
  46. package/dist/protocols/a2a/index.d.ts +6 -0
  47. package/dist/protocols/a2a/index.js +12 -0
  48. package/dist/protocols/a2a/server.d.ts +41 -0
  49. package/dist/protocols/a2a/server.js +295 -0
  50. package/dist/protocols/a2a/types.d.ts +91 -0
  51. package/dist/protocols/a2a/types.js +15 -0
  52. package/dist/protocols/a2a/utils.d.ts +6 -0
  53. package/dist/protocols/a2a/utils.js +47 -0
  54. package/dist/protocols/agui/client.d.ts +10 -0
  55. package/dist/protocols/agui/client.js +75 -0
  56. package/dist/protocols/agui/index.d.ts +4 -0
  57. package/dist/protocols/agui/index.js +25 -0
  58. package/dist/protocols/agui/server.d.ts +37 -0
  59. package/dist/protocols/agui/server.js +191 -0
  60. package/dist/protocols/agui/types.d.ts +107 -0
  61. package/dist/protocols/agui/types.js +17 -0
  62. package/dist/protocols/index.d.ts +2 -0
  63. package/dist/protocols/index.js +19 -0
  64. package/dist/protocols/mcp/agent-tools.d.ts +11 -0
  65. package/dist/protocols/mcp/agent-tools.js +129 -0
  66. package/dist/protocols/mcp/index.d.ts +5 -0
  67. package/dist/protocols/mcp/index.js +11 -0
  68. package/dist/protocols/mcp/server.d.ts +31 -0
  69. package/dist/protocols/mcp/server.js +248 -0
  70. package/dist/protocols/mcp/types.d.ts +92 -0
  71. package/dist/protocols/mcp/types.js +17 -0
  72. package/dist/providers/index.d.ts +5 -1
  73. package/dist/providers/index.js +16 -9
  74. package/dist/publish/index.d.ts +45 -0
  75. package/dist/publish/index.js +350 -0
  76. package/dist/schema/oad.d.ts +859 -67
  77. package/dist/schema/oad.js +47 -3
  78. package/dist/security/approval.d.ts +36 -0
  79. package/dist/security/approval.js +113 -0
  80. package/dist/security/index.d.ts +4 -0
  81. package/dist/security/index.js +8 -0
  82. package/dist/security/keys.d.ts +16 -0
  83. package/dist/security/keys.js +117 -0
  84. package/dist/skills/auto-learn.d.ts +28 -0
  85. package/dist/skills/auto-learn.js +257 -0
  86. package/dist/studio/server.d.ts +63 -0
  87. package/dist/studio/server.js +625 -0
  88. package/dist/studio-ui/index.html +662 -0
  89. package/dist/telemetry/index.d.ts +93 -0
  90. package/dist/telemetry/index.js +285 -0
  91. package/dist/tools/builtin/datetime.d.ts +3 -0
  92. package/dist/tools/builtin/datetime.js +44 -0
  93. package/dist/tools/builtin/file.d.ts +3 -0
  94. package/dist/tools/builtin/file.js +151 -0
  95. package/dist/tools/builtin/index.d.ts +15 -0
  96. package/dist/tools/builtin/index.js +30 -0
  97. package/dist/tools/builtin/shell.d.ts +3 -0
  98. package/dist/tools/builtin/shell.js +43 -0
  99. package/dist/tools/builtin/web.d.ts +3 -0
  100. package/dist/tools/builtin/web.js +37 -0
  101. package/dist/tools/mcp-client.d.ts +24 -0
  102. package/dist/tools/mcp-client.js +119 -0
  103. package/package.json +5 -3
  104. package/scripts/install.ps1 +31 -0
  105. package/scripts/install.sh +40 -0
  106. package/src/channels/email.ts +351 -177
  107. package/src/channels/feishu.ts +349 -236
  108. package/src/channels/telegram.ts +212 -90
  109. package/src/channels/websocket.ts +399 -87
  110. package/src/channels/wechat.ts +329 -149
  111. package/src/cli.ts +1201 -20
  112. package/src/core/a2a.ts +60 -0
  113. package/src/core/agent.ts +420 -152
  114. package/src/core/runtime.ts +174 -0
  115. package/src/core/sandbox.ts +143 -0
  116. package/src/core/scheduler.ts +187 -0
  117. package/src/core/subagent.ts +98 -0
  118. package/src/core/workflow-graph.ts +365 -0
  119. package/src/daemon.ts +96 -0
  120. package/src/doctor.ts +156 -0
  121. package/src/eval/index.ts +211 -0
  122. package/src/eval/suites/basic.json +16 -0
  123. package/src/eval/suites/memory.json +12 -0
  124. package/src/eval/suites/safety.json +14 -0
  125. package/src/index.ts +65 -6
  126. package/src/plugins/content-filter.ts +23 -0
  127. package/src/plugins/index.ts +133 -2
  128. package/src/plugins/logger.ts +18 -0
  129. package/src/plugins/rate-limiter.ts +38 -0
  130. package/src/protocols/a2a/client.ts +132 -0
  131. package/src/protocols/a2a/index.ts +8 -0
  132. package/src/protocols/a2a/server.ts +333 -0
  133. package/src/protocols/a2a/types.ts +88 -0
  134. package/src/protocols/a2a/utils.ts +50 -0
  135. package/src/protocols/agui/client.ts +83 -0
  136. package/src/protocols/agui/index.ts +4 -0
  137. package/src/protocols/agui/server.ts +218 -0
  138. package/src/protocols/agui/types.ts +153 -0
  139. package/src/protocols/index.ts +2 -0
  140. package/src/protocols/mcp/agent-tools.ts +134 -0
  141. package/src/protocols/mcp/index.ts +8 -0
  142. package/src/protocols/mcp/server.ts +262 -0
  143. package/src/protocols/mcp/types.ts +69 -0
  144. package/src/providers/index.ts +354 -339
  145. package/src/publish/index.ts +376 -0
  146. package/src/schema/oad.ts +204 -154
  147. package/src/security/approval.ts +131 -0
  148. package/src/security/index.ts +3 -0
  149. package/src/security/keys.ts +87 -0
  150. package/src/skills/auto-learn.ts +262 -0
  151. package/src/studio/server.ts +629 -0
  152. package/src/studio-ui/index.html +662 -0
  153. package/src/telemetry/index.ts +324 -0
  154. package/src/tools/builtin/datetime.ts +41 -0
  155. package/src/tools/builtin/file.ts +107 -0
  156. package/src/tools/builtin/index.ts +28 -0
  157. package/src/tools/builtin/shell.ts +43 -0
  158. package/src/tools/builtin/web.ts +35 -0
  159. package/src/tools/mcp-client.ts +131 -0
  160. package/src/types/agent-workstation.d.ts +2 -0
  161. package/tests/a2a-protocol.test.ts +285 -0
  162. package/tests/agui-protocol.test.ts +246 -0
  163. package/tests/auto-learn.test.ts +105 -0
  164. package/tests/builtin-tools.test.ts +83 -0
  165. package/tests/channels/discord.test.ts +79 -0
  166. package/tests/channels/email.test.ts +148 -0
  167. package/tests/channels/feishu.test.ts +123 -0
  168. package/tests/channels/telegram.test.ts +129 -0
  169. package/tests/channels/websocket.test.ts +53 -0
  170. package/tests/channels/wechat.test.ts +170 -0
  171. package/tests/chat-cli.test.ts +160 -0
  172. package/tests/cli.test.ts +46 -0
  173. package/tests/daemon.test.ts +135 -0
  174. package/tests/deepbrain-wire.test.ts +234 -0
  175. package/tests/doctor.test.ts +38 -0
  176. package/tests/eval.test.ts +173 -0
  177. package/tests/init-role.test.ts +124 -0
  178. package/tests/mcp-client.test.ts +92 -0
  179. package/tests/mcp-server.test.ts +178 -0
  180. package/tests/plugin-a2a-enhanced.test.ts +230 -0
  181. package/tests/publish.test.ts +231 -0
  182. package/tests/scheduler.test.ts +200 -0
  183. package/tests/security-enhanced.test.ts +233 -0
  184. package/tests/skill-learner.test.ts +161 -0
  185. package/tests/studio.test.ts +229 -0
  186. package/tests/subagent.test.ts +193 -0
  187. package/tests/telegram-discord.test.ts +60 -0
  188. package/tests/telemetry.test.ts +186 -0
  189. package/tests/tools/builtin-extended.test.ts +138 -0
  190. package/tests/workflow-graph.test.ts +279 -0
  191. package/tutorial/customer-service-agent/README.md +612 -0
  192. package/tutorial/customer-service-agent/SOUL.md +26 -0
  193. package/tutorial/customer-service-agent/agent.yaml +63 -0
  194. package/tutorial/customer-service-agent/package.json +19 -0
  195. package/tutorial/customer-service-agent/src/index.ts +69 -0
  196. package/tutorial/customer-service-agent/src/skills/faq.ts +27 -0
  197. package/tutorial/customer-service-agent/src/skills/ticket.ts +22 -0
  198. package/tutorial/customer-service-agent/tsconfig.json +14 -0
@@ -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();
@@ -1,6 +1,11 @@
1
1
  import { EventEmitter } from 'events';
2
2
  import type { AgentState, IAgent, IChannel, ISkill, Message, MemoryStore } from './types';
3
3
  import { type LLMProvider } from '../providers';
4
+ import { SkillLearner } from '../skills/auto-learn';
5
+ import type { MCPTool } from '../tools/mcp';
6
+ import { MCPToolRegistry } from '../tools/mcp';
7
+ import { type SubAgentConfig, type SubAgentResult } from './subagent';
8
+ import { Tracer } from '../telemetry';
4
9
  export declare class BaseAgent extends EventEmitter implements IAgent {
5
10
  readonly name: string;
6
11
  private _state;
@@ -10,6 +15,14 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
10
15
  private _provider;
11
16
  private systemPrompt;
12
17
  private historyLimit;
18
+ private toolRegistry;
19
+ private maxToolRounds;
20
+ private skillLearner?;
21
+ private autoLearnConfig;
22
+ private _subAgentManager?;
23
+ private longTermMemory?;
24
+ private longTermMemoryConfig;
25
+ private tracer?;
13
26
  constructor(options: {
14
27
  name: string;
15
28
  systemPrompt?: string;
@@ -17,11 +30,33 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
17
30
  model?: string;
18
31
  memory?: MemoryStore;
19
32
  historyLimit?: number;
33
+ skillsDir?: string;
34
+ learning?: {
35
+ autoSkillCreation?: boolean;
36
+ minConversationLength?: number;
37
+ improveOnUse?: boolean;
38
+ };
39
+ maxToolRounds?: number;
40
+ tracer?: Tracer;
20
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
+ };
21
51
  get state(): AgentState;
22
52
  get provider(): LLMProvider;
23
53
  getSystemPrompt(): string;
24
54
  getMemory(): MemoryStore;
55
+ getSkillLearner(): SkillLearner | undefined;
56
+ getToolRegistry(): MCPToolRegistry;
57
+ getTracer(): Tracer | undefined;
58
+ setTracer(tracer: Tracer): void;
59
+ registerTool(tool: MCPTool): void;
25
60
  private transition;
26
61
  init(): Promise<void>;
27
62
  start(): Promise<void>;
@@ -29,7 +64,11 @@ export declare class BaseAgent extends EventEmitter implements IAgent {
29
64
  registerSkill(skill: ISkill): void;
30
65
  bindChannel(channel: IChannel): void;
31
66
  getChannels(): IChannel[];
67
+ private getSubAgentManager;
68
+ spawnSubAgent(config: SubAgentConfig): Promise<SubAgentResult>;
69
+ spawnParallel(configs: SubAgentConfig[]): Promise<SubAgentResult[]>;
32
70
  handleMessage(message: Message): Promise<Message>;
71
+ private parseToolCall;
33
72
  handleMessageStream(message: Message): AsyncIterable<string>;
34
73
  private createResponse;
35
74
  }
@@ -4,6 +4,9 @@ exports.BaseAgent = void 0;
4
4
  const events_1 = require("events");
5
5
  const memory_1 = require("../memory");
6
6
  const providers_1 = require("../providers");
7
+ const auto_learn_1 = require("../skills/auto-learn");
8
+ const mcp_1 = require("../tools/mcp");
9
+ const subagent_1 = require("./subagent");
7
10
  class BaseAgent extends events_1.EventEmitter {
8
11
  name;
9
12
  _state = 'init';
@@ -13,6 +16,14 @@ class BaseAgent extends events_1.EventEmitter {
13
16
  _provider;
14
17
  systemPrompt;
15
18
  historyLimit;
19
+ toolRegistry = new mcp_1.MCPToolRegistry();
20
+ maxToolRounds;
21
+ skillLearner;
22
+ autoLearnConfig;
23
+ _subAgentManager;
24
+ longTermMemory;
25
+ longTermMemoryConfig = { autoLearn: true, autoRecall: true };
26
+ tracer;
16
27
  constructor(options) {
17
28
  super();
18
29
  this.name = options.name;
@@ -20,6 +31,31 @@ class BaseAgent extends events_1.EventEmitter {
20
31
  this.memory = options.memory ?? new memory_1.InMemoryStore();
21
32
  this._provider = (0, providers_1.createProvider)(options.provider ?? 'openai', options.model);
22
33
  this.historyLimit = options.historyLimit ?? 50;
34
+ this.maxToolRounds = options.maxToolRounds ?? 10;
35
+ this.autoLearnConfig = {
36
+ enabled: options.learning?.autoSkillCreation !== false,
37
+ minConversationLength: options.learning?.minConversationLength ?? 3,
38
+ improveOnUse: options.learning?.improveOnUse !== false,
39
+ };
40
+ if (options.skillsDir) {
41
+ this.skillLearner = new auto_learn_1.SkillLearner(options.skillsDir);
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;
23
59
  }
24
60
  get state() {
25
61
  return this._state;
@@ -33,12 +69,30 @@ class BaseAgent extends events_1.EventEmitter {
33
69
  getMemory() {
34
70
  return this.memory;
35
71
  }
72
+ getSkillLearner() {
73
+ return this.skillLearner;
74
+ }
75
+ getToolRegistry() {
76
+ return this.toolRegistry;
77
+ }
78
+ getTracer() {
79
+ return this.tracer;
80
+ }
81
+ setTracer(tracer) {
82
+ this.tracer = tracer;
83
+ }
84
+ registerTool(tool) {
85
+ this.toolRegistry.register(tool);
86
+ }
36
87
  transition(to) {
37
88
  const from = this._state;
38
89
  this._state = to;
39
90
  this.emit('state:change', from, to);
40
91
  }
41
92
  async init() {
93
+ if (this.skillLearner) {
94
+ await this.skillLearner.loadLearnedSkills();
95
+ }
42
96
  this.transition('ready');
43
97
  }
44
98
  async start() {
@@ -66,10 +120,59 @@ class BaseAgent extends events_1.EventEmitter {
66
120
  getChannels() {
67
121
  return this.channels;
68
122
  }
123
+ getSubAgentManager() {
124
+ if (!this._subAgentManager) {
125
+ this._subAgentManager = new subagent_1.SubAgentManager();
126
+ }
127
+ return this._subAgentManager;
128
+ }
129
+ async spawnSubAgent(config) {
130
+ return this.getSubAgentManager().spawn(config, this._provider);
131
+ }
132
+ async spawnParallel(configs) {
133
+ return this.getSubAgentManager().spawnParallel(configs, this._provider);
134
+ }
69
135
  async handleMessage(message) {
70
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
+ }
71
150
  const sessionId = message.metadata?.sessionId ?? 'default';
72
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
+ }
73
176
  const context = {
74
177
  agentName: this.name,
75
178
  sessionId,
@@ -93,13 +196,135 @@ class BaseAgent extends events_1.EventEmitter {
93
196
  this.emit('error', err instanceof Error ? err : new Error(String(err)));
94
197
  }
95
198
  }
96
- // Fall back to LLM
97
- const llmResponse = await this._provider.chat(context.messages, this.systemPrompt);
98
- const response = this.createResponse(llmResponse, message);
199
+ // Check if a learned skill matches — prepend instructions to system prompt
200
+ let effectiveSystemPrompt = this.systemPrompt;
201
+ // Inject long-term memory context
202
+ if (memoryContext) {
203
+ effectiveSystemPrompt = effectiveSystemPrompt + memoryContext;
204
+ }
205
+ const matchedSkill = this.skillLearner?.matchSkill(message.content);
206
+ if (matchedSkill) {
207
+ matchedSkill.usageCount++;
208
+ matchedSkill.lastUsed = new Date();
209
+ effectiveSystemPrompt = `[Learned Skill: ${matchedSkill.name}]\n${matchedSkill.instructions}\n\n${this.systemPrompt}`;
210
+ this.emit('skill:matched', matchedSkill);
211
+ if (this.tracer && rootSpan) {
212
+ this.tracer.addEvent(rootSpan, 'skill.matched', { 'skill.name': matchedSkill.name });
213
+ }
214
+ }
215
+ // Fall back to LLM with tool use loop
216
+ const tools = this.toolRegistry.list();
217
+ const llmMessages = [...context.messages];
218
+ let finalResponse = '';
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
+ }
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
+ }
233
+ const toolCall = this.parseToolCall(llmResponse);
234
+ if (!toolCall || tools.length === 0 || round === this.maxToolRounds) {
235
+ finalResponse = llmResponse;
236
+ break;
237
+ }
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
+ }
247
+ const toolResult = await this.toolRegistry.execute(toolCall.name, toolCall.arguments, context);
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
+ }
253
+ // Add tool call and result to messages for next round
254
+ llmMessages.push({
255
+ id: `tool_call_${Date.now()}`,
256
+ role: 'assistant',
257
+ content: llmResponse,
258
+ timestamp: Date.now(),
259
+ });
260
+ llmMessages.push({
261
+ id: `tool_result_${Date.now()}`,
262
+ role: 'user',
263
+ content: `[Tool Result for ${toolCall.name}]: ${toolResult.content}`,
264
+ timestamp: Date.now(),
265
+ });
266
+ }
267
+ const response = this.createResponse(finalResponse, message);
99
268
  await this.memory.addMessage(sessionId, response);
100
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
+ }
285
+ // After response, check if we should learn a skill
286
+ if (this.skillLearner &&
287
+ this.autoLearnConfig.enabled &&
288
+ context.messages.length >= this.autoLearnConfig.minConversationLength) {
289
+ this.skillLearner
290
+ .analyzeForSkillCreation(context.messages, this._provider)
291
+ .then(async (learnedSkill) => {
292
+ if (learnedSkill) {
293
+ await this.skillLearner.saveSkill(learnedSkill);
294
+ this.emit('skill:learned', learnedSkill);
295
+ }
296
+ })
297
+ .catch(() => { });
298
+ }
299
+ // Improve matched skill after use
300
+ if (matchedSkill && this.skillLearner && this.autoLearnConfig.improveOnUse) {
301
+ this.skillLearner
302
+ .improveSkill(matchedSkill, context.messages, this._provider)
303
+ .then(() => this.skillLearner.saveSkill(matchedSkill))
304
+ .catch(() => { });
305
+ }
101
306
  return response;
102
307
  }
308
+ parseToolCall(response) {
309
+ try {
310
+ const parsed = JSON.parse(response);
311
+ if (parsed.tool_call)
312
+ return parsed.tool_call;
313
+ if (parsed.name && parsed.arguments !== undefined)
314
+ return parsed;
315
+ }
316
+ catch { /* not JSON */ }
317
+ const match = response.match(/<tool_call>\s*(\{[\s\S]*?\})\s*<\/tool_call>/);
318
+ if (match) {
319
+ try {
320
+ const parsed = JSON.parse(match[1]);
321
+ if (parsed.name)
322
+ return parsed;
323
+ }
324
+ catch { /* not valid JSON */ }
325
+ }
326
+ return null;
327
+ }
103
328
  async *handleMessageStream(message) {
104
329
  const sessionId = message.metadata?.sessionId ?? 'default';
105
330
  await this.memory.addMessage(sessionId, message);
@@ -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';
@@ -11,6 +12,11 @@ export declare class AgentRuntime {
11
12
  private shutdownHandlers;
12
13
  private isShuttingDown;
13
14
  private analytics;
15
+ private scheduler;
16
+ private pluginManager;
17
+ private brain;
18
+ private agentBrain;
19
+ private evolveScheduler;
14
20
  loadConfig(filePath: string): Promise<OADDocument>;
15
21
  setHistoryLimit(limit: number): void;
16
22
  initialize(config?: OADDocument): Promise<BaseAgent>;
@@ -22,5 +28,6 @@ export declare class AgentRuntime {
22
28
  getAgent(): BaseAgent | null;
23
29
  getAnalytics(): Analytics;
24
30
  getConfig(): OADDocument | null;
31
+ getPluginManager(): PluginManager;
25
32
  }
26
33
  //# sourceMappingURL=runtime.d.ts.map