openbot 0.4.7 → 0.5.4
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/.claude/agents/runtime-security-reviewer.md +32 -0
- package/.claude/hooks/format.sh +18 -0
- package/.claude/hooks/protect-secrets.sh +23 -0
- package/.claude/settings.json +26 -0
- package/.claude/skills/deploy/SKILL.md +26 -0
- package/.claude/skills/new-plugin/SKILL.md +46 -0
- package/.dockerignore +9 -0
- package/.mcp.json +8 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +50 -0
- package/Dockerfile +41 -0
- package/deploy/README.md +61 -0
- package/deploy/entrypoint.sh +6 -0
- package/deploy/fly.toml +36 -0
- package/dist/app/bootstrap.js +29 -0
- package/dist/app/cli.js +3 -1
- package/dist/app/cloud-mode.js +26 -0
- package/dist/app/config.js +61 -16
- package/dist/app/server.js +38 -6
- package/dist/plugins/approval/index.js +1 -1
- package/dist/plugins/bash/index.js +386 -164
- package/dist/plugins/memory/service.js +2 -5
- package/dist/plugins/openbot/context.js +17 -1
- package/dist/plugins/openbot/index.js +23 -8
- package/dist/plugins/openbot/model.js +59 -0
- package/dist/plugins/openbot/runtime.js +39 -56
- package/dist/plugins/openbot/system-prompt.js +43 -8
- package/dist/plugins/preview/index.js +267 -0
- package/dist/plugins/storage/index.js +3 -3
- package/dist/plugins/storage/service.js +58 -12
- package/dist/plugins/todo/index.js +131 -38
- package/dist/plugins/todo/service.js +93 -0
- package/dist/plugins/ui/index.js +8 -1
- package/dist/services/plugins/model-registry.js +101 -0
- package/dist/services/plugins/registry.js +6 -4
- package/dist/services/plugins/service.js +2 -6
- package/docs/agents.md +20 -2
- package/docs/architecture.md +1 -1
- package/docs/plugins.md +13 -3
- package/docs/templates/AGENT.example.md +1 -1
- package/package.json +5 -2
- package/pnpm-workspace.yaml +2 -0
- package/src/app/bootstrap.ts +43 -0
- package/src/app/cli.ts +3 -1
- package/src/app/cloud-mode.ts +41 -0
- package/src/app/config.ts +71 -19
- package/src/app/server.ts +45 -6
- package/src/app/types.ts +162 -31
- package/src/plugins/approval/index.ts +1 -1
- package/src/plugins/bash/index.ts +498 -185
- package/src/plugins/memory/service.ts +2 -5
- package/src/plugins/openbot/context.ts +17 -1
- package/src/plugins/openbot/index.ts +25 -10
- package/src/plugins/openbot/model.ts +76 -0
- package/src/plugins/openbot/runtime.ts +47 -69
- package/src/plugins/openbot/system-prompt.ts +43 -8
- package/src/plugins/preview/index.ts +323 -0
- package/src/plugins/storage/index.ts +5 -8
- package/src/plugins/storage/service.ts +79 -15
- package/src/plugins/todo/index.ts +166 -0
- package/src/plugins/todo/service.ts +123 -0
- package/src/plugins/ui/index.ts +8 -1
- package/src/services/plugins/domain.ts +2 -0
- package/src/services/plugins/model-registry.ts +146 -0
- package/src/services/plugins/registry.ts +6 -4
- package/src/services/plugins/service.ts +2 -6
- package/dist/agents/openbot/index.js +0 -76
- package/dist/agents/openbot/middleware/approval.js +0 -132
- package/dist/agents/openbot/runtime.js +0 -289
- package/dist/agents/openbot/system-prompt.js +0 -32
- package/dist/agents/openbot/tools/delegation.js +0 -78
- package/dist/agents/openbot/tools/mcp.js +0 -99
- package/dist/agents/openbot/tools/shell.js +0 -91
- package/dist/agents/openbot/tools/storage.js +0 -75
- package/dist/agents/openbot/tools/ui.js +0 -176
- package/dist/agents/system.js +0 -33
- package/dist/bus/agent-package.js +0 -1
- package/dist/bus/plugin.js +0 -1
- package/dist/bus/services.js +0 -754
- package/dist/bus/types.js +0 -1
- package/dist/harness/agent-harness.js +0 -45
- package/dist/harness/agent-invoke-run.js +0 -44
- package/dist/harness/agent-turn.js +0 -99
- package/dist/harness/channel-participants.js +0 -40
- package/dist/harness/constants.js +0 -2
- package/dist/harness/context-meter.js +0 -97
- package/dist/harness/context.js +0 -363
- package/dist/harness/dispatch.js +0 -144
- package/dist/harness/dispatcher.js +0 -156
- package/dist/harness/event-normalizer.js +0 -59
- package/dist/harness/history.js +0 -177
- package/dist/harness/mcp.js +0 -61
- package/dist/harness/orchestration.js +0 -88
- package/dist/harness/orchestrator.js +0 -149
- package/dist/harness/participants.js +0 -22
- package/dist/harness/process.js +0 -29
- package/dist/harness/queue-processor.js +0 -187
- package/dist/harness/run-harness.js +0 -154
- package/dist/harness/run.js +0 -98
- package/dist/harness/runtime-factory.js +0 -73
- package/dist/harness/runtime.js +0 -57
- package/dist/harness/todo-advance.js +0 -93
- package/dist/harness/todo-dispatch.js +0 -51
- package/dist/harness/todos.js +0 -5
- package/dist/harness/turn.js +0 -79
- package/dist/harness/types.js +0 -1
- package/dist/plugins/ai-sdk/index.js +0 -34
- package/dist/plugins/ai-sdk/runtime.js +0 -395
- package/dist/plugins/ai-sdk/system-prompt.js +0 -18
- package/dist/plugins/ai-sdk.js +0 -331
- package/dist/plugins/approval.js +0 -163
- package/dist/plugins/delegation.js +0 -108
- package/dist/plugins/mcp/index.js +0 -108
- package/dist/plugins/mcp.js +0 -140
- package/dist/plugins/shell/index.js +0 -100
- package/dist/plugins/shell.js +0 -123
- package/dist/plugins/storage-tools/index.js +0 -76
- package/dist/plugins/storage.js +0 -737
- package/dist/plugins/thread-namer/index.js +0 -72
- package/dist/plugins/threads/index.js +0 -114
- package/dist/plugins/ui.js +0 -211
- package/dist/plugins/workflow/index.js +0 -65
- package/dist/registry/agents.js +0 -138
- package/dist/registry/plugins.js +0 -110
- package/dist/services/agent-packages.js +0 -103
- package/dist/services/memory.js +0 -152
- package/dist/services/plugins.js +0 -98
- package/dist/services/storage.js +0 -1028
- package/dist/workflow/service.js +0 -106
- package/dist/workflow/types.js +0 -3
package/dist/plugins/storage.js
DELETED
|
@@ -1,737 +0,0 @@
|
|
|
1
|
-
import { storageService } from '../services/storage.js';
|
|
2
|
-
import { pluginService } from '../services/plugins.js';
|
|
3
|
-
import z from 'zod';
|
|
4
|
-
export const storageToolDefinitions = {
|
|
5
|
-
create_channel: {
|
|
6
|
-
description: 'Create a new channel. Use this when you think the user intent is completelly different from the current channel and should be split into multiple channels. Before creating, always notify with details and ask for confirmation. If user asks basic questions, no need to create a channel.',
|
|
7
|
-
inputSchema: z.object({
|
|
8
|
-
channelId: z
|
|
9
|
-
.string()
|
|
10
|
-
.describe('Unique channel ID. Example: product-launch, backend-platform, or channel_roadmap.'),
|
|
11
|
-
spec: z
|
|
12
|
-
.string()
|
|
13
|
-
.optional()
|
|
14
|
-
.describe('Optional initial markdown content for the channel spec.'),
|
|
15
|
-
initialState: z
|
|
16
|
-
.record(z.string(), z.unknown())
|
|
17
|
-
.optional()
|
|
18
|
-
.describe('Optional initial state object for the channel.'),
|
|
19
|
-
cwd: z
|
|
20
|
-
.string()
|
|
21
|
-
.optional()
|
|
22
|
-
.describe('Optional initial current working directory for the channel.'),
|
|
23
|
-
}),
|
|
24
|
-
},
|
|
25
|
-
patch_channel_details: {
|
|
26
|
-
description: 'Patch current channel details (state and/or spec).',
|
|
27
|
-
inputSchema: z
|
|
28
|
-
.object({
|
|
29
|
-
state: z
|
|
30
|
-
.record(z.string(), z.unknown())
|
|
31
|
-
.optional()
|
|
32
|
-
.describe('JSON state object for the channel. Use this for structured data like `todos` or metadata.'),
|
|
33
|
-
spec: z
|
|
34
|
-
.string()
|
|
35
|
-
.optional()
|
|
36
|
-
.describe('Markdown content for the channel specification (SPEC.md). Use this for goals and rules.'),
|
|
37
|
-
cwd: z.string().optional().describe('Current working directory for the channel.'),
|
|
38
|
-
})
|
|
39
|
-
.refine((value) => value.state !== undefined || value.spec !== undefined || value.cwd !== undefined, {
|
|
40
|
-
message: 'Provide at least one of state, spec, or cwd.',
|
|
41
|
-
}),
|
|
42
|
-
},
|
|
43
|
-
patch_thread_details: {
|
|
44
|
-
description: 'Patch current thread details (state and/or spec).',
|
|
45
|
-
inputSchema: z
|
|
46
|
-
.object({
|
|
47
|
-
state: z
|
|
48
|
-
.record(z.string(), z.unknown())
|
|
49
|
-
.optional()
|
|
50
|
-
.describe('JSON state object for the thread. Use this for structured data like `todos` or progress tracking.'),
|
|
51
|
-
spec: z
|
|
52
|
-
.string()
|
|
53
|
-
.optional()
|
|
54
|
-
.describe('Markdown content for the thread specification (SPEC.md). Use this for detailed plans and goals.'),
|
|
55
|
-
})
|
|
56
|
-
.refine((value) => value.state !== undefined || value.spec !== undefined, {
|
|
57
|
-
message: 'Provide at least one of state or spec.',
|
|
58
|
-
}),
|
|
59
|
-
},
|
|
60
|
-
create_variable: {
|
|
61
|
-
description: 'Create or update a variable in the workspace storage.',
|
|
62
|
-
inputSchema: z.object({
|
|
63
|
-
key: z.string().describe('The key of the variable.'),
|
|
64
|
-
value: z.string().describe('The value of the variable.'),
|
|
65
|
-
secret: z.boolean().optional().describe('Whether the variable is a secret.'),
|
|
66
|
-
}),
|
|
67
|
-
},
|
|
68
|
-
delete_variable: {
|
|
69
|
-
description: 'Delete a variable from the workspace storage.',
|
|
70
|
-
inputSchema: z.object({
|
|
71
|
-
key: z.string().describe('The key of the variable to delete.'),
|
|
72
|
-
}),
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
export const storagePlugin = (options) => (builder) => {
|
|
76
|
-
const { storage } = options;
|
|
77
|
-
builder.on('action:create_thread', async function* (event, context) {
|
|
78
|
-
// We take threadId from meta so the next agent:invoke event will reply in the same thread.
|
|
79
|
-
const threadId = event.meta?.threadId;
|
|
80
|
-
const channelId = context.state.channelId;
|
|
81
|
-
const { threadTitle, spec, initialState } = event.data;
|
|
82
|
-
if (!threadId) {
|
|
83
|
-
console.warn('[storage] Cannot create thread: meta.threadId is missing');
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Override threadId in state to keep subsequent replies in the same thread.
|
|
87
|
-
context.state.threadId = threadId;
|
|
88
|
-
if (channelId) {
|
|
89
|
-
try {
|
|
90
|
-
await storage.createThread({
|
|
91
|
-
channelId,
|
|
92
|
-
threadId,
|
|
93
|
-
threadTitle,
|
|
94
|
-
spec,
|
|
95
|
-
initialState: initialState || {},
|
|
96
|
-
});
|
|
97
|
-
context.state.threadDetails = await storage.getThreadDetails({
|
|
98
|
-
channelId,
|
|
99
|
-
threadId,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
console.warn(`[storage] Failed to initialize thread for channel ${channelId} thread ${threadId}`, error);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
yield {
|
|
107
|
-
type: 'action:create_thread:result',
|
|
108
|
-
data: {
|
|
109
|
-
success: true,
|
|
110
|
-
threadId,
|
|
111
|
-
threadTitle,
|
|
112
|
-
},
|
|
113
|
-
meta: {
|
|
114
|
-
threadId,
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
});
|
|
118
|
-
builder.on('action:create_channel', async function* (event, context) {
|
|
119
|
-
const { channelId, spec, initialState, cwd } = event.data;
|
|
120
|
-
const rawChannelId = (channelId || '').trim();
|
|
121
|
-
const channelSpec = typeof spec === 'string' ? spec : '';
|
|
122
|
-
if (!rawChannelId) {
|
|
123
|
-
yield {
|
|
124
|
-
type: 'action:create_channel:result',
|
|
125
|
-
data: {
|
|
126
|
-
success: false,
|
|
127
|
-
channelId: '',
|
|
128
|
-
channelUrl: '',
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const channelUrl = `/channels/${rawChannelId}`;
|
|
134
|
-
try {
|
|
135
|
-
await storage.createChannel({
|
|
136
|
-
channelId: rawChannelId,
|
|
137
|
-
spec: channelSpec,
|
|
138
|
-
initialState: initialState,
|
|
139
|
-
cwd,
|
|
140
|
-
});
|
|
141
|
-
yield {
|
|
142
|
-
type: 'action:create_channel:result',
|
|
143
|
-
data: {
|
|
144
|
-
success: true,
|
|
145
|
-
channelId: rawChannelId,
|
|
146
|
-
channelUrl,
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
yield {
|
|
150
|
-
type: 'agent:output',
|
|
151
|
-
data: {
|
|
152
|
-
content: `Created channel \`${rawChannelId}\`.`,
|
|
153
|
-
},
|
|
154
|
-
meta: {
|
|
155
|
-
...(event.meta || {}),
|
|
156
|
-
agentId: context.state.agentId,
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
yield {
|
|
162
|
-
type: 'action:create_channel:result',
|
|
163
|
-
data: {
|
|
164
|
-
success: false,
|
|
165
|
-
channelId: rawChannelId,
|
|
166
|
-
channelUrl,
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
builder.on('action:storage:get-channels', async function* () {
|
|
172
|
-
const channels = await storage.getChannels();
|
|
173
|
-
yield {
|
|
174
|
-
type: 'action:storage:get-channels-result',
|
|
175
|
-
data: { channels },
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
builder.on('action:storage:get-threads', async function* (event) {
|
|
179
|
-
const threads = await storage.getThreads({ channelId: event.data.channelId });
|
|
180
|
-
yield {
|
|
181
|
-
type: 'action:storage:get-threads-result',
|
|
182
|
-
data: { threads },
|
|
183
|
-
};
|
|
184
|
-
});
|
|
185
|
-
builder.on('action:storage:get-channel-details', async function* (_, state) {
|
|
186
|
-
const channelDetails = await storage.getChannelDetails({ channelId: state.state.channelId });
|
|
187
|
-
yield {
|
|
188
|
-
type: 'action:storage:get-channel-details-result',
|
|
189
|
-
data: { channelDetails },
|
|
190
|
-
};
|
|
191
|
-
});
|
|
192
|
-
builder.on('action:storage:get-thread-details', async function* (_, state) {
|
|
193
|
-
const threadId = state.state.threadId;
|
|
194
|
-
const threadDetails = threadId
|
|
195
|
-
? await storage.getThreadDetails({ channelId: state.state.channelId, threadId })
|
|
196
|
-
: null;
|
|
197
|
-
yield {
|
|
198
|
-
type: 'action:storage:get-thread-details-result',
|
|
199
|
-
data: { threadDetails },
|
|
200
|
-
};
|
|
201
|
-
});
|
|
202
|
-
builder.on('action:storage:get-agents', async function* () {
|
|
203
|
-
const agents = await storage.getAgents();
|
|
204
|
-
yield {
|
|
205
|
-
type: 'action:storage:get-agents-result',
|
|
206
|
-
data: { agents },
|
|
207
|
-
};
|
|
208
|
-
});
|
|
209
|
-
builder.on('action:storage:get-plugins', async function* () {
|
|
210
|
-
const plugins = await storage.getPlugins();
|
|
211
|
-
yield {
|
|
212
|
-
type: 'action:storage:get-plugins-result',
|
|
213
|
-
data: { plugins },
|
|
214
|
-
};
|
|
215
|
-
});
|
|
216
|
-
builder.on('action:storage:get-agent-details', async function* (event, state) {
|
|
217
|
-
try {
|
|
218
|
-
const agentDetails = await storage.getAgentDetails({ agentId: event.data.agentId });
|
|
219
|
-
yield {
|
|
220
|
-
type: 'action:storage:get-agent-details-result',
|
|
221
|
-
data: { agentDetails },
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
console.error(`[storage] Failed to get agent details for ${event.data.agentId}`, error);
|
|
226
|
-
yield {
|
|
227
|
-
type: 'action:storage:get-agent-details-result',
|
|
228
|
-
data: {
|
|
229
|
-
agentDetails: null,
|
|
230
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
builder.on('action:storage:create-agent', async function* (event) {
|
|
236
|
-
try {
|
|
237
|
-
const { agentId, name, description, instructions, plugins, runtime } = event.data;
|
|
238
|
-
await storage.createAgent({
|
|
239
|
-
agentId,
|
|
240
|
-
name,
|
|
241
|
-
description,
|
|
242
|
-
instructions,
|
|
243
|
-
plugins,
|
|
244
|
-
runtime,
|
|
245
|
-
});
|
|
246
|
-
yield {
|
|
247
|
-
type: 'action:storage:create-agent-result',
|
|
248
|
-
data: { success: true },
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
catch (error) {
|
|
252
|
-
yield {
|
|
253
|
-
type: 'action:storage:create-agent-result',
|
|
254
|
-
data: {
|
|
255
|
-
success: false,
|
|
256
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
257
|
-
},
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
builder.on('action:storage:update-agent', async function* (event) {
|
|
262
|
-
try {
|
|
263
|
-
const { agentId, name, description, instructions, plugins, runtime } = event.data;
|
|
264
|
-
await storage.updateAgent({
|
|
265
|
-
agentId,
|
|
266
|
-
name,
|
|
267
|
-
description,
|
|
268
|
-
instructions,
|
|
269
|
-
plugins,
|
|
270
|
-
runtime,
|
|
271
|
-
});
|
|
272
|
-
yield {
|
|
273
|
-
type: 'action:storage:update-agent-result',
|
|
274
|
-
data: { success: true },
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
yield {
|
|
279
|
-
type: 'action:storage:update-agent-result',
|
|
280
|
-
data: {
|
|
281
|
-
success: false,
|
|
282
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
builder.on('action:storage:delete-agent', async function* (event) {
|
|
288
|
-
try {
|
|
289
|
-
const { agentId } = event.data;
|
|
290
|
-
await storage.deleteAgent({ agentId });
|
|
291
|
-
yield {
|
|
292
|
-
type: 'action:storage:delete-agent-result',
|
|
293
|
-
data: { success: true },
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
yield {
|
|
298
|
-
type: 'action:storage:delete-agent-result',
|
|
299
|
-
data: {
|
|
300
|
-
success: false,
|
|
301
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
302
|
-
},
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
builder.on('action:storage:get-events', async function* (_, state) {
|
|
307
|
-
const events = await storage.getEvents(state.state);
|
|
308
|
-
// Simple: fetching main channel events marks it as read
|
|
309
|
-
if (!state.state.threadId && events.length > 0) {
|
|
310
|
-
const lastId = events[events.length - 1]?.id;
|
|
311
|
-
if (lastId) {
|
|
312
|
-
// We call storageService directly as it's an internal helper now
|
|
313
|
-
await storageService.setLastReadForChannel({
|
|
314
|
-
channelId: state.state.channelId,
|
|
315
|
-
lastReadEventId: lastId,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
yield {
|
|
320
|
-
type: 'action:storage:get-events-result',
|
|
321
|
-
data: { events },
|
|
322
|
-
};
|
|
323
|
-
});
|
|
324
|
-
builder.on('action:storage:get-variables', async function* () {
|
|
325
|
-
const variables = await storage.getVariables();
|
|
326
|
-
const maskedVariables = {};
|
|
327
|
-
for (const [key, val] of Object.entries(variables)) {
|
|
328
|
-
if (typeof val === 'object' && val !== null && val.secret) {
|
|
329
|
-
maskedVariables[key] = '********';
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
maskedVariables[key] = typeof val === 'string' ? val : val.value;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
yield {
|
|
336
|
-
type: 'action:storage:get-variables-result',
|
|
337
|
-
data: { variables: maskedVariables },
|
|
338
|
-
};
|
|
339
|
-
});
|
|
340
|
-
builder.on('action:storage:create-variable', async function* (event) {
|
|
341
|
-
try {
|
|
342
|
-
const { key, value, secret } = event.data;
|
|
343
|
-
await storage.createVariable({ key, value, secret });
|
|
344
|
-
yield {
|
|
345
|
-
type: 'action:storage:create-variable-result',
|
|
346
|
-
data: { success: true },
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
catch (error) {
|
|
350
|
-
yield {
|
|
351
|
-
type: 'action:storage:create-variable-result',
|
|
352
|
-
data: {
|
|
353
|
-
success: false,
|
|
354
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
355
|
-
},
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
builder.on('action:storage:delete-variable', async function* (event) {
|
|
360
|
-
try {
|
|
361
|
-
const { key } = event.data;
|
|
362
|
-
await storage.deleteVariable({ key });
|
|
363
|
-
yield {
|
|
364
|
-
type: 'action:storage:delete-variable-result',
|
|
365
|
-
data: { success: true },
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
catch (error) {
|
|
369
|
-
yield {
|
|
370
|
-
type: 'action:storage:delete-variable-result',
|
|
371
|
-
data: {
|
|
372
|
-
success: false,
|
|
373
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
builder.on('action:storage:patch-channel-state', async function* (event, state) {
|
|
379
|
-
try {
|
|
380
|
-
await storage.patchChannelState({
|
|
381
|
-
channelId: state.state.channelId,
|
|
382
|
-
state: event.data.state,
|
|
383
|
-
});
|
|
384
|
-
yield {
|
|
385
|
-
type: 'action:storage:patch-channel-state-result',
|
|
386
|
-
data: { success: true },
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
catch (error) {
|
|
390
|
-
yield {
|
|
391
|
-
type: 'action:storage:patch-channel-state-result',
|
|
392
|
-
data: { success: false },
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
builder.on('action:storage:patch-thread-state', async function* (event, state) {
|
|
397
|
-
try {
|
|
398
|
-
if (!state.state.threadId) {
|
|
399
|
-
throw new Error('Missing threadId in state for patch-thread-state');
|
|
400
|
-
}
|
|
401
|
-
await storage.patchThreadState({
|
|
402
|
-
channelId: state.state.channelId,
|
|
403
|
-
threadId: state.state.threadId,
|
|
404
|
-
state: event.data.state,
|
|
405
|
-
});
|
|
406
|
-
yield {
|
|
407
|
-
type: 'action:storage:patch-thread-state-result',
|
|
408
|
-
data: { success: true },
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
catch (error) {
|
|
412
|
-
yield {
|
|
413
|
-
type: 'action:storage:patch-thread-state-result',
|
|
414
|
-
data: { success: false },
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
builder.on('action:patch_channel_details', async function* (event, context) {
|
|
419
|
-
const updatedFields = [];
|
|
420
|
-
try {
|
|
421
|
-
if (event.data.state !== undefined) {
|
|
422
|
-
await storage.patchChannelState({
|
|
423
|
-
channelId: context.state.channelId,
|
|
424
|
-
state: event.data.state,
|
|
425
|
-
});
|
|
426
|
-
updatedFields.push('state');
|
|
427
|
-
}
|
|
428
|
-
if (typeof event.data.spec === 'string') {
|
|
429
|
-
await storage.patchChannelSpec({
|
|
430
|
-
channelId: context.state.channelId,
|
|
431
|
-
spec: event.data.spec,
|
|
432
|
-
});
|
|
433
|
-
updatedFields.push('spec');
|
|
434
|
-
}
|
|
435
|
-
if (typeof event.data.cwd === 'string') {
|
|
436
|
-
await storage.patchChannelState({
|
|
437
|
-
channelId: context.state.channelId,
|
|
438
|
-
state: { cwd: event.data.cwd },
|
|
439
|
-
});
|
|
440
|
-
updatedFields.push('cwd');
|
|
441
|
-
}
|
|
442
|
-
context.state.channelDetails = await storage.getChannelDetails({
|
|
443
|
-
channelId: context.state.channelId,
|
|
444
|
-
});
|
|
445
|
-
yield {
|
|
446
|
-
type: 'action:patch_channel_details:result',
|
|
447
|
-
data: {
|
|
448
|
-
success: true,
|
|
449
|
-
updatedFields,
|
|
450
|
-
},
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
catch (error) {
|
|
454
|
-
yield {
|
|
455
|
-
type: 'action:patch_channel_details:result',
|
|
456
|
-
data: {
|
|
457
|
-
success: false,
|
|
458
|
-
updatedFields,
|
|
459
|
-
},
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
// Backward-compatible event used by external frontends.
|
|
464
|
-
builder.on('action:update_channel', async function* (event, context) {
|
|
465
|
-
const data = (event.data || {});
|
|
466
|
-
const targetChannelId = (data.channelId || context.state.channelId || '').trim();
|
|
467
|
-
if (!targetChannelId) {
|
|
468
|
-
yield {
|
|
469
|
-
type: 'action:update_channel:result',
|
|
470
|
-
data: {
|
|
471
|
-
success: false,
|
|
472
|
-
channelId: '',
|
|
473
|
-
updatedFields: [],
|
|
474
|
-
},
|
|
475
|
-
};
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
const patch = {};
|
|
479
|
-
const updatedFields = [];
|
|
480
|
-
if (typeof data.name === 'string' && data.name.trim()) {
|
|
481
|
-
patch.name = data.name.trim();
|
|
482
|
-
updatedFields.push('name');
|
|
483
|
-
}
|
|
484
|
-
if (typeof data.cwd === 'string' && data.cwd.trim()) {
|
|
485
|
-
patch.cwd = data.cwd.trim();
|
|
486
|
-
updatedFields.push('cwd');
|
|
487
|
-
}
|
|
488
|
-
try {
|
|
489
|
-
if (updatedFields.length > 0) {
|
|
490
|
-
await storage.patchChannelState({
|
|
491
|
-
channelId: targetChannelId,
|
|
492
|
-
state: patch,
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
if (targetChannelId === context.state.channelId) {
|
|
496
|
-
context.state.channelDetails = await storage.getChannelDetails({
|
|
497
|
-
channelId: context.state.channelId,
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
yield {
|
|
501
|
-
type: 'action:update_channel:result',
|
|
502
|
-
data: {
|
|
503
|
-
success: true,
|
|
504
|
-
channelId: targetChannelId,
|
|
505
|
-
updatedFields,
|
|
506
|
-
},
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
catch {
|
|
510
|
-
yield {
|
|
511
|
-
type: 'action:update_channel:result',
|
|
512
|
-
data: {
|
|
513
|
-
success: false,
|
|
514
|
-
channelId: targetChannelId,
|
|
515
|
-
updatedFields,
|
|
516
|
-
},
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
builder.on('action:patch_thread_details', async function* (event, context) {
|
|
521
|
-
const updatedFields = [];
|
|
522
|
-
try {
|
|
523
|
-
if (!context.state.threadId) {
|
|
524
|
-
throw new Error('Missing threadId in state for patch_thread_details');
|
|
525
|
-
}
|
|
526
|
-
if (event.data.state !== undefined) {
|
|
527
|
-
await storage.patchThreadState({
|
|
528
|
-
channelId: context.state.channelId,
|
|
529
|
-
threadId: context.state.threadId,
|
|
530
|
-
state: event.data.state,
|
|
531
|
-
});
|
|
532
|
-
updatedFields.push('state');
|
|
533
|
-
}
|
|
534
|
-
if (typeof event.data.spec === 'string') {
|
|
535
|
-
await storage.patchThreadSpec({
|
|
536
|
-
channelId: context.state.channelId,
|
|
537
|
-
threadId: context.state.threadId,
|
|
538
|
-
spec: event.data.spec,
|
|
539
|
-
});
|
|
540
|
-
updatedFields.push('spec');
|
|
541
|
-
}
|
|
542
|
-
context.state.threadDetails = await storage.getThreadDetails({
|
|
543
|
-
channelId: context.state.channelId,
|
|
544
|
-
threadId: context.state.threadId,
|
|
545
|
-
});
|
|
546
|
-
yield {
|
|
547
|
-
type: 'action:patch_thread_details:result',
|
|
548
|
-
data: {
|
|
549
|
-
success: true,
|
|
550
|
-
updatedFields,
|
|
551
|
-
},
|
|
552
|
-
};
|
|
553
|
-
yield {
|
|
554
|
-
type: 'agent:output',
|
|
555
|
-
data: {
|
|
556
|
-
content: `Thread details updated: ${updatedFields.join(', ')}`,
|
|
557
|
-
},
|
|
558
|
-
meta: {
|
|
559
|
-
agentId: context.state.agentId,
|
|
560
|
-
},
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
catch (error) {
|
|
564
|
-
yield {
|
|
565
|
-
type: 'action:patch_thread_details:result',
|
|
566
|
-
data: {
|
|
567
|
-
success: false,
|
|
568
|
-
updatedFields,
|
|
569
|
-
},
|
|
570
|
-
};
|
|
571
|
-
yield {
|
|
572
|
-
type: 'agent:output',
|
|
573
|
-
data: {
|
|
574
|
-
content: `Failed to update thread details: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
575
|
-
},
|
|
576
|
-
meta: {
|
|
577
|
-
agentId: context.state.agentId,
|
|
578
|
-
},
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
builder.on('action:storage:list-files', async function* (event, context) {
|
|
583
|
-
const channelId = context.state.channelId;
|
|
584
|
-
const subPath = event.data?.path || '';
|
|
585
|
-
try {
|
|
586
|
-
const files = await storage.listFiles({ channelId, path: subPath });
|
|
587
|
-
yield {
|
|
588
|
-
type: 'action:storage:list-files:result',
|
|
589
|
-
data: {
|
|
590
|
-
success: true,
|
|
591
|
-
files,
|
|
592
|
-
},
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
catch (error) {
|
|
596
|
-
yield {
|
|
597
|
-
type: 'action:storage:list-files:result',
|
|
598
|
-
data: {
|
|
599
|
-
success: false,
|
|
600
|
-
files: [],
|
|
601
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
602
|
-
},
|
|
603
|
-
};
|
|
604
|
-
}
|
|
605
|
-
});
|
|
606
|
-
builder.on('action:storage:read-file', async function* (event, context) {
|
|
607
|
-
const channelId = context.state.channelId;
|
|
608
|
-
const filePath = event.data?.path;
|
|
609
|
-
if (!filePath) {
|
|
610
|
-
yield {
|
|
611
|
-
type: 'action:storage:read-file:result',
|
|
612
|
-
data: {
|
|
613
|
-
success: false,
|
|
614
|
-
path: '',
|
|
615
|
-
error: 'Path is required',
|
|
616
|
-
},
|
|
617
|
-
};
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
try {
|
|
621
|
-
const content = await storage.readFile({ channelId, path: filePath });
|
|
622
|
-
yield {
|
|
623
|
-
type: 'action:storage:read-file:result',
|
|
624
|
-
data: {
|
|
625
|
-
success: true,
|
|
626
|
-
content,
|
|
627
|
-
path: filePath,
|
|
628
|
-
},
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
catch (error) {
|
|
632
|
-
yield {
|
|
633
|
-
type: 'action:storage:read-file:result',
|
|
634
|
-
data: {
|
|
635
|
-
success: false,
|
|
636
|
-
path: filePath,
|
|
637
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
638
|
-
},
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
builder.on('action:plugin:install', async function* (event) {
|
|
643
|
-
try {
|
|
644
|
-
const { name, version } = event.data;
|
|
645
|
-
const result = await pluginService.installPlugin({ packageName: name, version });
|
|
646
|
-
yield {
|
|
647
|
-
type: 'action:plugin:install:result',
|
|
648
|
-
data: { success: true, plugin: result },
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
catch (error) {
|
|
652
|
-
yield {
|
|
653
|
-
type: 'action:plugin:install:result',
|
|
654
|
-
data: { success: false, error: error.message },
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
});
|
|
658
|
-
builder.on('action:plugin:uninstall', async function* (event) {
|
|
659
|
-
try {
|
|
660
|
-
const { id } = event.data;
|
|
661
|
-
await pluginService.uninstallPlugin(id);
|
|
662
|
-
yield {
|
|
663
|
-
type: 'action:plugin:uninstall:result',
|
|
664
|
-
data: { success: true },
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
catch (error) {
|
|
668
|
-
yield {
|
|
669
|
-
type: 'action:plugin:uninstall:result',
|
|
670
|
-
data: { success: false, error: error.message },
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
});
|
|
674
|
-
builder.on('action:marketplace:list', async function* () {
|
|
675
|
-
// Mock marketplace agents for MVP
|
|
676
|
-
const agents = [
|
|
677
|
-
{
|
|
678
|
-
id: 'researcher',
|
|
679
|
-
name: 'Researcher',
|
|
680
|
-
description: 'Specialized in web research and information synthesis.',
|
|
681
|
-
// image: 'https://registry.openbot.local/agents/researcher/icon.svg',
|
|
682
|
-
instructions: 'You are a research assistant. Use available tools to find information.',
|
|
683
|
-
runtime: { name: 'ai-sdk', config: { model: 'openai/gpt-4o' } },
|
|
684
|
-
},
|
|
685
|
-
{
|
|
686
|
-
id: 'coder',
|
|
687
|
-
name: 'Coder',
|
|
688
|
-
description: 'Expert in multiple programming languages and software architecture.',
|
|
689
|
-
// image: 'https://registry.openbot.local/agents/coder/icon.svg',
|
|
690
|
-
instructions: 'You are an expert software engineer. Help the user with coding tasks.',
|
|
691
|
-
runtime: { name: 'ai-sdk', config: { model: 'openai/gpt-4o' } },
|
|
692
|
-
},
|
|
693
|
-
];
|
|
694
|
-
yield {
|
|
695
|
-
type: 'action:marketplace:list:result',
|
|
696
|
-
data: { success: true, agents },
|
|
697
|
-
};
|
|
698
|
-
});
|
|
699
|
-
builder.on('action:agent:install', async function* (event) {
|
|
700
|
-
try {
|
|
701
|
-
const { agentId, name, description, instructions, runtime, plugins } = event.data;
|
|
702
|
-
await storage.createAgent({
|
|
703
|
-
agentId,
|
|
704
|
-
name,
|
|
705
|
-
description,
|
|
706
|
-
instructions,
|
|
707
|
-
runtime,
|
|
708
|
-
plugins,
|
|
709
|
-
});
|
|
710
|
-
yield {
|
|
711
|
-
type: 'action:agent:install:result',
|
|
712
|
-
data: { success: true, agentId },
|
|
713
|
-
};
|
|
714
|
-
yield {
|
|
715
|
-
type: 'agent:output',
|
|
716
|
-
data: { content: `Successfully installed agent **${name}** (${agentId}) from marketplace.` },
|
|
717
|
-
meta: { agentId: 'system' },
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
catch (error) {
|
|
721
|
-
yield {
|
|
722
|
-
type: 'action:agent:install:result',
|
|
723
|
-
data: {
|
|
724
|
-
success: false,
|
|
725
|
-
agentId: event.data.agentId,
|
|
726
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
727
|
-
},
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
};
|
|
732
|
-
export const plugin = {
|
|
733
|
-
name: 'storage',
|
|
734
|
-
description: 'Built-in storage plugin',
|
|
735
|
-
factory: storagePlugin,
|
|
736
|
-
toolDefinitions: storageToolDefinitions,
|
|
737
|
-
};
|