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
@@ -0,0 +1,218 @@
1
+ // AG-UI Server — SSE streaming endpoint for agent-to-frontend communication
2
+ import { IncomingMessage, ServerResponse, Server } from 'http';
3
+ import type { AGUIEvent, AGUIRunRequest, AGUIMessage } from './types';
4
+ import type { BaseAgent } from '../../core/agent';
5
+ import type { Message } from '../../core/types';
6
+
7
+ // ─── AGUIEventEmitter ────────────────────────────────────────
8
+
9
+ export class AGUIEventEmitter {
10
+ private closed = false;
11
+
12
+ constructor(private res: ServerResponse) {}
13
+
14
+ emit(event: AGUIEvent): void {
15
+ if (this.closed) return;
16
+ const data = JSON.stringify(event);
17
+ this.res.write(`data: ${data}\n\n`);
18
+ }
19
+
20
+ textStart(messageId: string): void {
21
+ this.emit({ type: 'TEXT_MESSAGE_START', messageId, role: 'assistant', timestamp: now() });
22
+ }
23
+
24
+ textContent(messageId: string, delta: string): void {
25
+ this.emit({ type: 'TEXT_MESSAGE_CONTENT', messageId, delta, timestamp: now() });
26
+ }
27
+
28
+ textEnd(messageId: string): void {
29
+ this.emit({ type: 'TEXT_MESSAGE_END', messageId, timestamp: now() });
30
+ }
31
+
32
+ toolCallStart(id: string, name: string): void {
33
+ this.emit({ type: 'TOOL_CALL_START', toolCallId: id, toolCallName: name, timestamp: now() });
34
+ }
35
+
36
+ toolCallArgs(id: string, delta: string): void {
37
+ this.emit({ type: 'TOOL_CALL_ARGS', toolCallId: id, delta, timestamp: now() });
38
+ }
39
+
40
+ toolCallEnd(id: string): void {
41
+ this.emit({ type: 'TOOL_CALL_END', toolCallId: id, timestamp: now() });
42
+ }
43
+
44
+ stateSnapshot(snapshot: Record<string, any>): void {
45
+ this.emit({ type: 'STATE_SNAPSHOT', snapshot, timestamp: now() });
46
+ }
47
+
48
+ stateDelta(delta: any[]): void {
49
+ this.emit({ type: 'STATE_DELTA', delta, timestamp: now() });
50
+ }
51
+
52
+ runStarted(runId: string, threadId?: string): void {
53
+ this.emit({ type: 'RUN_STARTED', runId, ...(threadId ? { threadId } : {}), timestamp: now() });
54
+ }
55
+
56
+ runFinished(runId: string): void {
57
+ this.emit({ type: 'RUN_FINISHED', runId, timestamp: now() });
58
+ }
59
+
60
+ runError(runId: string, message: string, code?: string): void {
61
+ this.emit({ type: 'RUN_ERROR', runId, message, ...(code ? { code } : {}), timestamp: now() });
62
+ }
63
+
64
+ stepStarted(stepId: string, stepName?: string): void {
65
+ this.emit({ type: 'STEP_STARTED', stepId, ...(stepName ? { stepName } : {}), timestamp: now() });
66
+ }
67
+
68
+ stepFinished(stepId: string): void {
69
+ this.emit({ type: 'STEP_FINISHED', stepId, timestamp: now() });
70
+ }
71
+
72
+ messagesSnapshot(messages: AGUIMessage[]): void {
73
+ this.emit({ type: 'MESSAGES_SNAPSHOT', messages, timestamp: now() });
74
+ }
75
+
76
+ custom(name: string, value: any): void {
77
+ this.emit({ type: 'CUSTOM', name, value, timestamp: now() });
78
+ }
79
+
80
+ close(): void {
81
+ if (this.closed) return;
82
+ this.closed = true;
83
+ this.res.end();
84
+ }
85
+
86
+ get isClosed(): boolean {
87
+ return this.closed;
88
+ }
89
+ }
90
+
91
+ // ─── AGUIServer ──────────────────────────────────────────────
92
+
93
+ export class AGUIServer {
94
+ private agent: BaseAgent;
95
+ private path: string;
96
+
97
+ constructor(agent: BaseAgent, config?: { path?: string }) {
98
+ this.agent = agent;
99
+ this.path = config?.path ?? '/agui';
100
+ }
101
+
102
+ mount(server: Server): void {
103
+ const original = server.listeners('request')[0] as any;
104
+ server.removeAllListeners('request');
105
+
106
+ server.on('request', (req: IncomingMessage, res: ServerResponse) => {
107
+ const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
108
+ if (req.method === 'POST' && url.pathname === this.path) {
109
+ this.handleRun(req, res);
110
+ } else if (req.method === 'OPTIONS' && url.pathname === this.path) {
111
+ res.writeHead(204, {
112
+ 'Access-Control-Allow-Origin': '*',
113
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS',
114
+ 'Access-Control-Allow-Headers': 'Content-Type',
115
+ });
116
+ res.end();
117
+ } else if (original) {
118
+ original(req, res);
119
+ } else {
120
+ res.writeHead(404);
121
+ res.end('Not Found');
122
+ }
123
+ });
124
+ }
125
+
126
+ async handleRun(req: IncomingMessage, res: ServerResponse): Promise<void> {
127
+ let body = '';
128
+ for await (const chunk of req) body += chunk;
129
+
130
+ let request: AGUIRunRequest;
131
+ try {
132
+ request = JSON.parse(body);
133
+ if (!request.messages || !Array.isArray(request.messages)) {
134
+ res.writeHead(400, { 'Content-Type': 'application/json' });
135
+ res.end(JSON.stringify({ error: 'messages array required' }));
136
+ return;
137
+ }
138
+ } catch {
139
+ res.writeHead(400, { 'Content-Type': 'application/json' });
140
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
141
+ return;
142
+ }
143
+
144
+ // Set up SSE
145
+ res.writeHead(200, {
146
+ 'Content-Type': 'text/event-stream',
147
+ 'Cache-Control': 'no-cache',
148
+ 'Connection': 'keep-alive',
149
+ 'Access-Control-Allow-Origin': '*',
150
+ });
151
+
152
+ const emitter = new AGUIEventEmitter(res);
153
+ const runId = request.runId ?? `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
154
+
155
+ try {
156
+ await this.streamResponse(request, emitter, runId);
157
+ } catch (err: any) {
158
+ emitter.runError(runId, err?.message ?? 'Unknown error', 'INTERNAL_ERROR');
159
+ } finally {
160
+ emitter.close();
161
+ }
162
+ }
163
+
164
+ private async streamResponse(request: AGUIRunRequest, emitter: AGUIEventEmitter, runId: string): Promise<void> {
165
+ emitter.runStarted(runId, request.threadId);
166
+
167
+ // Convert AG-UI messages to BaseAgent message format
168
+ const lastUserMsg = [...request.messages].reverse().find(m => m.role === 'user');
169
+ if (!lastUserMsg) {
170
+ emitter.runError(runId, 'No user message found', 'BAD_REQUEST');
171
+ return;
172
+ }
173
+
174
+ const message: Message = {
175
+ id: lastUserMsg.id || `msg_${Date.now()}`,
176
+ role: 'user',
177
+ content: lastUserMsg.content,
178
+ timestamp: Date.now(),
179
+ metadata: {
180
+ channel: 'agui',
181
+ sessionId: request.threadId ?? 'agui-default',
182
+ },
183
+ };
184
+
185
+ const messageId = `msg_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
186
+
187
+ // Try streaming if agent supports it
188
+ try {
189
+ emitter.textStart(messageId);
190
+
191
+ let hasChunks = false;
192
+ for await (const chunk of this.agent.handleMessageStream(message)) {
193
+ hasChunks = true;
194
+ emitter.textContent(messageId, chunk);
195
+ }
196
+
197
+ if (!hasChunks) {
198
+ // Fallback to non-streaming
199
+ const response = await this.agent.handleMessage(message);
200
+ emitter.textContent(messageId, response.content);
201
+ }
202
+
203
+ emitter.textEnd(messageId);
204
+ } catch {
205
+ // Fallback to non-streaming handleMessage
206
+ emitter.textStart(messageId);
207
+ const response = await this.agent.handleMessage(message);
208
+ emitter.textContent(messageId, response.content);
209
+ emitter.textEnd(messageId);
210
+ }
211
+
212
+ emitter.runFinished(runId);
213
+ }
214
+ }
215
+
216
+ function now(): string {
217
+ return new Date().toISOString();
218
+ }
@@ -0,0 +1,153 @@
1
+ // AG-UI Protocol Types — Agent-User Interaction Protocol
2
+ // https://docs.ag-ui.com
3
+
4
+ export type AGUIEventType =
5
+ | 'TEXT_MESSAGE_START'
6
+ | 'TEXT_MESSAGE_CONTENT'
7
+ | 'TEXT_MESSAGE_END'
8
+ | 'TOOL_CALL_START'
9
+ | 'TOOL_CALL_ARGS'
10
+ | 'TOOL_CALL_END'
11
+ | 'STATE_SNAPSHOT'
12
+ | 'STATE_DELTA'
13
+ | 'MESSAGES_SNAPSHOT'
14
+ | 'RUN_STARTED'
15
+ | 'RUN_FINISHED'
16
+ | 'RUN_ERROR'
17
+ | 'STEP_STARTED'
18
+ | 'STEP_FINISHED'
19
+ | 'CUSTOM';
20
+
21
+ export const AGUI_EVENT_TYPES: AGUIEventType[] = [
22
+ 'TEXT_MESSAGE_START', 'TEXT_MESSAGE_CONTENT', 'TEXT_MESSAGE_END',
23
+ 'TOOL_CALL_START', 'TOOL_CALL_ARGS', 'TOOL_CALL_END',
24
+ 'STATE_SNAPSHOT', 'STATE_DELTA', 'MESSAGES_SNAPSHOT',
25
+ 'RUN_STARTED', 'RUN_FINISHED', 'RUN_ERROR',
26
+ 'STEP_STARTED', 'STEP_FINISHED', 'CUSTOM',
27
+ ];
28
+
29
+ export interface AGUIEvent {
30
+ type: AGUIEventType;
31
+ timestamp: string;
32
+ [key: string]: any;
33
+ }
34
+
35
+ export interface TextMessageStartEvent extends AGUIEvent {
36
+ type: 'TEXT_MESSAGE_START';
37
+ messageId: string;
38
+ role: 'assistant';
39
+ }
40
+
41
+ export interface TextMessageContentEvent extends AGUIEvent {
42
+ type: 'TEXT_MESSAGE_CONTENT';
43
+ messageId: string;
44
+ delta: string;
45
+ }
46
+
47
+ export interface TextMessageEndEvent extends AGUIEvent {
48
+ type: 'TEXT_MESSAGE_END';
49
+ messageId: string;
50
+ }
51
+
52
+ export interface ToolCallStartEvent extends AGUIEvent {
53
+ type: 'TOOL_CALL_START';
54
+ toolCallId: string;
55
+ toolCallName: string;
56
+ }
57
+
58
+ export interface ToolCallArgsEvent extends AGUIEvent {
59
+ type: 'TOOL_CALL_ARGS';
60
+ toolCallId: string;
61
+ delta: string;
62
+ }
63
+
64
+ export interface ToolCallEndEvent extends AGUIEvent {
65
+ type: 'TOOL_CALL_END';
66
+ toolCallId: string;
67
+ }
68
+
69
+ export interface StateSnapshotEvent extends AGUIEvent {
70
+ type: 'STATE_SNAPSHOT';
71
+ snapshot: Record<string, any>;
72
+ }
73
+
74
+ export interface StateDeltaEvent extends AGUIEvent {
75
+ type: 'STATE_DELTA';
76
+ delta: any[]; // JSON Patch (RFC 6902)
77
+ }
78
+
79
+ export interface MessagesSnapshotEvent extends AGUIEvent {
80
+ type: 'MESSAGES_SNAPSHOT';
81
+ messages: AGUIMessage[];
82
+ }
83
+
84
+ export interface RunStartedEvent extends AGUIEvent {
85
+ type: 'RUN_STARTED';
86
+ runId: string;
87
+ threadId?: string;
88
+ }
89
+
90
+ export interface RunFinishedEvent extends AGUIEvent {
91
+ type: 'RUN_FINISHED';
92
+ runId: string;
93
+ }
94
+
95
+ export interface RunErrorEvent extends AGUIEvent {
96
+ type: 'RUN_ERROR';
97
+ runId: string;
98
+ message: string;
99
+ code?: string;
100
+ }
101
+
102
+ export interface StepStartedEvent extends AGUIEvent {
103
+ type: 'STEP_STARTED';
104
+ stepId: string;
105
+ stepName?: string;
106
+ }
107
+
108
+ export interface StepFinishedEvent extends AGUIEvent {
109
+ type: 'STEP_FINISHED';
110
+ stepId: string;
111
+ }
112
+
113
+ export interface CustomEvent extends AGUIEvent {
114
+ type: 'CUSTOM';
115
+ name: string;
116
+ value: any;
117
+ }
118
+
119
+ // ─── Message & Request Types ─────────────────────────────────
120
+
121
+ export interface AGUIMessage {
122
+ id: string;
123
+ role: 'user' | 'assistant' | 'system' | 'tool';
124
+ content: string;
125
+ name?: string;
126
+ toolCallId?: string;
127
+ toolCalls?: AGUIToolCall[];
128
+ }
129
+
130
+ export interface AGUIToolCall {
131
+ id: string;
132
+ type: 'function';
133
+ function: { name: string; arguments: string };
134
+ }
135
+
136
+ export interface AGUIRunRequest {
137
+ threadId?: string;
138
+ runId?: string;
139
+ messages: AGUIMessage[];
140
+ tools?: AGUIToolDefinition[];
141
+ context?: any[];
142
+ forwardedProps?: Record<string, any>;
143
+ }
144
+
145
+ export interface AGUIToolDefinition {
146
+ name: string;
147
+ description: string;
148
+ parameters: Record<string, any>; // JSON Schema
149
+ }
150
+
151
+ export function isValidEventType(type: string): type is AGUIEventType {
152
+ return AGUI_EVENT_TYPES.includes(type as AGUIEventType);
153
+ }
@@ -0,0 +1,2 @@
1
+ // Protocols barrel export
2
+ export * from './agui';
@@ -0,0 +1,134 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import type { MCPServerToolDefinition, MCPResourceDefinition } from './types';
4
+
5
+ /**
6
+ * Convert an OPC agent into MCP tool definitions.
7
+ * Works with any agent-like object that has name/handleMessage/brain.
8
+ */
9
+ export function agentToMCPTools(agent: any): MCPServerToolDefinition[] {
10
+ const tools: MCPServerToolDefinition[] = [];
11
+ const agentName = agent?.name || agent?.config?.name || 'agent';
12
+
13
+ // 1. Chat tool
14
+ tools.push({
15
+ name: 'chat',
16
+ description: `Chat with ${agentName} agent`,
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: { message: { type: 'string', description: 'Message to send to the agent' } },
20
+ required: ['message'],
21
+ },
22
+ handler: async (args: any) => {
23
+ if (typeof agent.handleMessage === 'function') {
24
+ const result = await agent.handleMessage({
25
+ role: 'user', content: args.message, channel: 'mcp',
26
+ });
27
+ return typeof result === 'string' ? result : result?.content || JSON.stringify(result);
28
+ }
29
+ return `Agent ${agentName} does not support handleMessage`;
30
+ },
31
+ });
32
+
33
+ // 2. Memory search
34
+ tools.push({
35
+ name: 'memory_search',
36
+ description: 'Search agent memory/knowledge',
37
+ inputSchema: {
38
+ type: 'object',
39
+ properties: { query: { type: 'string', description: 'Search query' } },
40
+ required: ['query'],
41
+ },
42
+ handler: async (args: any) => {
43
+ const brain = agent.brain || agent.memory || agent.memoryStore;
44
+ if (brain && typeof brain.query === 'function') {
45
+ return await brain.query(args.query);
46
+ }
47
+ if (brain && typeof brain.search === 'function') {
48
+ return await brain.search(args.query);
49
+ }
50
+ return 'Memory search not available';
51
+ },
52
+ });
53
+
54
+ // 3. Memory store
55
+ tools.push({
56
+ name: 'memory_store',
57
+ description: 'Store knowledge in agent memory',
58
+ inputSchema: {
59
+ type: 'object',
60
+ properties: {
61
+ slug: { type: 'string', description: 'Identifier/key for the memory entry' },
62
+ content: { type: 'string', description: 'Content to store' },
63
+ },
64
+ required: ['slug', 'content'],
65
+ },
66
+ handler: async (args: any) => {
67
+ const brain = agent.brain || agent.memory || agent.memoryStore;
68
+ if (brain && typeof brain.put === 'function') {
69
+ await brain.put(args.slug, args.content);
70
+ return `Stored: ${args.slug}`;
71
+ }
72
+ if (brain && typeof brain.store === 'function') {
73
+ await brain.store(args.slug, args.content);
74
+ return `Stored: ${args.slug}`;
75
+ }
76
+ return 'Memory store not available';
77
+ },
78
+ });
79
+
80
+ // 4. Expose agent skills as individual tools
81
+ const skills = agent.skills || agent.skillRegistry?.list?.() || [];
82
+ for (const skill of Array.isArray(skills) ? skills : []) {
83
+ const skillName = skill.name || skill.id;
84
+ if (!skillName) continue;
85
+ tools.push({
86
+ name: `skill_${skillName}`,
87
+ description: skill.description || `Execute ${skillName} skill`,
88
+ inputSchema: skill.inputSchema || {
89
+ type: 'object',
90
+ properties: { input: { type: 'string' } },
91
+ required: ['input'],
92
+ },
93
+ handler: async (args: any) => {
94
+ if (typeof skill.execute === 'function') {
95
+ return await skill.execute(args);
96
+ }
97
+ return `Skill ${skillName} not executable`;
98
+ },
99
+ });
100
+ }
101
+
102
+ return tools;
103
+ }
104
+
105
+ /**
106
+ * Expose agent files and brain pages as MCP resources.
107
+ */
108
+ export function agentToMCPResources(agent: any, agentDir: string): MCPResourceDefinition[] {
109
+ const resources: MCPResourceDefinition[] = [];
110
+
111
+ // Standard agent files
112
+ const standardFiles = [
113
+ { name: 'SOUL.md', desc: 'Agent personality and identity' },
114
+ { name: 'CONTEXT.md', desc: 'Agent context' },
115
+ { name: 'AGENTS.md', desc: 'Agent instructions' },
116
+ { name: 'USER.md', desc: 'User profile' },
117
+ { name: 'agent.yaml', desc: 'Agent OAD configuration' },
118
+ ];
119
+
120
+ for (const file of standardFiles) {
121
+ const filePath = join(agentDir, file.name);
122
+ if (existsSync(filePath)) {
123
+ resources.push({
124
+ uri: `agent:///${file.name}`,
125
+ name: file.name,
126
+ description: file.desc,
127
+ mimeType: file.name.endsWith('.yaml') ? 'text/yaml' : 'text/markdown',
128
+ handler: async () => readFileSync(filePath, 'utf-8'),
129
+ });
130
+ }
131
+ }
132
+
133
+ return resources;
134
+ }
@@ -0,0 +1,8 @@
1
+ export type {
2
+ MCPServerConfig, MCPServerToolDefinition, MCPResourceDefinition,
3
+ MCPPromptDefinition, MCPPromptArgument, MCPPromptMessage,
4
+ JsonRpcRequest, JsonRpcResponse,
5
+ } from './types';
6
+ export { MCP_ERRORS } from './types';
7
+ export { MCPServer } from './server';
8
+ export { agentToMCPTools, agentToMCPResources } from './agent-tools';