Open computers from the chat, let bots ask for a take-over, show task progress
- Serve each computer to its owner under /computers/<id>/ (HTTP and websockets proxied to the AIO sandbox) and show it in a shared ComputerView with browser, terminal and code modes, opened from the computers modal or a take-over button in the thread. - ask_user_to_take_over lets a bot hand a computer to the user for a login or captcha; the message gets a take-over button and needs-you, and the viewer hands it back with a chat message. - While a task runs the thread shows "<bot> is working..." with the task's latest step; steps read as plain words, not tool names. - A coordinator with no workers no longer claims to delegate, and bots describe started tasks in the first person. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { BUN_SQLITE_COBBLE_BOTS } from "@/db/types/db";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import { ChatReplyNote, CoordinatorReplyNote } from "@/src/data/harness-prompts";
|
||||
import { ChatReplyNote, CoordinatorReplyNote, CoordinatorSoloNote } from "@/src/data/harness-prompts";
|
||||
import grabBotMessages from "@/src/functions/backend/db/bots/grab-bot-messages";
|
||||
import grabBotPrompt from "@/src/functions/backend/db/bots/grab-bot-prompt";
|
||||
import grabBotComputers from "@/src/functions/backend/db/computers/grab-bot-computers";
|
||||
@@ -9,6 +9,7 @@ import grabBotChatTools from "@/src/harness/tools/bot/grab-bot-chat-tools";
|
||||
import botMessagesToHarness from "./bot-messages-to-harness";
|
||||
import composeComputersNote from "./compose-computers-note";
|
||||
import loadAttachmentParts from "./load-attachment-parts";
|
||||
import withTakeOverRefs from "./with-take-over-refs";
|
||||
import type { BotJobContext, BotJobOutcome } from "./types";
|
||||
|
||||
type Params = BotJobContext & {
|
||||
@@ -40,12 +41,32 @@ export default async function runBotReply({
|
||||
const prompt = await grabBotPrompt({ bot_id: bot.id, user_id: bot.user_id });
|
||||
const computers = await grabBotComputers({ bot_id: bot.id, user_id: bot.user_id });
|
||||
|
||||
const take_overs: string[] = [];
|
||||
|
||||
const tools = await grabBotChatTools({
|
||||
bot,
|
||||
user_id: bot.user_id,
|
||||
computers,
|
||||
message_id: job.message_id || undefined,
|
||||
onTakeOver: ({ ref }) => take_overs.push(ref),
|
||||
});
|
||||
|
||||
/**
|
||||
* delegate_task is only there while the coordinator has workers.
|
||||
*/
|
||||
const crew_note =
|
||||
bot.kind != "coordinator"
|
||||
? ""
|
||||
: tools.some((tool) => tool.name == "delegate_task")
|
||||
? CoordinatorReplyNote
|
||||
: CoordinatorSoloNote;
|
||||
|
||||
const result = await runTextLoop({
|
||||
system: [
|
||||
prompt,
|
||||
ChatReplyNote,
|
||||
composeComputersNote({ computers, is_coordinator: bot.kind == "coordinator" }),
|
||||
bot.kind == "coordinator" ? CoordinatorReplyNote : "",
|
||||
crew_note,
|
||||
`Now: ${new Date().toUTCString()}.`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
@@ -54,17 +75,12 @@ export default async function runBotReply({
|
||||
messages: history,
|
||||
parts: await loadAttachmentParts({ messages: history }),
|
||||
}),
|
||||
tools: await grabBotChatTools({
|
||||
bot,
|
||||
user_id: bot.user_id,
|
||||
computers,
|
||||
message_id: job.message_id || undefined,
|
||||
}),
|
||||
tools,
|
||||
max_steps: AppData.BotReplyMaxToolSteps,
|
||||
bot_id: bot.id,
|
||||
signal,
|
||||
onStep: report,
|
||||
});
|
||||
|
||||
return { result: result.text };
|
||||
return withTakeOverRefs({ text: result.text, refs: take_overs });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user