openbot 0.5.9 → 0.5.11
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/active-runs.js +70 -0
- package/dist/app/cli.js +1 -1
- package/dist/app/lifecycle-events.js +27 -0
- package/dist/app/run-event-handler.js +37 -0
- package/dist/app/server.js +124 -124
- package/dist/app/slack-webhook.js +81 -0
- package/dist/app/webhook-routing.js +52 -0
- package/dist/harness/index.js +11 -14
- package/dist/plugins/slack-webhook/index.js +51 -0
- package/dist/plugins/storage/index.js +72 -14
- package/dist/plugins/storage/service.js +7 -1
- package/docs/plugins.md +39 -0
- package/package.json +2 -2
- package/src/app/active-runs.ts +95 -0
- package/src/app/cli.ts +1 -1
- package/src/app/lifecycle-events.ts +46 -0
- package/src/app/run-event-handler.ts +55 -0
- package/src/app/server.ts +143 -154
- package/src/app/types.ts +32 -4
- package/src/app/webhook-routing.ts +70 -0
- package/src/harness/index.ts +10 -19
- package/src/plugins/storage/index.ts +432 -372
- package/src/plugins/storage/service.ts +9 -3
- package/src/services/plugins/types.ts +0 -2
|
@@ -10,404 +10,464 @@ export const storagePlugin: Plugin = {
|
|
|
10
10
|
id: 'storage',
|
|
11
11
|
name: 'Storage',
|
|
12
12
|
description: 'Infrastructure storage handlers for channels, threads, agents, and files.',
|
|
13
|
-
factory:
|
|
14
|
-
|
|
13
|
+
factory:
|
|
14
|
+
({ storage, publicBaseUrl }) =>
|
|
15
|
+
(builder) => {
|
|
16
|
+
const resolvePublicBaseUrl = () => publicBaseUrl;
|
|
17
|
+
|
|
18
|
+
builder.on('action:create_thread', async function* (event, context) {
|
|
19
|
+
const threadId = event.meta?.threadId;
|
|
20
|
+
const channelId = context.state.channelId;
|
|
21
|
+
const { threadTitle, initialState } = (event as any).data;
|
|
22
|
+
|
|
23
|
+
if (!threadId) {
|
|
24
|
+
console.warn('[storage] Cannot create thread: meta.threadId is missing');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
context.state.threadId = threadId;
|
|
29
|
+
|
|
30
|
+
if (channelId) {
|
|
31
|
+
try {
|
|
32
|
+
await storage.createThread({
|
|
33
|
+
channelId,
|
|
34
|
+
threadId,
|
|
35
|
+
threadTitle,
|
|
36
|
+
initialState: (initialState as Record<string, unknown>) || {},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
context.state.threadDetails = await storage.getThreadDetails({
|
|
40
|
+
channelId,
|
|
41
|
+
threadId,
|
|
42
|
+
});
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.warn(
|
|
45
|
+
`[storage] Failed to initialize thread for channel ${channelId} thread ${threadId}`,
|
|
46
|
+
error,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
yield {
|
|
52
|
+
type: 'action:create_thread:result',
|
|
53
|
+
data: { success: true, threadId, threadTitle },
|
|
54
|
+
meta: { ...(event.meta || {}), threadId, agentId: context.state.agentId },
|
|
55
|
+
} as OpenBotEvent;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
builder.on('agent:usage', async function* (event, context) {
|
|
59
|
+
const { usage } = event.data;
|
|
60
|
+
const channelId = context.state.channelId;
|
|
61
|
+
if (!channelId || !context.state.threadId) return;
|
|
62
|
+
|
|
63
|
+
const currentState = (context.state.threadDetails?.state as Record<string, any>) || {};
|
|
64
|
+
const currentUsage = currentState.usage || {
|
|
65
|
+
promptTokens: 0,
|
|
66
|
+
completionTokens: 0,
|
|
67
|
+
totalTokens: 0,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const nextUsage = {
|
|
71
|
+
promptTokens: (currentUsage.promptTokens || 0) + usage.promptTokens,
|
|
72
|
+
completionTokens: (currentUsage.completionTokens || 0) + usage.completionTokens,
|
|
73
|
+
totalTokens: (currentUsage.totalTokens || 0) + usage.totalTokens,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
await storage.patchThreadState({
|
|
77
|
+
channelId,
|
|
78
|
+
threadId: context.state.threadId,
|
|
79
|
+
state: { usage: nextUsage },
|
|
80
|
+
});
|
|
15
81
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
82
|
+
context.state.threadDetails = await storage.getThreadDetails({
|
|
83
|
+
channelId,
|
|
84
|
+
threadId: context.state.threadId,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
20
87
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
88
|
+
builder.on('action:storage:get-channels', async function* () {
|
|
89
|
+
const channels = await storage.getChannels();
|
|
90
|
+
yield { type: 'action:storage:get-channels-result', data: { channels } };
|
|
91
|
+
});
|
|
25
92
|
|
|
26
|
-
|
|
93
|
+
builder.on('action:storage:get-threads', async function* (event) {
|
|
94
|
+
const threads = await storage.getThreads({ channelId: event.data.channelId });
|
|
95
|
+
yield { type: 'action:storage:get-threads-result', data: { threads } };
|
|
96
|
+
});
|
|
27
97
|
|
|
28
|
-
|
|
98
|
+
builder.on('action:storage:set-last-read', async function* (event, context) {
|
|
99
|
+
const { channelId, threadId, lastReadEventId } = event.data;
|
|
100
|
+
const resolvedChannelId = channelId || context.state.channelId;
|
|
101
|
+
if (!resolvedChannelId) {
|
|
102
|
+
yield {
|
|
103
|
+
type: 'action:storage:set-last-read-result',
|
|
104
|
+
data: { success: false, error: 'channelId is required' },
|
|
105
|
+
};
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
29
108
|
try {
|
|
30
|
-
await storage.
|
|
31
|
-
channelId,
|
|
32
|
-
threadId,
|
|
33
|
-
|
|
34
|
-
initialState: (initialState as Record<string, unknown>) || {},
|
|
109
|
+
await storage.setLastRead({
|
|
110
|
+
channelId: resolvedChannelId,
|
|
111
|
+
threadId: threadId || context.state.threadId,
|
|
112
|
+
lastReadEventId,
|
|
35
113
|
});
|
|
114
|
+
yield { type: 'action:storage:set-last-read-result', data: { success: true } };
|
|
115
|
+
} catch (error) {
|
|
116
|
+
yield {
|
|
117
|
+
type: 'action:storage:set-last-read-result',
|
|
118
|
+
data: {
|
|
119
|
+
success: false,
|
|
120
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
});
|
|
36
125
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
126
|
+
builder.on('action:storage:get-channel-details', async function* (_, state) {
|
|
127
|
+
const channelId = state.state.channelId;
|
|
128
|
+
if (!channelId) {
|
|
129
|
+
yield {
|
|
130
|
+
type: 'action:storage:get-channel-details-result',
|
|
131
|
+
data: { channelDetails: null as any, error: 'channelId is required' },
|
|
132
|
+
};
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const channelDetails = await storage.getChannelDetails({ channelId });
|
|
136
|
+
yield { type: 'action:storage:get-channel-details-result', data: { channelDetails } };
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
builder.on('action:storage:get-thread-details', async function* (_, state) {
|
|
140
|
+
const channelId = state.state.channelId;
|
|
141
|
+
const threadId = state.state.threadId;
|
|
142
|
+
if (!channelId) {
|
|
143
|
+
yield {
|
|
144
|
+
type: 'action:storage:get-thread-details-result',
|
|
145
|
+
data: { threadDetails: null, error: 'channelId is required' },
|
|
146
|
+
};
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const threadDetails = threadId
|
|
150
|
+
? await storage.getThreadDetails({ channelId, threadId })
|
|
151
|
+
: null;
|
|
152
|
+
yield { type: 'action:storage:get-thread-details-result', data: { threadDetails } };
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
builder.on('action:storage:get-agents', async function* () {
|
|
156
|
+
const agents = await storage.getAgents();
|
|
157
|
+
yield { type: 'action:storage:get-agents-result', data: { agents } };
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
builder.on('action:storage:get-plugins', async function* () {
|
|
161
|
+
const plugins = await storage.getPlugins();
|
|
162
|
+
yield { type: 'action:storage:get-plugins-result', data: { plugins } };
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
builder.on('action:storage:get-agent-details', async function* (event) {
|
|
166
|
+
try {
|
|
167
|
+
const agentDetails = await storage.getAgentDetails({ agentId: event.data.agentId });
|
|
168
|
+
yield { type: 'action:storage:get-agent-details-result', data: { agentDetails } };
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error(`[storage] Failed to get agent details for ${event.data.agentId}`, error);
|
|
171
|
+
yield {
|
|
172
|
+
type: 'action:storage:get-agent-details-result',
|
|
173
|
+
data: {
|
|
174
|
+
agentDetails: null as any,
|
|
175
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
builder.on('action:storage:create-agent', async function* (event) {
|
|
182
|
+
try {
|
|
183
|
+
const { agentId, name, description, image, hidden, instructions, plugins } = event.data;
|
|
184
|
+
await storage.createAgent({
|
|
185
|
+
agentId,
|
|
186
|
+
name,
|
|
187
|
+
description,
|
|
188
|
+
image,
|
|
189
|
+
hidden,
|
|
190
|
+
instructions,
|
|
191
|
+
plugins,
|
|
40
192
|
});
|
|
193
|
+
yield { type: 'action:storage:create-agent-result', data: { success: true } };
|
|
41
194
|
} catch (error) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
195
|
+
yield {
|
|
196
|
+
type: 'action:storage:create-agent-result',
|
|
197
|
+
data: {
|
|
198
|
+
success: false,
|
|
199
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
200
|
+
},
|
|
201
|
+
};
|
|
46
202
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
yield {
|
|
50
|
-
type: 'action:create_thread:result',
|
|
51
|
-
data: { success: true, threadId, threadTitle },
|
|
52
|
-
meta: { ...(event.meta || {}), threadId, agentId: context.state.agentId },
|
|
53
|
-
} as OpenBotEvent;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
builder.on('agent:usage', async function* (event, context) {
|
|
57
|
-
const { usage } = event.data;
|
|
58
|
-
if (!context.state.threadId) return;
|
|
59
|
-
|
|
60
|
-
const currentState = (context.state.threadDetails?.state as Record<string, any>) || {};
|
|
61
|
-
const currentUsage = currentState.usage || {
|
|
62
|
-
promptTokens: 0,
|
|
63
|
-
completionTokens: 0,
|
|
64
|
-
totalTokens: 0,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const nextUsage = {
|
|
68
|
-
promptTokens: (currentUsage.promptTokens || 0) + usage.promptTokens,
|
|
69
|
-
completionTokens: (currentUsage.completionTokens || 0) + usage.completionTokens,
|
|
70
|
-
totalTokens: (currentUsage.totalTokens || 0) + usage.totalTokens,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
await storage.patchThreadState({
|
|
74
|
-
channelId: context.state.channelId,
|
|
75
|
-
threadId: context.state.threadId,
|
|
76
|
-
state: { usage: nextUsage },
|
|
77
203
|
});
|
|
78
204
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
205
|
+
builder.on('action:storage:update-agent', async function* (event) {
|
|
206
|
+
try {
|
|
207
|
+
const { agentId, name, description, image, hidden, instructions, plugins } = event.data;
|
|
208
|
+
await storage.updateAgent({
|
|
209
|
+
agentId,
|
|
210
|
+
name,
|
|
211
|
+
description,
|
|
212
|
+
image,
|
|
213
|
+
hidden,
|
|
214
|
+
instructions,
|
|
215
|
+
plugins,
|
|
216
|
+
});
|
|
217
|
+
yield { type: 'action:storage:update-agent-result', data: { success: true } };
|
|
218
|
+
} catch (error) {
|
|
219
|
+
yield {
|
|
220
|
+
type: 'action:storage:update-agent-result',
|
|
221
|
+
data: {
|
|
222
|
+
success: false,
|
|
223
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
82
227
|
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
builder.on('action:storage:get-channels', async function* () {
|
|
86
|
-
const channels = await storage.getChannels();
|
|
87
|
-
yield { type: 'action:storage:get-channels-result', data: { channels } };
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
builder.on('action:storage:get-threads', async function* (event) {
|
|
91
|
-
const threads = await storage.getThreads({ channelId: event.data.channelId });
|
|
92
|
-
yield { type: 'action:storage:get-threads-result', data: { threads } };
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
builder.on('action:storage:set-last-read', async function* (event, context) {
|
|
96
|
-
const { channelId, threadId, lastReadEventId } = event.data;
|
|
97
|
-
try {
|
|
98
|
-
await storage.setLastRead({
|
|
99
|
-
channelId: channelId || context.state.channelId,
|
|
100
|
-
threadId: threadId || context.state.threadId,
|
|
101
|
-
lastReadEventId,
|
|
102
|
-
});
|
|
103
|
-
yield { type: 'action:storage:set-last-read-result', data: { success: true } };
|
|
104
|
-
} catch (error) {
|
|
105
|
-
yield {
|
|
106
|
-
type: 'action:storage:set-last-read-result',
|
|
107
|
-
data: {
|
|
108
|
-
success: false,
|
|
109
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
228
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
229
|
+
builder.on('action:storage:delete-channel', async function* (event) {
|
|
230
|
+
try {
|
|
231
|
+
await storage.deleteChannel({ channelId: event.data.channelId });
|
|
232
|
+
yield { type: 'action:storage:delete-channel-result', data: { success: true } };
|
|
233
|
+
} catch (error) {
|
|
234
|
+
yield {
|
|
235
|
+
type: 'action:storage:delete-channel-result',
|
|
236
|
+
data: {
|
|
237
|
+
success: false,
|
|
238
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
118
242
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
yield { type: 'action:storage:get-agents-result', data: { agents } };
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
builder.on('action:storage:get-plugins', async function* () {
|
|
136
|
-
const plugins = await storage.getPlugins();
|
|
137
|
-
yield { type: 'action:storage:get-plugins-result', data: { plugins } };
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
builder.on('action:storage:get-agent-details', async function* (event) {
|
|
141
|
-
try {
|
|
142
|
-
const agentDetails = await storage.getAgentDetails({ agentId: event.data.agentId });
|
|
143
|
-
yield { type: 'action:storage:get-agent-details-result', data: { agentDetails } };
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.error(`[storage] Failed to get agent details for ${event.data.agentId}`, error);
|
|
146
|
-
yield {
|
|
147
|
-
type: 'action:storage:get-agent-details-result',
|
|
148
|
-
data: {
|
|
149
|
-
agentDetails: null as any,
|
|
150
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
151
|
-
},
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
builder.on('action:storage:create-agent', async function* (event) {
|
|
157
|
-
try {
|
|
158
|
-
const { agentId, name, description, image, hidden, instructions, plugins } = event.data;
|
|
159
|
-
await storage.createAgent({
|
|
160
|
-
agentId,
|
|
161
|
-
name,
|
|
162
|
-
description,
|
|
163
|
-
image,
|
|
164
|
-
hidden,
|
|
165
|
-
instructions,
|
|
166
|
-
plugins,
|
|
167
|
-
});
|
|
168
|
-
yield { type: 'action:storage:create-agent-result', data: { success: true } };
|
|
169
|
-
} catch (error) {
|
|
170
|
-
yield {
|
|
171
|
-
type: 'action:storage:create-agent-result',
|
|
172
|
-
data: {
|
|
173
|
-
success: false,
|
|
174
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
builder.on('action:storage:update-agent', async function* (event) {
|
|
181
|
-
try {
|
|
182
|
-
const { agentId, name, description, image, hidden, instructions, plugins } = event.data;
|
|
183
|
-
await storage.updateAgent({
|
|
184
|
-
agentId,
|
|
185
|
-
name,
|
|
186
|
-
description,
|
|
187
|
-
image,
|
|
188
|
-
hidden,
|
|
189
|
-
instructions,
|
|
190
|
-
plugins,
|
|
191
|
-
});
|
|
192
|
-
yield { type: 'action:storage:update-agent-result', data: { success: true } };
|
|
193
|
-
} catch (error) {
|
|
194
|
-
yield {
|
|
195
|
-
type: 'action:storage:update-agent-result',
|
|
196
|
-
data: {
|
|
197
|
-
success: false,
|
|
198
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
199
|
-
},
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
builder.on('action:storage:delete-channel', async function* (event) {
|
|
205
|
-
try {
|
|
206
|
-
await storage.deleteChannel({ channelId: event.data.channelId });
|
|
207
|
-
yield { type: 'action:storage:delete-channel-result', data: { success: true } };
|
|
208
|
-
} catch (error) {
|
|
209
|
-
yield {
|
|
210
|
-
type: 'action:storage:delete-channel-result',
|
|
211
|
-
data: {
|
|
212
|
-
success: false,
|
|
213
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
214
|
-
},
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
builder.on('action:storage:delete-agent', async function* (event) {
|
|
220
|
-
try {
|
|
221
|
-
await storage.deleteAgent({ agentId: event.data.agentId });
|
|
222
|
-
yield { type: 'action:storage:delete-agent-result', data: { success: true } };
|
|
223
|
-
} catch (error) {
|
|
224
|
-
yield {
|
|
225
|
-
type: 'action:storage:delete-agent-result',
|
|
226
|
-
data: {
|
|
227
|
-
success: false,
|
|
228
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
builder.on('action:storage:get-events', async function* (_, state) {
|
|
235
|
-
const events = await storage.getEvents(state.state);
|
|
236
|
-
yield { type: 'action:storage:get-events-result', data: { events } };
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
builder.on('action:storage:get-variables', async function* () {
|
|
240
|
-
const variables = await storage.getVariables();
|
|
241
|
-
const masked: Record<string, string> = {};
|
|
242
|
-
for (const [key, val] of Object.entries(variables)) {
|
|
243
|
-
if (typeof val === 'object' && val !== null && val.secret) {
|
|
244
|
-
masked[key] = '********';
|
|
245
|
-
} else {
|
|
246
|
-
masked[key] = typeof val === 'string' ? val : val.value;
|
|
243
|
+
|
|
244
|
+
builder.on('action:storage:delete-agent', async function* (event) {
|
|
245
|
+
try {
|
|
246
|
+
await storage.deleteAgent({ agentId: event.data.agentId });
|
|
247
|
+
yield { type: 'action:storage:delete-agent-result', data: { success: true } };
|
|
248
|
+
} catch (error) {
|
|
249
|
+
yield {
|
|
250
|
+
type: 'action:storage:delete-agent-result',
|
|
251
|
+
data: {
|
|
252
|
+
success: false,
|
|
253
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
254
|
+
},
|
|
255
|
+
};
|
|
247
256
|
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
builder.on('action:storage:delete-variable', async function* (event) {
|
|
272
|
-
try {
|
|
273
|
-
await storage.deleteVariable({ key: event.data.key });
|
|
274
|
-
yield { type: 'action:storage:delete-variable-result', data: { success: true } };
|
|
275
|
-
} catch (error) {
|
|
276
|
-
yield {
|
|
277
|
-
type: 'action:storage:delete-variable-result',
|
|
278
|
-
data: {
|
|
279
|
-
success: false,
|
|
280
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
281
|
-
},
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
builder.on('action:storage:patch-channel-state', async function* (event, state) {
|
|
287
|
-
try {
|
|
288
|
-
await storage.patchChannelState({
|
|
289
|
-
channelId: state.state.channelId,
|
|
290
|
-
state: event.data.state,
|
|
291
|
-
});
|
|
292
|
-
yield { type: 'action:storage:patch-channel-state-result', data: { success: true } };
|
|
293
|
-
} catch {
|
|
294
|
-
yield { type: 'action:storage:patch-channel-state-result', data: { success: false } };
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
builder.on('action:storage:patch-thread-state', async function* (event, state) {
|
|
299
|
-
try {
|
|
300
|
-
if (!state.state.threadId) {
|
|
301
|
-
throw new Error('Missing threadId in state for patch-thread-state');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
builder.on('action:storage:get-events', async function* (_, state) {
|
|
260
|
+
const channelId = state.state.channelId;
|
|
261
|
+
if (!channelId) {
|
|
262
|
+
yield { type: 'action:storage:get-events-result', data: { events: [] } };
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const events = await storage.getEvents({ channelId, threadId: state.state.threadId });
|
|
266
|
+
yield { type: 'action:storage:get-events-result', data: { events } };
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
builder.on('action:storage:get-variables', async function* () {
|
|
270
|
+
const variables = await storage.getVariables();
|
|
271
|
+
const masked: Record<string, string> = {};
|
|
272
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
273
|
+
if (typeof val === 'object' && val !== null && val.secret) {
|
|
274
|
+
masked[key] = '********';
|
|
275
|
+
} else {
|
|
276
|
+
masked[key] = typeof val === 'string' ? val : val.value;
|
|
277
|
+
}
|
|
302
278
|
}
|
|
303
|
-
await storage.patchThreadState({
|
|
304
|
-
channelId: state.state.channelId,
|
|
305
|
-
threadId: state.state.threadId,
|
|
306
|
-
state: event.data.state,
|
|
307
|
-
});
|
|
308
|
-
yield { type: 'action:storage:patch-thread-state-result', data: { success: true } };
|
|
309
|
-
} catch {
|
|
310
|
-
yield { type: 'action:storage:patch-thread-state-result', data: { success: false } };
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
builder.on('action:storage:list-files', async function* (event, context) {
|
|
315
|
-
const channelId = context.state.channelId;
|
|
316
|
-
const subPath = (event.data as any)?.path || '';
|
|
317
|
-
try {
|
|
318
|
-
const files = await storage.listFiles({ channelId, path: subPath });
|
|
319
|
-
yield {
|
|
320
|
-
type: 'action:storage:list-files:result',
|
|
321
|
-
data: { success: true, files },
|
|
322
|
-
};
|
|
323
|
-
} catch (error) {
|
|
324
|
-
yield {
|
|
325
|
-
type: 'action:storage:list-files:result',
|
|
326
|
-
data: {
|
|
327
|
-
success: false,
|
|
328
|
-
files: [],
|
|
329
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
330
|
-
},
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
builder.on('action:storage:read-file', async function* (event, context) {
|
|
336
|
-
const channelId = context.state.channelId;
|
|
337
|
-
const data = event.data as { path?: string; encoding?: 'utf8' | 'base64' };
|
|
338
|
-
const filePath = data?.path;
|
|
339
|
-
const encoding = data?.encoding ?? 'utf8';
|
|
340
|
-
if (!filePath) {
|
|
341
279
|
yield {
|
|
342
|
-
type: 'action:storage:
|
|
343
|
-
data: {
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const
|
|
280
|
+
type: 'action:storage:get-variables-result',
|
|
281
|
+
data: { variables: masked },
|
|
282
|
+
} as OpenBotEvent;
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
builder.on('action:storage:create-variable', async function* (event) {
|
|
286
|
+
try {
|
|
287
|
+
const { key, value, secret } = event.data;
|
|
288
|
+
await storage.createVariable({ key, value, secret });
|
|
289
|
+
yield { type: 'action:storage:create-variable-result', data: { success: true } };
|
|
290
|
+
} catch (error) {
|
|
350
291
|
yield {
|
|
351
|
-
type: 'action:storage:
|
|
352
|
-
data: {
|
|
292
|
+
type: 'action:storage:create-variable-result',
|
|
293
|
+
data: {
|
|
294
|
+
success: false,
|
|
295
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
builder.on('action:storage:delete-variable', async function* (event) {
|
|
302
|
+
try {
|
|
303
|
+
await storage.deleteVariable({ key: event.data.key });
|
|
304
|
+
yield { type: 'action:storage:delete-variable-result', data: { success: true } };
|
|
305
|
+
} catch (error) {
|
|
306
|
+
yield {
|
|
307
|
+
type: 'action:storage:delete-variable-result',
|
|
308
|
+
data: {
|
|
309
|
+
success: false,
|
|
310
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
311
|
+
},
|
|
353
312
|
};
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
builder.on('action:storage:patch-channel-state', async function* (event, state) {
|
|
317
|
+
const channelId = state.state.channelId;
|
|
318
|
+
if (!channelId) {
|
|
319
|
+
yield { type: 'action:storage:patch-channel-state-result', data: { success: false } };
|
|
354
320
|
return;
|
|
355
321
|
}
|
|
322
|
+
try {
|
|
323
|
+
await storage.patchChannelState({
|
|
324
|
+
channelId,
|
|
325
|
+
state: event.data.state,
|
|
326
|
+
});
|
|
327
|
+
yield { type: 'action:storage:patch-channel-state-result', data: { success: true } };
|
|
328
|
+
} catch {
|
|
329
|
+
yield { type: 'action:storage:patch-channel-state-result', data: { success: false } };
|
|
330
|
+
}
|
|
331
|
+
});
|
|
356
332
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
type: 'action:storage:
|
|
369
|
-
|
|
370
|
-
|
|
333
|
+
builder.on('action:storage:patch-thread-state', async function* (event, state) {
|
|
334
|
+
const channelId = state.state.channelId;
|
|
335
|
+
try {
|
|
336
|
+
if (!channelId || !state.state.threadId) {
|
|
337
|
+
throw new Error('Missing channelId or threadId in state for patch-thread-state');
|
|
338
|
+
}
|
|
339
|
+
await storage.patchThreadState({
|
|
340
|
+
channelId,
|
|
341
|
+
threadId: state.state.threadId,
|
|
342
|
+
state: event.data.state,
|
|
343
|
+
});
|
|
344
|
+
yield { type: 'action:storage:patch-thread-state-result', data: { success: true } };
|
|
345
|
+
} catch {
|
|
346
|
+
yield { type: 'action:storage:patch-thread-state-result', data: { success: false } };
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
builder.on('action:storage:list-files', async function* (event, context) {
|
|
351
|
+
const channelId = context.state.channelId;
|
|
352
|
+
const subPath = (event.data as any)?.path || '';
|
|
353
|
+
if (!channelId) {
|
|
354
|
+
yield {
|
|
355
|
+
type: 'action:storage:list-files:result',
|
|
356
|
+
data: { success: false, files: [], error: 'channelId is required' },
|
|
357
|
+
};
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const files = await storage.listFiles({ channelId, path: subPath });
|
|
362
|
+
yield {
|
|
363
|
+
type: 'action:storage:list-files:result',
|
|
364
|
+
data: { success: true, files },
|
|
365
|
+
};
|
|
366
|
+
} catch (error) {
|
|
367
|
+
yield {
|
|
368
|
+
type: 'action:storage:list-files:result',
|
|
369
|
+
data: {
|
|
370
|
+
success: false,
|
|
371
|
+
files: [],
|
|
372
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
builder.on('action:storage:read-file', async function* (event, context) {
|
|
379
|
+
const channelId = context.state.channelId;
|
|
380
|
+
const data = event.data as { path?: string; encoding?: 'utf8' | 'base64' };
|
|
381
|
+
const filePath = data?.path;
|
|
382
|
+
const encoding = data?.encoding ?? 'utf8';
|
|
383
|
+
if (!filePath) {
|
|
384
|
+
yield {
|
|
385
|
+
type: 'action:storage:read-file:result',
|
|
386
|
+
data: { success: false, path: '', error: 'Path is required' },
|
|
387
|
+
};
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (!channelId) {
|
|
391
|
+
yield {
|
|
392
|
+
type: 'action:storage:read-file:result',
|
|
393
|
+
data: { success: false, path: filePath, error: 'channelId is required' },
|
|
394
|
+
};
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
if (encoding === 'utf8') {
|
|
399
|
+
const content = await storage.readFile({ channelId, path: filePath });
|
|
400
|
+
yield {
|
|
401
|
+
type: 'action:storage:read-file:result',
|
|
402
|
+
data: { success: true, content, path: filePath, encoding },
|
|
403
|
+
};
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const { content, mimeType, size } = await storage.readChannelFile({
|
|
408
|
+
channelId,
|
|
371
409
|
path: filePath,
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
410
|
+
encoding,
|
|
411
|
+
});
|
|
412
|
+
yield {
|
|
413
|
+
type: 'action:storage:read-file:result',
|
|
414
|
+
data: { success: true, content, path: filePath, encoding, mimeType, size },
|
|
415
|
+
};
|
|
416
|
+
} catch (error) {
|
|
417
|
+
yield {
|
|
418
|
+
type: 'action:storage:read-file:result',
|
|
419
|
+
data: {
|
|
420
|
+
success: false,
|
|
421
|
+
path: filePath,
|
|
422
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
});
|
|
377
427
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
};
|
|
399
|
-
} catch (error) {
|
|
400
|
-
yield {
|
|
401
|
-
type: 'action:storage:get-file-url:result',
|
|
402
|
-
data: {
|
|
403
|
-
success: false,
|
|
428
|
+
builder.on('action:storage:get-file-url', async function* (event, context) {
|
|
429
|
+
const channelId = context.state.channelId;
|
|
430
|
+
const filePath = (event.data as { path?: string })?.path;
|
|
431
|
+
if (!filePath) {
|
|
432
|
+
yield {
|
|
433
|
+
type: 'action:storage:get-file-url:result',
|
|
434
|
+
data: { success: false, path: '', error: 'Path is required' },
|
|
435
|
+
};
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (!channelId) {
|
|
439
|
+
yield {
|
|
440
|
+
type: 'action:storage:get-file-url:result',
|
|
441
|
+
data: { success: false, path: filePath, error: 'channelId is required' },
|
|
442
|
+
};
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
const { size, mimeType } = await storage.getChannelFileStat({
|
|
447
|
+
channelId,
|
|
404
448
|
path: filePath,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
449
|
+
});
|
|
450
|
+
const url = buildWorkspaceFileUrl({
|
|
451
|
+
baseUrl: resolvePublicBaseUrl(),
|
|
452
|
+
channelId,
|
|
453
|
+
filePath,
|
|
454
|
+
});
|
|
455
|
+
yield {
|
|
456
|
+
type: 'action:storage:get-file-url:result',
|
|
457
|
+
data: { success: true, path: filePath, url, mimeType, size },
|
|
458
|
+
};
|
|
459
|
+
} catch (error) {
|
|
460
|
+
yield {
|
|
461
|
+
type: 'action:storage:get-file-url:result',
|
|
462
|
+
data: {
|
|
463
|
+
success: false,
|
|
464
|
+
path: filePath,
|
|
465
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
},
|
|
411
471
|
};
|
|
412
472
|
|
|
413
473
|
export default storagePlugin;
|