@meetopenbot/openbot 0.2.7 → 1.0.0
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/auto-model.js +13 -0
- package/dist/build-tools.js +26 -0
- package/dist/index.js +66 -67
- package/dist/output-buffer.js +31 -0
- package/dist/runtime.js +359 -483
- package/dist/stream-error.js +6 -0
- package/dist/system-prompt.js +4 -0
- package/dist/tools/approval.js +137 -108
- package/dist/tools/ask-agent.js +39 -47
- package/dist/tools/memory.js +41 -73
- package/dist/tools/start-work.js +61 -141
- package/dist/tools/storage.js +62 -424
- package/dist/tools/thread-status.js +22 -38
- package/dist/tools/thread-title.js +57 -0
- package/dist/tools/todo.js +33 -52
- package/dist/types.js +0 -8
- package/package.json +2 -2
- package/dist/tools/bash.js +0 -432
- package/dist/tools/preview.js +0 -269
- package/dist/tools/ui.js +0 -120
- package/dist/utils/workspace-url.js +0 -6
package/dist/tools/start-work.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { GENERAL_SPACE_ID, isPlaceholderSpaceId, placeholderSpaceError, } from "../space-id.js";
|
|
4
|
-
import { asActionBuilder, } from "../types.js";
|
|
5
4
|
function normalizeSpaceId(raw) {
|
|
6
5
|
return raw
|
|
7
6
|
.trim()
|
|
@@ -24,7 +23,14 @@ function startWorkWidget(args) {
|
|
|
24
23
|
meta: args.meta,
|
|
25
24
|
};
|
|
26
25
|
}
|
|
27
|
-
|
|
26
|
+
function resultMeta(ctx) {
|
|
27
|
+
return {
|
|
28
|
+
agentId: ctx.agentId,
|
|
29
|
+
threadId: ctx.threadId ?? ctx.state.threadId,
|
|
30
|
+
toolCallId: ctx.toolCallId,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export const toolDefinitions = {
|
|
28
34
|
start_work: {
|
|
29
35
|
description: "Start the human's ask in an existing Space. Use from #general for real project work only — not questions, listings, or setup. If the Space does not exist, do not invent one: propose it to the human, then create_channel after they agree. Do not call this on work that was already forwarded.",
|
|
30
36
|
inputSchema: z.object({
|
|
@@ -45,149 +51,71 @@ const startWorkToolDefinitions = {
|
|
|
45
51
|
}),
|
|
46
52
|
},
|
|
47
53
|
};
|
|
48
|
-
export const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const data = event.data;
|
|
57
|
-
const toolCallId = event.meta?.toolCallId;
|
|
58
|
-
const resultMeta = {
|
|
59
|
-
...(event.meta || {}),
|
|
60
|
-
agentId: context.state.agentId,
|
|
61
|
-
threadId: event.meta?.threadId || context.state.threadId,
|
|
62
|
-
};
|
|
63
|
-
const widgetId = typeof toolCallId === "string"
|
|
64
|
-
? toolCallId
|
|
54
|
+
export const tools = {
|
|
55
|
+
start_work: {
|
|
56
|
+
...toolDefinitions.start_work,
|
|
57
|
+
execute: async (rawArgs, ctx) => {
|
|
58
|
+
const data = (rawArgs ?? {});
|
|
59
|
+
const meta = resultMeta(ctx);
|
|
60
|
+
const widgetId = typeof ctx.toolCallId === "string"
|
|
61
|
+
? ctx.toolCallId
|
|
65
62
|
: `start_work:${Date.now()}`;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
yield startWorkWidget({
|
|
63
|
+
const fail = async (error, spaceId = "") => {
|
|
64
|
+
await ctx.emit(startWorkWidget({
|
|
69
65
|
widgetId,
|
|
70
|
-
spaceId
|
|
66
|
+
spaceId,
|
|
71
67
|
body: error,
|
|
72
68
|
state: "error",
|
|
73
|
-
meta
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
return;
|
|
69
|
+
meta,
|
|
70
|
+
}));
|
|
71
|
+
return { success: false, spaceId, error, output: error };
|
|
72
|
+
};
|
|
73
|
+
if (ctx.agentId !== ctx.host.orchestratorAgentId) {
|
|
74
|
+
return fail("Only OpenBot can start work in another Space.");
|
|
81
75
|
}
|
|
82
|
-
const invokeData =
|
|
83
|
-
?
|
|
76
|
+
const invokeData = ctx.state.triggerEvent?.type === "agent:invoke"
|
|
77
|
+
? ctx.state.triggerEvent.data
|
|
84
78
|
: undefined;
|
|
85
79
|
if (typeof invokeData?.forwardedFromSpaceId === "string") {
|
|
86
|
-
|
|
87
|
-
yield startWorkWidget({
|
|
88
|
-
widgetId,
|
|
89
|
-
spaceId: "",
|
|
90
|
-
body: error,
|
|
91
|
-
state: "error",
|
|
92
|
-
meta: resultMeta,
|
|
93
|
-
});
|
|
94
|
-
yield {
|
|
95
|
-
type: "action:start_work:result",
|
|
96
|
-
data: { success: false, error, output: error },
|
|
97
|
-
meta: resultMeta,
|
|
98
|
-
};
|
|
99
|
-
return;
|
|
80
|
+
return fail("This thread was already forwarded. Stay here and ask agents; do not start_work again.");
|
|
100
81
|
}
|
|
101
82
|
const spaceId = normalizeSpaceId(data.spaceId || "");
|
|
102
83
|
const prompt = typeof data.prompt === "string" ? data.prompt.trim() : "";
|
|
103
84
|
if (spaceId && isPlaceholderSpaceId(spaceId)) {
|
|
104
|
-
|
|
105
|
-
yield startWorkWidget({
|
|
106
|
-
widgetId,
|
|
107
|
-
spaceId,
|
|
108
|
-
body: error,
|
|
109
|
-
state: "error",
|
|
110
|
-
meta: resultMeta,
|
|
111
|
-
});
|
|
112
|
-
yield {
|
|
113
|
-
type: "action:start_work:result",
|
|
114
|
-
data: { success: false, spaceId, error, output: error },
|
|
115
|
-
meta: resultMeta,
|
|
116
|
-
};
|
|
117
|
-
return;
|
|
85
|
+
return fail(placeholderSpaceError(spaceId), spaceId);
|
|
118
86
|
}
|
|
119
87
|
if (!spaceId || !prompt) {
|
|
120
|
-
|
|
121
|
-
yield startWorkWidget({
|
|
122
|
-
widgetId,
|
|
123
|
-
spaceId,
|
|
124
|
-
body: error,
|
|
125
|
-
state: "error",
|
|
126
|
-
meta: resultMeta,
|
|
127
|
-
});
|
|
128
|
-
yield {
|
|
129
|
-
type: "action:start_work:result",
|
|
130
|
-
data: { success: false, spaceId, error, output: error },
|
|
131
|
-
meta: resultMeta,
|
|
132
|
-
};
|
|
133
|
-
return;
|
|
88
|
+
return fail("spaceId and prompt are required", spaceId);
|
|
134
89
|
}
|
|
135
|
-
if (spaceId ===
|
|
136
|
-
|
|
137
|
-
yield startWorkWidget({
|
|
138
|
-
widgetId,
|
|
139
|
-
spaceId,
|
|
140
|
-
body: error,
|
|
141
|
-
state: "error",
|
|
142
|
-
meta: resultMeta,
|
|
143
|
-
});
|
|
144
|
-
yield {
|
|
145
|
-
type: "action:start_work:result",
|
|
146
|
-
data: { success: false, spaceId, error, output: error },
|
|
147
|
-
meta: resultMeta,
|
|
148
|
-
};
|
|
149
|
-
return;
|
|
90
|
+
if (spaceId === (ctx.channelId ?? ctx.state.channelId)) {
|
|
91
|
+
return fail(`Already in #${spaceId}. Ask an agent here instead of start_work.`, spaceId);
|
|
150
92
|
}
|
|
151
|
-
const
|
|
152
|
-
const existing = (await storage.getChannels?.().catch(() => []));
|
|
93
|
+
const existing = (await ctx.storage.getChannels?.().catch(() => []));
|
|
153
94
|
const exists = Array.isArray(existing) &&
|
|
154
95
|
existing.some((space) => space.id === spaceId);
|
|
155
96
|
if (!exists) {
|
|
156
|
-
|
|
157
|
-
yield startWorkWidget({
|
|
158
|
-
widgetId,
|
|
159
|
-
spaceId,
|
|
160
|
-
body: error,
|
|
161
|
-
state: "error",
|
|
162
|
-
meta: resultMeta,
|
|
163
|
-
});
|
|
164
|
-
yield {
|
|
165
|
-
type: "action:start_work:result",
|
|
166
|
-
data: { success: false, spaceId, error, output: error },
|
|
167
|
-
meta: resultMeta,
|
|
168
|
-
};
|
|
169
|
-
return;
|
|
97
|
+
return fail(`Space #${spaceId} does not exist. Propose it to the human (name + why). After they agree, use create_channel, then start_work. Do not invent a placeholder Space.`, spaceId);
|
|
170
98
|
}
|
|
171
99
|
const threadId = randomUUID();
|
|
172
100
|
const threadTitle = typeof data.title === "string" && data.title.trim()
|
|
173
101
|
? data.title.trim()
|
|
174
102
|
: undefined;
|
|
175
103
|
const threadUrl = `/channels/${encodeURIComponent(spaceId)}/threads/${encodeURIComponent(threadId)}`;
|
|
176
|
-
const fromSpace =
|
|
177
|
-
|
|
104
|
+
const fromSpace = ctx.channelId ?? ctx.state.channelId ?? GENERAL_SPACE_ID;
|
|
105
|
+
await ctx.emit(startWorkWidget({
|
|
178
106
|
widgetId,
|
|
179
107
|
spaceId,
|
|
180
108
|
body: `Starting in #${spaceId}…`,
|
|
181
109
|
state: "open",
|
|
182
|
-
meta
|
|
183
|
-
});
|
|
110
|
+
meta,
|
|
111
|
+
}));
|
|
184
112
|
try {
|
|
185
|
-
await storage.createThread({
|
|
113
|
+
await ctx.storage.createThread({
|
|
186
114
|
channelId: spaceId,
|
|
187
115
|
threadId,
|
|
188
116
|
threadTitle,
|
|
189
117
|
initialState: {
|
|
190
|
-
respondingAgentId:
|
|
118
|
+
respondingAgentId: ctx.host.orchestratorAgentId,
|
|
191
119
|
...(threadTitle ? { name: threadTitle } : {}),
|
|
192
120
|
},
|
|
193
121
|
});
|
|
@@ -205,58 +133,50 @@ export const startWorkPlugin = {
|
|
|
205
133
|
meta: {
|
|
206
134
|
channelId: spaceId,
|
|
207
135
|
threadId,
|
|
208
|
-
userId:
|
|
209
|
-
userName:
|
|
210
|
-
userAvatarUrl:
|
|
136
|
+
userId: ctx.state.triggerEvent?.meta?.userId,
|
|
137
|
+
userName: ctx.state.triggerEvent?.meta?.userName,
|
|
138
|
+
userAvatarUrl: ctx.state.triggerEvent?.meta?.userAvatarUrl,
|
|
211
139
|
},
|
|
212
140
|
};
|
|
213
|
-
await
|
|
141
|
+
await ctx.host.runAgent({
|
|
214
142
|
runId: `sw_${randomUUID()}`,
|
|
215
|
-
agentId:
|
|
143
|
+
agentId: ctx.host.orchestratorAgentId,
|
|
216
144
|
event: invokeEvent,
|
|
217
|
-
publicBaseUrl:
|
|
145
|
+
publicBaseUrl: ctx.publicBaseUrl,
|
|
218
146
|
persistEvents: true,
|
|
219
147
|
onEvent: async () => {
|
|
220
148
|
// Persist in the target Space via the inner harness. Do not echo into this thread.
|
|
221
149
|
},
|
|
222
150
|
});
|
|
223
151
|
const output = `Started work in #${spaceId}. Open ${threadUrl}`;
|
|
224
|
-
|
|
152
|
+
await ctx.emit(startWorkWidget({
|
|
225
153
|
widgetId,
|
|
226
154
|
spaceId,
|
|
227
155
|
body: output,
|
|
228
156
|
state: "submitted",
|
|
229
|
-
meta
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
threadUrl,
|
|
238
|
-
output,
|
|
239
|
-
},
|
|
240
|
-
meta: resultMeta,
|
|
157
|
+
meta,
|
|
158
|
+
}));
|
|
159
|
+
return {
|
|
160
|
+
success: true,
|
|
161
|
+
spaceId,
|
|
162
|
+
threadId,
|
|
163
|
+
threadUrl,
|
|
164
|
+
output,
|
|
241
165
|
};
|
|
242
166
|
}
|
|
243
167
|
catch (error) {
|
|
244
168
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
245
169
|
const output = `Failed to start work in #${spaceId}: ${message}`;
|
|
246
|
-
|
|
170
|
+
await ctx.emit(startWorkWidget({
|
|
247
171
|
widgetId,
|
|
248
172
|
spaceId,
|
|
249
173
|
body: output,
|
|
250
174
|
state: "error",
|
|
251
|
-
meta
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
type: "action:start_work:result",
|
|
255
|
-
data: { success: false, spaceId, threadId, error: message, output },
|
|
256
|
-
meta: resultMeta,
|
|
257
|
-
};
|
|
175
|
+
meta,
|
|
176
|
+
}));
|
|
177
|
+
return { success: false, spaceId, threadId, error: message, output };
|
|
258
178
|
}
|
|
259
|
-
}
|
|
179
|
+
},
|
|
260
180
|
},
|
|
261
181
|
};
|
|
262
|
-
export
|
|
182
|
+
export const startWorkTools = tools;
|