openbot 0.4.0 → 0.4.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/dist/app/cli.js +1 -1
- package/dist/app/config.js +10 -0
- package/dist/app/server.js +200 -3
- package/dist/harness/index.js +18 -0
- package/dist/plugins/approval/index.js +35 -20
- package/dist/plugins/bash/index.js +195 -0
- package/dist/plugins/delegation/index.js +4 -2
- package/dist/plugins/openbot/context.js +54 -9
- package/dist/plugins/openbot/history.js +47 -1
- package/dist/plugins/openbot/index.js +43 -3
- package/dist/plugins/openbot/runtime.js +91 -27
- package/dist/plugins/openbot/system-prompt.js +21 -1
- package/dist/plugins/plugin-manager/index.js +87 -3
- package/dist/plugins/shell/index.js +2 -1
- package/dist/plugins/storage/files.js +67 -0
- package/dist/plugins/storage/index.js +184 -7
- package/dist/plugins/storage/service.js +201 -44
- package/dist/plugins/ui/index.js +109 -150
- package/dist/services/abort.js +43 -0
- package/dist/services/plugins/registry.js +5 -3
- package/dist/services/plugins/service.js +66 -11
- package/docs/agents.md +5 -8
- package/docs/architecture.md +1 -1
- package/docs/plugins.md +28 -7
- package/docs/templates/AGENT.example.md +4 -4
- package/package.json +1 -1
- package/src/app/cli.ts +1 -1
- package/src/app/config.ts +13 -0
- package/src/app/server.ts +235 -3
- package/src/app/types.ts +284 -14
- package/src/harness/index.ts +21 -0
- package/src/plugins/approval/index.ts +37 -20
- package/src/plugins/bash/index.ts +232 -0
- package/src/plugins/delegation/index.ts +5 -2
- package/src/plugins/openbot/context.ts +58 -9
- package/src/plugins/openbot/history.ts +52 -1
- package/src/plugins/openbot/index.ts +45 -3
- package/src/plugins/openbot/runtime.ts +121 -27
- package/src/plugins/openbot/system-prompt.ts +21 -1
- package/src/plugins/plugin-manager/index.ts +105 -3
- package/src/plugins/storage/files.ts +81 -0
- package/src/plugins/storage/index.ts +198 -8
- package/src/plugins/storage/service.ts +267 -44
- package/src/plugins/ui/index.ts +123 -0
- package/src/services/abort.ts +46 -0
- package/src/services/plugins/domain.ts +34 -1
- package/src/services/plugins/registry.ts +5 -3
- package/src/services/plugins/service.ts +136 -45
- package/src/services/plugins/types.ts +5 -1
- package/src/plugins/shell/index.ts +0 -123
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import z from 'zod';
|
|
2
2
|
import type { Plugin } from '../../services/plugins/types.js';
|
|
3
3
|
import { OpenBotEvent } from '../../app/types.js';
|
|
4
|
+
import { buildWorkspaceFileUrl } from './files.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* `storage` — exposes channel/thread/variable mutation tools and provides
|
|
@@ -25,7 +26,9 @@ const storageToolDefinitions = {
|
|
|
25
26
|
cwd: z
|
|
26
27
|
.string()
|
|
27
28
|
.optional()
|
|
28
|
-
.describe(
|
|
29
|
+
.describe(
|
|
30
|
+
'Optional initial current working directory for the channel. Defaults to an absolute path under ~/openbot/{channelId}.',
|
|
31
|
+
),
|
|
29
32
|
}),
|
|
30
33
|
},
|
|
31
34
|
patch_channel_details: {
|
|
@@ -45,10 +48,20 @@ const storageToolDefinitions = {
|
|
|
45
48
|
'Markdown content for the channel specification (SPEC.md). Use for goals and rules.',
|
|
46
49
|
),
|
|
47
50
|
cwd: z.string().optional().describe('Current working directory for the channel.'),
|
|
51
|
+
participants: z
|
|
52
|
+
.array(z.string())
|
|
53
|
+
.optional()
|
|
54
|
+
.describe(
|
|
55
|
+
'List of agent IDs that are participants in this channel. When a user tags an agent (e.g. @agent-id), you should ensure they are added to this list if they are not already there.',
|
|
56
|
+
),
|
|
48
57
|
})
|
|
49
58
|
.refine(
|
|
50
|
-
(value) =>
|
|
51
|
-
|
|
59
|
+
(value) =>
|
|
60
|
+
value.state !== undefined ||
|
|
61
|
+
value.spec !== undefined ||
|
|
62
|
+
value.cwd !== undefined ||
|
|
63
|
+
value.participants !== undefined,
|
|
64
|
+
{ message: 'Provide at least one of state, spec, cwd, or participants.' },
|
|
52
65
|
),
|
|
53
66
|
},
|
|
54
67
|
patch_thread_details: {
|
|
@@ -75,6 +88,22 @@ const storageToolDefinitions = {
|
|
|
75
88
|
key: z.string().describe('The key of the variable to delete.'),
|
|
76
89
|
}),
|
|
77
90
|
},
|
|
91
|
+
delete_channel: {
|
|
92
|
+
description:
|
|
93
|
+
'Permanently delete a channel and all its threads and events. Always confirm with the user before deleting.',
|
|
94
|
+
inputSchema: z.object({
|
|
95
|
+
channelId: z.string().describe('The channel ID to delete.'),
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
get_workspace_file_url: {
|
|
99
|
+
description:
|
|
100
|
+
'Get a fetchable HTTP URL for a file in the current channel workspace (images, video, audio, documents).',
|
|
101
|
+
inputSchema: z.object({
|
|
102
|
+
path: z
|
|
103
|
+
.string()
|
|
104
|
+
.describe('Path relative to the channel working directory, e.g. "uploads/clip.mp4".'),
|
|
105
|
+
}),
|
|
106
|
+
},
|
|
78
107
|
};
|
|
79
108
|
|
|
80
109
|
export const storagePlugin: Plugin = {
|
|
@@ -82,7 +111,9 @@ export const storagePlugin: Plugin = {
|
|
|
82
111
|
name: 'Storage',
|
|
83
112
|
description: 'Tools for creating channels, patching state, and managing workspace variables.',
|
|
84
113
|
toolDefinitions: storageToolDefinitions,
|
|
85
|
-
factory: ({ storage }) => (builder) => {
|
|
114
|
+
factory: ({ storage, publicBaseUrl }) => (builder) => {
|
|
115
|
+
const resolvePublicBaseUrl = () => publicBaseUrl;
|
|
116
|
+
|
|
86
117
|
builder.on('action:create_thread', async function* (event, context) {
|
|
87
118
|
const threadId = event.meta?.threadId;
|
|
88
119
|
const channelId = context.state.channelId;
|
|
@@ -180,6 +211,44 @@ export const storagePlugin: Plugin = {
|
|
|
180
211
|
}
|
|
181
212
|
});
|
|
182
213
|
|
|
214
|
+
builder.on('action:delete_channel', async function* (event, context) {
|
|
215
|
+
const rawChannelId = ((event.data as { channelId?: string })?.channelId || '').trim();
|
|
216
|
+
const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
|
|
217
|
+
|
|
218
|
+
if (!rawChannelId) {
|
|
219
|
+
yield {
|
|
220
|
+
type: 'action:delete_channel:result',
|
|
221
|
+
data: { success: false, channelId: '', error: 'channelId is required' },
|
|
222
|
+
meta: resultMeta,
|
|
223
|
+
} as OpenBotEvent;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
await storage.deleteChannel({ channelId: rawChannelId });
|
|
229
|
+
yield {
|
|
230
|
+
type: 'action:delete_channel:result',
|
|
231
|
+
data: { success: true, channelId: rawChannelId },
|
|
232
|
+
meta: resultMeta,
|
|
233
|
+
} as OpenBotEvent;
|
|
234
|
+
yield {
|
|
235
|
+
type: 'agent:output',
|
|
236
|
+
data: { content: `Deleted channel \`${rawChannelId}\`.` },
|
|
237
|
+
meta: resultMeta,
|
|
238
|
+
} as OpenBotEvent;
|
|
239
|
+
} catch (error) {
|
|
240
|
+
yield {
|
|
241
|
+
type: 'action:delete_channel:result',
|
|
242
|
+
data: {
|
|
243
|
+
success: false,
|
|
244
|
+
channelId: rawChannelId,
|
|
245
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
246
|
+
},
|
|
247
|
+
meta: resultMeta,
|
|
248
|
+
} as OpenBotEvent;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
|
|
183
252
|
builder.on('action:update_channel', async function* (event, context) {
|
|
184
253
|
const data = (event.data || {}) as {
|
|
185
254
|
channelId?: string;
|
|
@@ -302,7 +371,8 @@ export const storagePlugin: Plugin = {
|
|
|
302
371
|
widgetId: "patch-channel-details-result" + Date.now(),
|
|
303
372
|
kind: "message",
|
|
304
373
|
title: "Channel details updated.",
|
|
305
|
-
body:
|
|
374
|
+
body: `The channel details have been updated. ${updatedFields.join(', ')}`,
|
|
375
|
+
display: "collapsed",
|
|
306
376
|
},
|
|
307
377
|
meta: resultMeta,
|
|
308
378
|
}
|
|
@@ -395,6 +465,26 @@ export const storagePlugin: Plugin = {
|
|
|
395
465
|
yield { type: 'action:storage:get-threads-result', data: { threads } };
|
|
396
466
|
});
|
|
397
467
|
|
|
468
|
+
builder.on('action:storage:set-last-read', async function* (event, context) {
|
|
469
|
+
const { channelId, threadId, lastReadEventId } = event.data;
|
|
470
|
+
try {
|
|
471
|
+
await storage.setLastRead({
|
|
472
|
+
channelId: channelId || context.state.channelId,
|
|
473
|
+
threadId: threadId || context.state.threadId,
|
|
474
|
+
lastReadEventId,
|
|
475
|
+
});
|
|
476
|
+
yield { type: 'action:storage:set-last-read-result', data: { success: true } };
|
|
477
|
+
} catch (error) {
|
|
478
|
+
yield {
|
|
479
|
+
type: 'action:storage:set-last-read-result',
|
|
480
|
+
data: {
|
|
481
|
+
success: false,
|
|
482
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
483
|
+
},
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
|
|
398
488
|
builder.on('action:storage:get-channel-details', async function* (_, state) {
|
|
399
489
|
const channelDetails = await storage.getChannelDetails({
|
|
400
490
|
channelId: state.state.channelId,
|
|
@@ -484,6 +574,21 @@ export const storagePlugin: Plugin = {
|
|
|
484
574
|
}
|
|
485
575
|
});
|
|
486
576
|
|
|
577
|
+
builder.on('action:storage:delete-channel', async function* (event) {
|
|
578
|
+
try {
|
|
579
|
+
await storage.deleteChannel({ channelId: event.data.channelId });
|
|
580
|
+
yield { type: 'action:storage:delete-channel-result', data: { success: true } };
|
|
581
|
+
} catch (error) {
|
|
582
|
+
yield {
|
|
583
|
+
type: 'action:storage:delete-channel-result',
|
|
584
|
+
data: {
|
|
585
|
+
success: false,
|
|
586
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
587
|
+
},
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
487
592
|
builder.on('action:storage:delete-agent', async function* (event) {
|
|
488
593
|
try {
|
|
489
594
|
await storage.deleteAgent({ agentId: event.data.agentId });
|
|
@@ -602,7 +707,9 @@ export const storagePlugin: Plugin = {
|
|
|
602
707
|
|
|
603
708
|
builder.on('action:storage:read-file', async function* (event, context) {
|
|
604
709
|
const channelId = context.state.channelId;
|
|
605
|
-
const
|
|
710
|
+
const data = event.data as { path?: string; encoding?: 'utf8' | 'base64' };
|
|
711
|
+
const filePath = data?.path;
|
|
712
|
+
const encoding = data?.encoding ?? 'utf8';
|
|
606
713
|
if (!filePath) {
|
|
607
714
|
yield {
|
|
608
715
|
type: 'action:storage:read-file:result',
|
|
@@ -611,10 +718,23 @@ export const storagePlugin: Plugin = {
|
|
|
611
718
|
return;
|
|
612
719
|
}
|
|
613
720
|
try {
|
|
614
|
-
|
|
721
|
+
if (encoding === 'utf8') {
|
|
722
|
+
const content = await storage.readFile({ channelId, path: filePath });
|
|
723
|
+
yield {
|
|
724
|
+
type: 'action:storage:read-file:result',
|
|
725
|
+
data: { success: true, content, path: filePath, encoding },
|
|
726
|
+
};
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
const { content, mimeType, size } = await storage.readChannelFile({
|
|
731
|
+
channelId,
|
|
732
|
+
path: filePath,
|
|
733
|
+
encoding,
|
|
734
|
+
});
|
|
615
735
|
yield {
|
|
616
736
|
type: 'action:storage:read-file:result',
|
|
617
|
-
data: { success: true, content, path: filePath },
|
|
737
|
+
data: { success: true, content, path: filePath, encoding, mimeType, size },
|
|
618
738
|
};
|
|
619
739
|
} catch (error) {
|
|
620
740
|
yield {
|
|
@@ -627,6 +747,76 @@ export const storagePlugin: Plugin = {
|
|
|
627
747
|
};
|
|
628
748
|
}
|
|
629
749
|
});
|
|
750
|
+
|
|
751
|
+
builder.on('action:storage:get-file-url', async function* (event, context) {
|
|
752
|
+
const channelId = context.state.channelId;
|
|
753
|
+
const filePath = (event.data as { path?: string })?.path;
|
|
754
|
+
if (!filePath) {
|
|
755
|
+
yield {
|
|
756
|
+
type: 'action:storage:get-file-url:result',
|
|
757
|
+
data: { success: false, path: '', error: 'Path is required' },
|
|
758
|
+
};
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
try {
|
|
762
|
+
const { size, mimeType } = await storage.getChannelFileStat({ channelId, path: filePath });
|
|
763
|
+
const url = buildWorkspaceFileUrl({
|
|
764
|
+
baseUrl: resolvePublicBaseUrl(),
|
|
765
|
+
channelId,
|
|
766
|
+
filePath,
|
|
767
|
+
});
|
|
768
|
+
yield {
|
|
769
|
+
type: 'action:storage:get-file-url:result',
|
|
770
|
+
data: { success: true, path: filePath, url, mimeType, size },
|
|
771
|
+
};
|
|
772
|
+
} catch (error) {
|
|
773
|
+
yield {
|
|
774
|
+
type: 'action:storage:get-file-url:result',
|
|
775
|
+
data: {
|
|
776
|
+
success: false,
|
|
777
|
+
path: filePath,
|
|
778
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
779
|
+
},
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
builder.on('action:get_workspace_file_url', async function* (event, context) {
|
|
785
|
+
const channelId = context.state.channelId;
|
|
786
|
+
const filePath = (event.data as { path?: string })?.path;
|
|
787
|
+
const toolCallId = event.meta?.toolCallId;
|
|
788
|
+
|
|
789
|
+
if (!filePath) {
|
|
790
|
+
yield {
|
|
791
|
+
type: 'action:get_workspace_file_url:result',
|
|
792
|
+
data: { success: false, path: '', error: 'Path is required', output: 'Path is required' },
|
|
793
|
+
meta: { ...(event.meta || {}), toolCallId },
|
|
794
|
+
};
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
try {
|
|
799
|
+
const { size, mimeType } = await storage.getChannelFileStat({ channelId, path: filePath });
|
|
800
|
+
const url = buildWorkspaceFileUrl({
|
|
801
|
+
baseUrl: resolvePublicBaseUrl(),
|
|
802
|
+
channelId,
|
|
803
|
+
filePath,
|
|
804
|
+
});
|
|
805
|
+
const output = JSON.stringify({ path: filePath, url, mimeType, size });
|
|
806
|
+
yield {
|
|
807
|
+
type: 'action:get_workspace_file_url:result',
|
|
808
|
+
data: { success: true, path: filePath, url, mimeType, size, output },
|
|
809
|
+
meta: { ...(event.meta || {}), toolCallId },
|
|
810
|
+
};
|
|
811
|
+
} catch (error) {
|
|
812
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
813
|
+
yield {
|
|
814
|
+
type: 'action:get_workspace_file_url:result',
|
|
815
|
+
data: { success: false, path: filePath, error: message, output: message },
|
|
816
|
+
meta: { ...(event.meta || {}), toolCallId },
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
});
|
|
630
820
|
},
|
|
631
821
|
};
|
|
632
822
|
|