openbot 0.2.12 → 0.2.14

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 (141) hide show
  1. package/.prettierrc +8 -0
  2. package/AGENTS.md +68 -0
  3. package/CONTRIBUTING.md +74 -0
  4. package/LICENSE +21 -0
  5. package/README.md +117 -14
  6. package/dist/agents/system.js +106 -0
  7. package/dist/app/cli.js +27 -0
  8. package/dist/app/config.js +64 -0
  9. package/dist/app/server.js +237 -0
  10. package/dist/app/utils.js +35 -0
  11. package/dist/harness/agent-harness.js +45 -0
  12. package/dist/harness/mcp.js +61 -0
  13. package/dist/harness/orchestrator.js +273 -0
  14. package/dist/harness/process.js +7 -0
  15. package/dist/plugins/ai-sdk.js +141 -0
  16. package/dist/plugins/delegation.js +52 -0
  17. package/dist/plugins/mcp.js +140 -0
  18. package/dist/plugins/storage.js +502 -0
  19. package/dist/plugins/ui.js +47 -0
  20. package/dist/registry/plugins.js +73 -0
  21. package/dist/services/storage.js +724 -0
  22. package/docs/README.md +7 -0
  23. package/docs/agents.md +83 -0
  24. package/docs/architecture.md +34 -0
  25. package/docs/plugins.md +77 -0
  26. package/logo-black.png +0 -0
  27. package/{dist/assets/logo.js → logo-black.svg} +24 -24
  28. package/{dist/ui/sidebar.js → logo-white.svg} +23 -88
  29. package/package.json +6 -5
  30. package/src/agents/system.ts +112 -0
  31. package/src/app/cli.ts +38 -0
  32. package/src/app/config.ts +104 -0
  33. package/src/app/server.ts +284 -0
  34. package/src/app/types.ts +476 -0
  35. package/src/app/utils.ts +43 -0
  36. package/src/assets/icon.svg +1 -0
  37. package/src/harness/agent-harness.ts +58 -0
  38. package/src/harness/mcp.ts +78 -0
  39. package/src/harness/orchestrator.ts +342 -0
  40. package/src/harness/process.ts +9 -0
  41. package/src/harness/types.ts +34 -0
  42. package/src/plugins/ai-sdk.ts +197 -0
  43. package/src/plugins/delegation.ts +60 -0
  44. package/src/plugins/mcp.ts +154 -0
  45. package/src/plugins/storage.ts +725 -0
  46. package/src/plugins/ui.ts +57 -0
  47. package/src/registry/plugins.ts +85 -0
  48. package/src/services/storage.ts +957 -0
  49. package/tsconfig.json +18 -0
  50. package/dist/agents/agent-creator.js +0 -74
  51. package/dist/agents/browser-agent.js +0 -31
  52. package/dist/agents/os-agent.js +0 -32
  53. package/dist/agents/planner-agent.js +0 -32
  54. package/dist/agents/topic-agent.js +0 -46
  55. package/dist/architecture/execution-engine.js +0 -151
  56. package/dist/architecture/intent-classifier.js +0 -26
  57. package/dist/architecture/planner.js +0 -106
  58. package/dist/automation-worker.js +0 -121
  59. package/dist/automations.js +0 -52
  60. package/dist/cli.js +0 -279
  61. package/dist/config.js +0 -53
  62. package/dist/core/agents.js +0 -41
  63. package/dist/core/delegation.js +0 -230
  64. package/dist/core/manager.js +0 -96
  65. package/dist/core/plugins.js +0 -74
  66. package/dist/core/router.js +0 -191
  67. package/dist/handlers/init.js +0 -29
  68. package/dist/handlers/session-change.js +0 -21
  69. package/dist/handlers/settings.js +0 -47
  70. package/dist/handlers/tab-change.js +0 -14
  71. package/dist/installers.js +0 -156
  72. package/dist/marketplace.js +0 -80
  73. package/dist/model-catalog.js +0 -132
  74. package/dist/model-defaults.js +0 -25
  75. package/dist/models.js +0 -47
  76. package/dist/open-bot.js +0 -51
  77. package/dist/orchestrator/direct-invocation.js +0 -13
  78. package/dist/orchestrator/events.js +0 -36
  79. package/dist/orchestrator/state.js +0 -54
  80. package/dist/orchestrator.js +0 -422
  81. package/dist/plugins/agent/index.js +0 -81
  82. package/dist/plugins/approval/index.js +0 -100
  83. package/dist/plugins/brain/identity.js +0 -77
  84. package/dist/plugins/brain/index.js +0 -204
  85. package/dist/plugins/brain/memory.js +0 -120
  86. package/dist/plugins/brain/prompt.js +0 -46
  87. package/dist/plugins/brain/types.js +0 -45
  88. package/dist/plugins/brain/ui.js +0 -7
  89. package/dist/plugins/browser/index.js +0 -629
  90. package/dist/plugins/browser/ui.js +0 -13
  91. package/dist/plugins/file-system/index.js +0 -171
  92. package/dist/plugins/file-system/ui.js +0 -6
  93. package/dist/plugins/llm/context-budget.js +0 -139
  94. package/dist/plugins/llm/context-shaping.js +0 -177
  95. package/dist/plugins/llm/index.js +0 -380
  96. package/dist/plugins/memory/index.js +0 -220
  97. package/dist/plugins/memory/memory.js +0 -122
  98. package/dist/plugins/memory/prompt.js +0 -55
  99. package/dist/plugins/memory/types.js +0 -45
  100. package/dist/plugins/meta-agent/index.js +0 -570
  101. package/dist/plugins/meta-agent/ui.js +0 -11
  102. package/dist/plugins/shell/index.js +0 -100
  103. package/dist/plugins/shell/ui.js +0 -6
  104. package/dist/plugins/skills/index.js +0 -286
  105. package/dist/plugins/skills/types.js +0 -50
  106. package/dist/plugins/skills/ui.js +0 -12
  107. package/dist/registry/agent-registry.js +0 -35
  108. package/dist/registry/index.js +0 -2
  109. package/dist/registry/plugin-loader.js +0 -499
  110. package/dist/registry/plugin-registry.js +0 -44
  111. package/dist/registry/ts-agent-loader.js +0 -82
  112. package/dist/registry/yaml-agent-loader.js +0 -246
  113. package/dist/runtime/execution-trace.js +0 -41
  114. package/dist/runtime/intent-routing.js +0 -26
  115. package/dist/runtime/openbot-runtime.js +0 -354
  116. package/dist/server.js +0 -890
  117. package/dist/session.js +0 -179
  118. package/dist/ui/block.js +0 -12
  119. package/dist/ui/header.js +0 -52
  120. package/dist/ui/layout.js +0 -26
  121. package/dist/ui/navigation.js +0 -15
  122. package/dist/ui/settings.js +0 -106
  123. package/dist/ui/skills.js +0 -7
  124. package/dist/ui/thread.js +0 -16
  125. package/dist/ui/widgets/action-list.js +0 -2
  126. package/dist/ui/widgets/approval-card.js +0 -9
  127. package/dist/ui/widgets/code-snippet.js +0 -2
  128. package/dist/ui/widgets/data-block.js +0 -2
  129. package/dist/ui/widgets/data-table.js +0 -2
  130. package/dist/ui/widgets/delegation.js +0 -29
  131. package/dist/ui/widgets/empty-state.js +0 -2
  132. package/dist/ui/widgets/index.js +0 -23
  133. package/dist/ui/widgets/inquiry.js +0 -7
  134. package/dist/ui/widgets/key-value.js +0 -2
  135. package/dist/ui/widgets/progress-step.js +0 -2
  136. package/dist/ui/widgets/resource-card.js +0 -2
  137. package/dist/ui/widgets/status.js +0 -2
  138. package/dist/ui/widgets/todo-list.js +0 -2
  139. package/dist/version.js +0 -62
  140. /package/dist/{types.js → app/types.js} +0 -0
  141. /package/dist/{architecture/contracts.js → harness/types.js} +0 -0
@@ -0,0 +1,476 @@
1
+ import {
2
+ Agent,
3
+ AgentDetails,
4
+ Channel,
5
+ ChannelDetails,
6
+ Plugin,
7
+ Thread,
8
+ ThreadDetails,
9
+ } from '../plugins/storage.js';
10
+
11
+ export interface OpenBotState {
12
+ agentId: string;
13
+ runId: string;
14
+ channelId: string;
15
+ threadId?: string;
16
+ agentDetails?: AgentDetails;
17
+ channelDetails?: ChannelDetails;
18
+ threadDetails?: ThreadDetails;
19
+ triggerEvent?: OpenBotEvent;
20
+ shortTermMessages?: ShortTermMessage[];
21
+ }
22
+
23
+ export type ShortTermMessage = {
24
+ role: 'user' | 'assistant' | 'system';
25
+ content: string;
26
+ };
27
+
28
+ export type BaseEvent = {
29
+ id?: string;
30
+ type: string;
31
+ meta?: any;
32
+ };
33
+
34
+ export type AgentInvokeEvent = BaseEvent & {
35
+ type: 'agent:invoke';
36
+ data: {
37
+ role?: 'user' | 'assistant' | 'system';
38
+ content: string;
39
+ agentId?: string;
40
+ };
41
+ };
42
+
43
+ export type GetChannelsEvent = BaseEvent & {
44
+ type: 'action:storage:get-channels';
45
+ };
46
+
47
+ export type GetChannelsResultEvent = BaseEvent & {
48
+ type: 'action:storage:get-channels-result';
49
+ data: {
50
+ channels: Channel[];
51
+ };
52
+ };
53
+
54
+ export type GetThreadsEvent = BaseEvent & {
55
+ type: 'action:storage:get-threads';
56
+ data: {
57
+ channelId: string;
58
+ };
59
+ };
60
+
61
+ export type GetThreadsResultEvent = BaseEvent & {
62
+ type: 'action:storage:get-threads-result';
63
+ data: {
64
+ threads: Thread[];
65
+ };
66
+ };
67
+
68
+ export type GetChannelDetailsEvent = BaseEvent & {
69
+ type: 'action:storage:get-channel-details';
70
+ };
71
+
72
+ export type GetChannelDetailsResultEvent = BaseEvent & {
73
+ type: 'action:storage:get-channel-details-result';
74
+ data: {
75
+ channelDetails: ChannelDetails;
76
+ };
77
+ };
78
+
79
+ export type GetAgentsEvent = BaseEvent & {
80
+ type: 'action:storage:get-agents';
81
+ };
82
+
83
+ export type GetAgentsResultEvent = BaseEvent & {
84
+ type: 'action:storage:get-agents-result';
85
+ data: {
86
+ agents: Agent[];
87
+ };
88
+ };
89
+
90
+ export type GetPluginsEvent = BaseEvent & {
91
+ type: 'action:storage:get-plugins';
92
+ };
93
+
94
+ export type GetPluginsResultEvent = BaseEvent & {
95
+ type: 'action:storage:get-plugins-result';
96
+ data: {
97
+ plugins: Plugin[];
98
+ };
99
+ };
100
+
101
+ export type GetEventsEvent = BaseEvent & {
102
+ type: 'action:storage:get-events';
103
+ };
104
+
105
+ export type GetEventsResultEvent = BaseEvent & {
106
+ type: 'action:storage:get-events-result';
107
+ data: {
108
+ events: OpenBotEvent[];
109
+ };
110
+ };
111
+
112
+ export type GetAgentDetailsEvent = BaseEvent & {
113
+ type: 'action:storage:get-agent-details';
114
+ data: {
115
+ agentId: string;
116
+ };
117
+ };
118
+
119
+ export type GetAgentDetailsResultEvent = BaseEvent & {
120
+ type: 'action:storage:get-agent-details-result';
121
+ data: {
122
+ agentDetails: AgentDetails;
123
+ };
124
+ };
125
+
126
+ export type StreamThreadEvent = BaseEvent & {
127
+ type: 'stream:thread';
128
+ data: {
129
+ channelId: string;
130
+ threadId?: string;
131
+ };
132
+ };
133
+
134
+ export type GetVariablesEvent = BaseEvent & {
135
+ type: 'action:storage:get-variables';
136
+ };
137
+
138
+ export type GetVariablesResultEvent = BaseEvent & {
139
+ type: 'action:storage:get-variables-result';
140
+ data: {
141
+ variables: Record<string, string | { value: string; secret: boolean }>;
142
+ };
143
+ };
144
+
145
+ export type PatchChannelStateEvent = BaseEvent & {
146
+ type: 'action:storage:patch-channel-state';
147
+ data: {
148
+ state: unknown;
149
+ };
150
+ };
151
+
152
+ export type PatchChannelStateResultEvent = BaseEvent & {
153
+ type: 'action:storage:patch-channel-state-result';
154
+ data: {
155
+ success: boolean;
156
+ };
157
+ };
158
+
159
+ export type PatchThreadStateEvent = BaseEvent & {
160
+ type: 'action:storage:patch-thread-state';
161
+ data: {
162
+ state: unknown;
163
+ };
164
+ };
165
+
166
+ export type PatchThreadStateResultEvent = BaseEvent & {
167
+ type: 'action:storage:patch-thread-state-result';
168
+ data: {
169
+ success: boolean;
170
+ };
171
+ };
172
+
173
+ export type PatchChannelDetailsEvent = BaseEvent & {
174
+ type: 'action:patch_channel_details';
175
+ data: {
176
+ state?: Record<string, unknown>;
177
+ spec?: string;
178
+ cwd?: string;
179
+ };
180
+ };
181
+
182
+ export type PatchChannelDetailsResultEvent = BaseEvent & {
183
+ type: 'action:patch_channel_details:result';
184
+ data: {
185
+ success: boolean;
186
+ updatedFields: ('state' | 'spec' | 'cwd')[];
187
+ };
188
+ };
189
+
190
+ export type PatchThreadDetailsEvent = BaseEvent & {
191
+ type: 'action:patch_thread_details';
192
+ data: {
193
+ state?: Record<string, unknown>;
194
+ spec?: string;
195
+ };
196
+ };
197
+
198
+ export type PatchThreadDetailsResultEvent = BaseEvent & {
199
+ type: 'action:patch_thread_details:result';
200
+ data: {
201
+ success: boolean;
202
+ updatedFields: ('state' | 'spec')[];
203
+ };
204
+ };
205
+
206
+ export type ListFilesEvent = BaseEvent & {
207
+ type: 'action:storage:list-files';
208
+ data: {
209
+ path?: string;
210
+ };
211
+ };
212
+
213
+ export type ListFilesResultEvent = BaseEvent & {
214
+ type: 'action:storage:list-files:result';
215
+ data: {
216
+ success: boolean;
217
+ files: Array<{ name: string; isDirectory: boolean }>;
218
+ error?: string;
219
+ };
220
+ };
221
+
222
+ export type ReadFileEvent = BaseEvent & {
223
+ type: 'action:storage:read-file';
224
+ data: {
225
+ path: string;
226
+ };
227
+ };
228
+
229
+ export type ReadFileResultEvent = BaseEvent & {
230
+ type: 'action:storage:read-file:result';
231
+ data: {
232
+ success: boolean;
233
+ content?: string;
234
+ path: string;
235
+ error?: string;
236
+ };
237
+ };
238
+
239
+ export type AgentOutputEvent = BaseEvent & {
240
+ type: 'agent:output';
241
+ data: {
242
+ content: string;
243
+ };
244
+ meta: {
245
+ agentId: string;
246
+ [key: string]: any;
247
+ };
248
+ };
249
+
250
+ export type AgentRunStartEvent = BaseEvent & {
251
+ type: 'agent:run:start';
252
+ data: {
253
+ runId: string;
254
+ agentId: string;
255
+ channelId: string;
256
+ threadId?: string;
257
+ };
258
+ };
259
+
260
+ export type AgentRunEndEvent = BaseEvent & {
261
+ type: 'agent:run:end';
262
+ data: {
263
+ runId: string;
264
+ agentId: string;
265
+ channelId: string;
266
+ threadId?: string;
267
+ };
268
+ };
269
+
270
+ export type ActiveRunsSnapshotEvent = BaseEvent & {
271
+ type: 'agent:active-runs:snapshot';
272
+ data: {
273
+ channels: Array<{
274
+ channelId: string;
275
+ activeCount: number;
276
+ agentIds: string[];
277
+ }>;
278
+ };
279
+ };
280
+
281
+ export type CreateThreadEvent = BaseEvent & {
282
+ type: 'action:create_thread';
283
+ data: {
284
+ threadTitle: string;
285
+ spec?: string;
286
+ initialState?: Record<string, unknown>;
287
+ };
288
+ meta: {
289
+ toolCallId: string;
290
+ agentId: string;
291
+ threadId: string;
292
+ };
293
+ };
294
+
295
+ export type CreateThreadResultEvent = BaseEvent & {
296
+ type: 'action:create_thread:result';
297
+ data: {
298
+ success: boolean;
299
+ threadId: string;
300
+ threadTitle: string;
301
+ };
302
+ meta: {
303
+ threadId: string;
304
+ };
305
+ };
306
+
307
+ export type CreateChannelEvent = BaseEvent & {
308
+ type: 'action:create_channel';
309
+ data: {
310
+ channelId: string;
311
+ spec?: string;
312
+ initialState?: Record<string, unknown>;
313
+ cwd?: string;
314
+ };
315
+ meta?: {
316
+ toolCallId?: string;
317
+ agentId?: string;
318
+ threadId?: string;
319
+ };
320
+ };
321
+
322
+ export type CreateChannelResultEvent = BaseEvent & {
323
+ type: 'action:create_channel:result';
324
+ data: {
325
+ success: boolean;
326
+ channelId: string;
327
+ channelUrl: string;
328
+ };
329
+ };
330
+
331
+ export type UpdateChannelEvent = BaseEvent & {
332
+ type: 'action:update_channel';
333
+ data: {
334
+ channelId?: string;
335
+ name?: string;
336
+ cwd?: string;
337
+ };
338
+ };
339
+
340
+ export type UpdateChannelResultEvent = BaseEvent & {
341
+ type: 'action:update_channel:result';
342
+ data: {
343
+ success: boolean;
344
+ channelId: string;
345
+ updatedFields: string[];
346
+ };
347
+ };
348
+
349
+ export type UIWidgetEvent = BaseEvent & {
350
+ type: 'client:ui:widget';
351
+ data: {
352
+ widgetId: string;
353
+ kind: 'approval' | 'todo_list' | 'form';
354
+ title?: string;
355
+ props: Record<string, unknown>;
356
+ };
357
+ };
358
+
359
+ export type RenderUIWidgetEvent = BaseEvent & {
360
+ type: 'action:render_ui_widget';
361
+ data: {
362
+ kind: 'approval' | 'todo_list' | 'form';
363
+ title?: string;
364
+ props: Record<string, unknown>;
365
+ };
366
+ };
367
+
368
+ export type DelegateEvent = BaseEvent & {
369
+ type: 'action:delegate';
370
+ data: {
371
+ agentId: string;
372
+ content: string;
373
+ };
374
+ meta: {
375
+ toolCallId: string;
376
+ };
377
+ };
378
+
379
+ export type MCPListToolsEvent = BaseEvent & {
380
+ type: 'action:mcp_list_tools';
381
+ data: {
382
+ serverId: string;
383
+ };
384
+ };
385
+
386
+ export type MCPListToolsResultEvent = BaseEvent & {
387
+ type: 'action:mcp_list_tools:result';
388
+ data: {
389
+ success: boolean;
390
+ serverId: string;
391
+ tools: Array<{ name: string; description?: string; inputSchema?: unknown }>;
392
+ error?: string;
393
+ };
394
+ };
395
+
396
+ export type MCPCallEvent = BaseEvent & {
397
+ type: 'action:mcp_call';
398
+ data: {
399
+ serverId: string;
400
+ toolName: string;
401
+ args?: Record<string, unknown>;
402
+ };
403
+ };
404
+
405
+ export type MCPCallResultEvent = BaseEvent & {
406
+ type: 'action:mcp_call:result';
407
+ data: {
408
+ success: boolean;
409
+ serverId: string;
410
+ toolName: string;
411
+ result?: unknown;
412
+ error?: string;
413
+ };
414
+ };
415
+
416
+ export type UserInputEvent = BaseEvent & {
417
+ type: 'user:input';
418
+ data: {
419
+ content: string;
420
+ };
421
+ meta?: {
422
+ userId?: string;
423
+ userName?: string;
424
+ userAvatarUrl?: string;
425
+ };
426
+ };
427
+
428
+ export type OpenBotEvent =
429
+ | UserInputEvent
430
+ | AgentInvokeEvent
431
+ | AgentOutputEvent
432
+ | AgentRunStartEvent
433
+ | AgentRunEndEvent
434
+ | ActiveRunsSnapshotEvent
435
+ | GetChannelsEvent
436
+ | GetChannelsResultEvent
437
+ | GetThreadsEvent
438
+ | GetThreadsResultEvent
439
+ | GetChannelDetailsEvent
440
+ | GetChannelDetailsResultEvent
441
+ | GetAgentsEvent
442
+ | GetAgentsResultEvent
443
+ | GetPluginsEvent
444
+ | GetPluginsResultEvent
445
+ | GetAgentDetailsEvent
446
+ | GetAgentDetailsResultEvent
447
+ | GetEventsEvent
448
+ | GetEventsResultEvent
449
+ | StreamThreadEvent
450
+ | GetVariablesEvent
451
+ | GetVariablesResultEvent
452
+ | PatchChannelStateEvent
453
+ | PatchChannelStateResultEvent
454
+ | PatchThreadStateEvent
455
+ | PatchThreadStateResultEvent
456
+ | PatchChannelDetailsEvent
457
+ | PatchChannelDetailsResultEvent
458
+ | PatchThreadDetailsEvent
459
+ | PatchThreadDetailsResultEvent
460
+ | ListFilesEvent
461
+ | ListFilesResultEvent
462
+ | ReadFileEvent
463
+ | ReadFileResultEvent
464
+ | CreateThreadEvent
465
+ | CreateThreadResultEvent
466
+ | CreateChannelEvent
467
+ | CreateChannelResultEvent
468
+ | UpdateChannelEvent
469
+ | UpdateChannelResultEvent
470
+ | UIWidgetEvent
471
+ | RenderUIWidgetEvent
472
+ | DelegateEvent
473
+ | MCPListToolsEvent
474
+ | MCPListToolsResultEvent
475
+ | MCPCallEvent
476
+ | MCPCallResultEvent;
@@ -0,0 +1,43 @@
1
+ import express from 'express';
2
+ import crypto from 'node:crypto';
3
+ import { OpenBotEvent } from './types.js';
4
+
5
+ /** Express query values are always strings; parse JSON `data` for typed events. */
6
+ export function openBotEventFromQuery(query: express.Request['query']): OpenBotEvent {
7
+ const typeRaw = query.type;
8
+ const type =
9
+ typeof typeRaw === 'string'
10
+ ? typeRaw
11
+ : Array.isArray(typeRaw) && typeof typeRaw[0] === 'string'
12
+ ? typeRaw[0]
13
+ : '';
14
+
15
+ const dataRaw = query.data;
16
+ const dataStr =
17
+ typeof dataRaw === 'string'
18
+ ? dataRaw
19
+ : Array.isArray(dataRaw) && typeof dataRaw[0] === 'string'
20
+ ? dataRaw[0]
21
+ : undefined;
22
+
23
+ if (dataStr === undefined || dataStr.trim() === '') {
24
+ return { type } as OpenBotEvent;
25
+ }
26
+
27
+ try {
28
+ const data = JSON.parse(dataStr) as unknown;
29
+ return { type, data } as OpenBotEvent;
30
+ } catch {
31
+ throw new Error('Query parameter "data" must be valid JSON when provided');
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Ensures the event has a unique ID.
37
+ */
38
+ export function ensureEventId(event: OpenBotEvent): OpenBotEvent {
39
+ if (!event.id) {
40
+ event.id = crypto.randomUUID();
41
+ }
42
+ return event;
43
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 762 762" fill="none" shape-rendering="auto"><metadata xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/"><rdf:RDF><rdf:Description><dc:title>Adventurer</dc:title><dc:creator>Lisa Wischofsky</dc:creator><dc:source xsi:type="dcterms:URI">https://www.figma.com/community/file/1184595184137881796</dc:source><dcterms:license xsi:type="dcterms:URI">https://creativecommons.org/licenses/by/4.0/</dcterms:license><dc:rights>Remix of „Adventurer” (https://www.figma.com/community/file/1184595184137881796) by „Lisa Wischofsky”, licensed under „CC BY 4.0” (https://creativecommons.org/licenses/by/4.0/)</dc:rights></rdf:Description></rdf:RDF></metadata><mask id="viewboxMask"><rect width="762" height="762" rx="0" ry="0" x="0" y="0" fill="#fff" /></mask><g mask="url(#viewboxMask)"><path d="M396 164.8a224.8 224.8 0 0 1 104.8 42.4c6.2 4.9 12.5 9.4 18 15a225.4 225.4 0 0 1 71.8 149 58.5 58.5 0 0 1 50.9 42.2 71 71 0 0 1-27.6 76.5c-11 7.7-24.5 12-38 11.7-5 0-10-1.6-15-1.8-1.9 2.2-3.3 4.9-4.8 7.3A223.3 223.3 0 0 1 389 609.8c-11 .7-21.9 2-33 .7a223.7 223.7 0 0 1-178.8-342.3A223.4 223.4 0 0 1 352 163.5c14.6-1.4 29.4-.3 44 1.3Z" fill="#000"/><path fill-rule="evenodd" clip-rule="evenodd" d="M498.8 213.2A216 216 0 0 0 363 169c-13-.2-26.2 1.6-39 4a218 218 0 0 0-113.6 365.5 218.5 218.5 0 0 0 260.4 40.2c35-18.8 64.2-47.3 84.4-81.5l-3-1.6c-2.8-1.4-5.7-3-8-5-2.2-2-.3-5.8 2.7-4.7 1.5.7 3 1.6 4.4 2.4a55 55 0 0 0 59.6-3.6 64.5 64.5 0 0 0 25-69.8 53.1 53.1 0 0 0-24-31 52.6 52.6 0 0 0-47-2.8c-1.6.8-3.4 1.5-5 1.3-2.5-.2-2.8-4.2-.6-5.2 8-4 16.5-5.6 25.4-6.4a217 217 0 0 0-72-146.4c-4.4-4-8.7-8.1-13.9-11.3Zm107.6 196.2c2-1.2 1.3-5.1-1.4-5-2 0-4.2.8-6.2 1.6l-1.4.4a95.1 95.1 0 0 0-25.5 12.4c-2.2 2-2.2 4.4.1 6.2a92 92 0 0 0 5.2 2.8 36 36 0 0 1 13 9.2c-.2 1.9-2 3.4-3.4 4.5l-.2.2c-3.9 3-8.8 5-13.6 7-2.5 1-4.9 2-7.1 3.1-1.7.8-2.6 2.2-1.6 3.9 1 2 3.2 1.1 5 .5l.6-.2 5.4-2.3c5.4-2.3 11-4.5 15.4-8 2.7-2.1 5.1-5.1 5.4-8.7-.5-3.4-2.7-5.7-5.3-7.8a83 83 0 0 0-11.6-7.2l-1.1-.6c5.4-3 10.8-5.6 16.6-7.7l5-1.7a52 52 0 0 0 6.7-2.6Z" fill="#763900"/><g transform="translate(-161 -83)"><path d="M589.3 432.7a64.4 64.4 0 0 1 28.5 33.5 64.3 64.3 0 0 1 .5 45.1c-1 2.9-2.9 5.2-6.3 4.8-15-.8-30 .1-45 .5-10 1.1-20 2.2-30 3.8-10.5 1.8-20.6 4.1-31 6.1-4.3-.1-5.3-4.2-7.2-7.3A65.5 65.5 0 0 1 546 425c14.8-2.6 30.5.2 43.4 7.7Z" fill="#000"/><path d="M558 429.9a59.1 59.1 0 0 1 54.4 80.6l-3.2-.3a27 27 0 0 0 1.3-15.4 26.6 26.6 0 1 0-50 16.9 287 287 0 0 0-34 5.2c-6.7 1.2-13.4 3.2-20.1 4A59.8 59.8 0 0 1 517 445a59 59 0 0 1 41-15.1Z" fill="#fff"/><path d="M392 447a54.8 54.8 0 0 1 42.8 81.9c-1.1 1.9-2.9 4-5 4.7-3 .8-6.6-.2-9.6-.9-8.7-2-17.4-3.8-26.3-5.1-12.9-.9-26-1-39 0-4.7.4-9.7 1.4-14.5 1-2.3-1-3.7-4.2-4.6-6.4a54.9 54.9 0 0 1 56.2-75Z" fill="#000"/><path d="M401.5 454.7a49.3 49.3 0 0 1 26.7 74l-4.1-.7c4.1-4.4 7-9.8 6.8-16a22.6 22.6 0 0 0-43.7-8.8c-2.5 5.9-1.9 12 .4 18-7.6.2-15-.4-22.6.3-7.3.7-14.7 1.2-22 1.8l-1.9-3.4a49.2 49.2 0 0 1 60.4-65.2Z" fill="#fff"/></g><g transform="translate(-161 -83)"><path d="M531 352.3a85.8 85.8 0 0 1 60.6 15.1 82.9 82.9 0 0 1 29 33c1 3-.4 3.8-2.6 5.3-4-2.2-6.9-5.6-10.5-8.3-13-9.7-28-16.3-43.7-20.2-15-3.5-30.6-5-45.8-2.8-4.8.4-9.3 2-14 2.7-2.4.2-5.1-1.2-4.2-4 1.9-4.2 4.2-8.6 7.6-11.7a45 45 0 0 1 23.6-9ZM383 428.8c13.4-.8 26.3-.6 39 4.3 5.9 2.3 11.6 5.9 14 12a14 14 0 0 1-1.8 12.6c-4.9-.7-9.4-2.6-14.1-3.8a203 203 0 0 0-71-6c-5 .4-10 2-14.8 1.8-1.8-.5-1.2-2.2-1-3.5.9-2.5 3.6-3.9 5.8-5.1a119.2 119.2 0 0 1 43.9-12.3Z" fill="#000"/></g><g transform="translate(-161 -83)"><path d="m525 563.7 1.2 2.3c.4 2.7-2 3.4-3.8 4.4a184 184 0 0 1-85.8 17c-5-.6-10.2-.7-15-2-2.3-1-2.6-4-.3-5.2 2.7 0 5.5.9 8.2 1 7.2 1 14.3.7 21.5.7 22.5-.8 45-6.8 65.7-15.5 2.8-1.2 5.2-2.6 8.3-2.7Z" fill="#000"/></g><g transform="translate(-161 -83)"></g><g transform="translate(-161 -83)"></g><g transform="translate(-161 -83)"><path d="M754.9 186.1a94.7 94.7 0 0 1 29 52c5.3 43 5.3 86 11.8 128.9 4.5 31.8 10.7 66.1 25.5 94.9 10.3 20.5 21.8 40.5 31.8 61.1 8.6 17.7 14 37.3 14.8 57 .9 11.5.4 23.5-.6 34.9-2.2 18-7.9 36.3-17.5 51.8-7.5 12.2-19 21.4-30.6 29.5-1.3.8-2.5 2.8-4.1 2.6-2 0-3-2-2.5-3.8a95 95 0 0 0 6.5-69.1c-.3-1-.4-2.1-1.4-2.7-4.6 25.3-15 49.9-31.4 69.9-13.2 16-30 28.9-50.2 34.6a73.7 73.7 0 0 1-47-1.7c-1.6-1.7-4.5-3.3-3.3-6a68.1 68.1 0 0 0 16.8-32c-1.8.6-3.3 1.7-5 2.4a67.7 67.7 0 0 1-29.5 5.9c-9 0-19.3-2-26.3-8-1.8-1.6-4-3.2-3.3-5.9a69 69 0 0 0 12.8-32.3c.7-.9 1.9-1.4 2.8-2.1 26-18.2 47.3-42.2 63.5-69.5 1-2.3 3.4-2.8 5.6-2a55.2 55.2 0 0 0 41.4-4 64.8 64.8 0 0 0 34.3-65.5 55 55 0 0 0-19.8-36 50.2 50.2 0 0 0-55-6 123 123 0 0 1-4.6 32.1 123.4 123.4 0 0 1-35 58.3c-1.3 1-2.7 2.6-4.4 3.1-1.3.1-3.5-.9-3.5-2.5-.3-1.9 1.7-3.3 2.7-4.8a76.6 76.6 0 0 0 10-21.2c4.3-14 6-29.3 6.1-44-.3-26-5-52.4-16-76.1-.6-1.8-1.8-3.8-1-5.8 2-5 3-10.3 3.2-15.7-4.3 2.8-9 5.2-13.4 7.7-2.2 1.2-5.4 2.1-7.3 0-1.1-3.4-1-7.5-.7-11 .3-6.2.5-12.1 0-18.2-6.9 3.7-13.3 7.5-20.6 10.4-2.5 1-5.3 0-7.7-.9a83.6 83.6 0 0 1-29.2-23c-4.7-5.3-9-10.6-11.8-17.3-2.6-6-3.6-12.1-3.7-18.6-13.7 7.3-31 6.1-46.1 6.2-16 .3-32.2-.8-48 1.1-1.8.2-4.8-.8-4.9-2.9-.5-2.8 1.8-4.6 3.5-6.5-13.2 3.6-26.2 8.7-39 13-3.6.9-7 2.6-10.4.4-3.5-2.5-2.6-6.2-2.3-10-3 0-6 1.4-8.8 2.3a721.5 721.5 0 0 1-41 14.3c-9.5 2.9-19 5-29.1 4.8-4.8-.2-9.6.9-14 3a62.4 62.4 0 0 1-44.1-15 40.6 40.6 0 0 1-13-24.2 46 46 0 0 1 2-20 69.7 69.7 0 0 1 34.4-37.7c1.6-.8 3.9-2.4 5.7-1.4 1.7 1 2 3.4 1 5a49.6 49.6 0 0 0-5.8 57.9c4.4 7.3 10.9 14.2 19.5 16 2.6-15 10.8-29 20.5-40.6a205.6 205.6 0 0 1 49.4-41.6 297.1 297.1 0 0 1 114.9-41.3 176 176 0 0 1 66.5 2.6c17-22 42.5-37.2 70-41.6 30.7-5.4 63.9 3.6 86.9 24.8Z" fill="#000"/><g fill="#3eac2c"><path d="M681 165.9c28-1.7 56.2 9.2 75.2 29.9a88.5 88.5 0 0 1 21.6 42.3c.6 7 2 13.8 2.2 20.8 1.3 9.7 1.5 19.4 2.5 29.1 1.2 22.6 3.1 45.5 5.7 68 4 29 8 57.1 17.6 85 5.8 16.7 14.1 31.4 22.3 46.9 7.8 14.9 16.1 29.7 22.9 45.1 11.9 27.4 13.5 58.6 9.4 87.9a112.7 112.7 0 0 1-22.5 52c-4.5 5-9.7 9.9-15.2 13.7 4.3-12.3 6.3-25.6 5.7-38.6-.3-12.7-3.2-26-9.2-37.2-1.2-2.3-5.1-2-5.7.7-3.7 30-15.6 60.3-36.2 82.8a90 90 0 0 1-52.4 29.8 66.1 66.1 0 0 1-32.2-3c8.3-10.9 15.8-25.2 15.7-39.1.2-2.8-3.4-3.3-5.1-1.8a53.9 53.9 0 0 1-19.3 8.6 52.6 52.6 0 0 1-34.5-2.3c-1.2-.8-3.7-1.9-4.2-3.2a84.7 84.7 0 0 0 11.5-29.8c1.5-2 4.1-3 6-4.7a226.1 226.1 0 0 0 59-66.2c4.7.4 9.3 1.8 14.2 1.9a66 66 0 0 0 55-27.5 72.5 72.5 0 0 0 14.1-39 62.6 62.6 0 0 0-20.9-50 55 55 0 0 0 6.6-19c3.1-19.7.1-40.7-4.4-60a214.8 214.8 0 0 0-21-53.1c-3.6-15.1-8.4-29.8-15.8-43.5a138 138 0 0 0-55.4-56.6c-1.2-.7-2.5-.9-3.9-1.1a58.9 58.9 0 0 0-44.3-24.4c-5-.8-9.9 0-14.9 0-3.3-2.4-7-3.2-11-3.4-6.1-.5-11 1.8-16.6-1.5A104.6 104.6 0 0 1 681 166Z"/><path d="M594 208c1 .4 2.3.3 2.9 1.4-2.4.6-4.8 1.4-7 2.3a320.2 320.2 0 0 0-75.1 33.9c-8.2 5-16.1 10.6-23.5 16.7-1.5 1.3-1.6 3.3-.5 5 1.5.8 2.8.8 4.1-.4a254.2 254.2 0 0 1 46.6-29.4 268.6 268.6 0 0 1 61.6-23c6.4-1 13.5-2.5 20-1.3 2.2.4 4.2 1.7 6.4 2.4 3 1.2 6.2.2 9.5.2 4.3.1 8.8.3 13 1.2 12.5 2.2 24 9 32 19a91.5 91.5 0 0 1 17.3 44.1c1 7.6 1.8 15.2 1.6 22.9 0 2.2 0 5.7 3 5.5 2.2 0 3-1.6 3-3.5 0-21.1-3-41.8-12.4-61a127.4 127.4 0 0 1 36.4 33 156 156 0 0 1 27.8 66c4.7 25.5 4.3 52.4 1 78-.5 3.3-1.3 6.8-1.1 10.1 1.3 3 5.2 2.2 5.5-1 1.7-8.8 2.7-18 3.2-27.1 1.6-16.3.9-32.1-.8-48.3.3 2 1.4 3.6 2.2 5.4A202.3 202.3 0 0 1 786 428c.3 11.7-.6 25.3-6.3 35.8a57 57 0 0 0-56-5.3c-.6-1.6-.5-4.2-2.8-4.4-1.7-.3-3.4 1-3.3 2.9.3 6.6.5 13.4-.2 20a130.9 130.9 0 0 1-22.6 58l-1 .5c.2-2 .8-3.7 1.4-5.5 5-16.8 6.3-34.2 5.8-51.6-1.2-24.9-6.5-50.5-17.4-73.1 2.4-6 3-12 3.8-18.3.1-2 .5-4.1 0-6.1-1.2-2.4-4.1-1.8-5.7-.1-3.2 3-7 5.1-10.9 7-1.6.8-3.2 2.2-5 2.2 0-3.6.4-7.3.2-11 0-5.9.5-12.4-1-18-2.5-2.2-5-1-7.2.9-6.2 3.5-12.5 6.8-19 9.6-1.8.8-3.4.2-5-.4a78.2 78.2 0 0 1-24.8-19.2 64.7 64.7 0 0 1-13.4-19.4 39.7 39.7 0 0 1 2-33c1-1.6.5-4.1-1.7-4.4-2.7-.6-4 3-5 4.9-2 4.5-4 10.9-8.4 13.6-9.6 4-19.4 4.3-29.6 4.2h-48c-2.6.1-5.1.6-7.8.8 2-3 5.3-5 3.1-8.9-3.2-2-6.4-.7-9.8-.1-13.2 3.5-26 8.6-39 13-2 .6-4 1.4-6 1 .1-2.8 1.4-6.8-1-9-2-2.3-4.8-2-7.5-1.5-7 1.8-13.2 4.6-20 7-12.9 4.5-25.9 9.3-39.2 12.5-7.5 1.7-15.1 1.9-22.8 2-3.7 0-6.3 2.6-10 2.3a54 54 0 0 1-26-5c-9.7-4.3-17.9-11.9-21.6-22a37 37 0 0 1 1.2-27 62.3 62.3 0 0 1 22-26.4c-1.6 4-3.3 7.8-4.3 12-4.5 19 .4 40.8 15.1 54.1 5.2 3.6 10 7 16.6 7.1 2.3 0 3.8-1.3 4.2-3.5 3.4-20.6 18-39.2 32.8-53.2 26.2-24.4 59.4-42.1 93-53.9 13.1-4.4 26.4-8 40-10.7 24.7-4.5 51.4-6.2 76-.4Z"/></g></g><g transform="translate(-161 -83)"></g></g></svg>
@@ -0,0 +1,58 @@
1
+ import { Runtime } from 'melony';
2
+ import { OpenBotEvent, OpenBotState } from '../app/types.js';
3
+ import { Harness, HarnessOptions } from './types.js';
4
+ import { orchestratorService } from './orchestrator.js';
5
+ import { ensureEventId } from '../app/utils.js';
6
+
7
+ /**
8
+ * Standard implementation of the Agent Harness.
9
+ * It wraps the orchestrator logic into a clean, stateful container.
10
+ */
11
+ export class AgentHarness implements Harness {
12
+ public readonly runId: string;
13
+ public readonly agentId: string;
14
+ public readonly channelId: string;
15
+ public threadId?: string;
16
+ private eventCallbacks: ((event: OpenBotEvent, state: OpenBotState) => Promise<void>)[] = [];
17
+
18
+ constructor(options: HarnessOptions) {
19
+ this.runId = options.runId;
20
+ this.agentId = options.agentId;
21
+ this.channelId = options.channelId;
22
+ this.threadId = options.threadId;
23
+ if (options.onEvent) {
24
+ this.eventCallbacks.push(options.onEvent);
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Dispatches an event to the agent within this harness.
30
+ */
31
+ async dispatch(event: OpenBotEvent): Promise<void> {
32
+ ensureEventId(event);
33
+
34
+ await orchestratorService.dispatch({
35
+ runId: this.runId,
36
+ agentId: this.agentId,
37
+ event,
38
+ channelId: this.channelId,
39
+ threadId: this.threadId,
40
+ onEvent: async (chunk, state) => {
41
+ // Update internal thread state if it changes (e.g. thread creation)
42
+ if (chunk.type === 'action:create_thread:result' && chunk.data.success) {
43
+ this.threadId = chunk.data.threadId || this.threadId;
44
+ }
45
+
46
+ // Notify all observers
47
+ await Promise.all(this.eventCallbacks.map(cb => cb(chunk, state)));
48
+ }
49
+ });
50
+ }
51
+
52
+ /**
53
+ * Adds an event listener to the harness.
54
+ */
55
+ onEvent(callback: (event: OpenBotEvent, state: OpenBotState) => Promise<void>): void {
56
+ this.eventCallbacks.push(callback);
57
+ }
58
+ }
@@ -0,0 +1,78 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ import { loadConfig, type MCPServerConfig } from '../app/config.js';
4
+
5
+ type MCPToolSummary = {
6
+ name: string;
7
+ description?: string;
8
+ inputSchema?: unknown;
9
+ };
10
+
11
+ class MCPService {
12
+ private clients = new Map<string, Client>();
13
+
14
+ private transports = new Map<string, StdioClientTransport>();
15
+
16
+ private getServerConfig(serverId: string): MCPServerConfig {
17
+ const config = loadConfig();
18
+ const server = (config.mcpServers || []).find((s) => s.id === serverId);
19
+ if (!server) {
20
+ throw new Error(`MCP server "${serverId}" is not configured`);
21
+ }
22
+ return server;
23
+ }
24
+
25
+ private async getClient(serverId: string): Promise<Client> {
26
+ const existing = this.clients.get(serverId);
27
+ if (existing) {
28
+ return existing;
29
+ }
30
+
31
+ const server = this.getServerConfig(serverId);
32
+ const client = new Client(
33
+ {
34
+ name: 'openbot-v2',
35
+ version: '0.1.0',
36
+ },
37
+ {
38
+ capabilities: {},
39
+ },
40
+ );
41
+ const transport = new StdioClientTransport({
42
+ command: server.command,
43
+ args: server.args || [],
44
+ env: server.env,
45
+ cwd: server.cwd,
46
+ });
47
+
48
+ await client.connect(transport);
49
+ this.clients.set(serverId, client);
50
+ this.transports.set(serverId, transport);
51
+ return client;
52
+ }
53
+
54
+ async listServers(): Promise<string[]> {
55
+ const config = loadConfig();
56
+ return (config.mcpServers || []).map((server) => server.id);
57
+ }
58
+
59
+ async listTools(serverId: string): Promise<MCPToolSummary[]> {
60
+ const client = await this.getClient(serverId);
61
+ const result = await client.listTools();
62
+ return (result.tools || []).map((tool) => ({
63
+ name: tool.name,
64
+ description: tool.description,
65
+ inputSchema: tool.inputSchema,
66
+ }));
67
+ }
68
+
69
+ async callTool(serverId: string, toolName: string, args: Record<string, unknown>) {
70
+ const client = await this.getClient(serverId);
71
+ return client.callTool({
72
+ name: toolName,
73
+ arguments: args,
74
+ });
75
+ }
76
+ }
77
+
78
+ export const mcpService = new MCPService();