Name the workspace in a bot's task status line
A task running in a workspace shows "Working on a task in <name> workspace", so the bot's own chat and the main rail say where the work is. Outside a workspace it stays "Working on a task". Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -16,12 +16,13 @@ import scheduledRunRetryAt from "@/src/utils/scheduled-run-retry-at";
|
|||||||
import {
|
import {
|
||||||
BotComputerBusyStatusLine,
|
BotComputerBusyStatusLine,
|
||||||
BotReplyJobTitle,
|
BotReplyJobTitle,
|
||||||
BotTaskStatusLine,
|
|
||||||
BotWaitingStatusLine,
|
BotWaitingStatusLine,
|
||||||
} from "@/src/dict/bot-queue-dict";
|
} from "@/src/dict/bot-queue-dict";
|
||||||
import BotJobFatalError from "./bot-job-fatal-error";
|
import BotJobFatalError from "./bot-job-fatal-error";
|
||||||
import describeJobStep from "./describe-job-step";
|
import describeJobStep from "./describe-job-step";
|
||||||
import pushToSessionUser from "./push-to-session-user";
|
import pushToSessionUser from "./push-to-session-user";
|
||||||
|
import taskStatusLine from "@/src/utils/task-status-line";
|
||||||
|
import grabWorkspaceName from "@/src/functions/backend/db/workspaces/grab-workspace-name";
|
||||||
import pushBotNotice from "./push-bot-notice";
|
import pushBotNotice from "./push-bot-notice";
|
||||||
import grabJobUserId from "@/src/functions/backend/db/bots-queue/grab-job-user-id";
|
import grabJobUserId from "@/src/functions/backend/db/bots-queue/grab-job-user-id";
|
||||||
import runBotJob from "./run-bot-job";
|
import runBotJob from "./run-bot-job";
|
||||||
@@ -167,7 +168,10 @@ export default async function processBotJob({
|
|||||||
const run = async () => {
|
const run = async () => {
|
||||||
await setFace({
|
await setFace({
|
||||||
face: "working",
|
face: "working",
|
||||||
status_line: job.kind == "reply" ? BotReplyJobTitle : BotTaskStatusLine,
|
status_line:
|
||||||
|
job.kind == "reply"
|
||||||
|
? BotReplyJobTitle
|
||||||
|
: taskStatusLine({ workspace_name: await grabWorkspaceName({ workspace_id: job.workspace_id }) }),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type { BotFace } from "@/src/dict/bot-dict";
|
import type { BotFace } from "@/src/dict/bot-dict";
|
||||||
import { BotReplyJobTitle, BotTaskStatusLine } from "@/src/dict/bot-queue-dict";
|
import { BotReplyJobTitle } from "@/src/dict/bot-queue-dict";
|
||||||
|
import taskStatusLine from "@/src/utils/task-status-line";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
bot_id: number | string;
|
bot_id: number | string;
|
||||||
@@ -13,22 +14,29 @@ type Params = {
|
|||||||
/**
|
/**
|
||||||
* The face a bot should show one user while other jobs for them are
|
* The face a bot should show one user while other jobs for them are
|
||||||
* still running: thinking while a reply runs (it's short, and its chat
|
* still running: thinking while a reply runs (it's short, and its chat
|
||||||
* needs the row), else working on a task. Null when none is running.
|
* needs the row), else working on a task (in its workspace, if it runs in
|
||||||
|
* one). Null when none is running.
|
||||||
*/
|
*/
|
||||||
export default async function grabRunningBotJobFace({
|
export default async function grabRunningBotJobFace({
|
||||||
bot_id,
|
bot_id,
|
||||||
user_id,
|
user_id,
|
||||||
}: Params): Promise<{ face: BotFace; status_line: string } | null> {
|
}: Params): Promise<{ face: BotFace; status_line: string } | null> {
|
||||||
const kinds = (
|
const jobs = (
|
||||||
await BunSQLite.sql<{ kind: string }>({
|
await BunSQLite.sql<{ kind: string; workspace_name: string | null }>({
|
||||||
sql: `SELECT DISTINCT kind FROM bots_queue WHERE bot_id = ? AND status = 'processing'
|
sql: `SELECT q.kind, w.name AS workspace_name FROM bots_queue q
|
||||||
AND session_id IN (SELECT id FROM bot_sessions WHERE user_id = ?)`,
|
LEFT JOIN workspaces w ON w.id = q.workspace_id
|
||||||
|
WHERE q.bot_id = ? AND q.status = 'processing'
|
||||||
|
AND q.session_id IN (SELECT id FROM bot_sessions WHERE user_id = ?)
|
||||||
|
ORDER BY q.id`,
|
||||||
values: [bot_id, user_id],
|
values: [bot_id, user_id],
|
||||||
})
|
})
|
||||||
).payload?.map((row) => row.kind) || [];
|
).payload || [];
|
||||||
|
|
||||||
if (kinds.includes("reply")) return { face: "working", status_line: BotReplyJobTitle };
|
if (jobs.some((job) => job.kind == "reply")) return { face: "working", status_line: BotReplyJobTitle };
|
||||||
if (kinds.includes("task")) return { face: "working", status_line: BotTaskStatusLine };
|
|
||||||
|
const task = jobs.find((job) => job.kind == "task");
|
||||||
|
|
||||||
|
if (task) return { face: "working", status_line: taskStatusLine({ workspace_name: task.workspace_name }) };
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
|
|
||||||
|
type Params = {
|
||||||
|
workspace_id?: number | string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A workspace's name as it is, without an access check, for copy the
|
||||||
|
* caller already decided to show. Null when there's none.
|
||||||
|
*/
|
||||||
|
export default async function grabWorkspaceName({ workspace_id }: Params): Promise<string | null> {
|
||||||
|
if (!workspace_id) return null;
|
||||||
|
|
||||||
|
const res = await BunSQLite.sql<{ name: string | null }>({
|
||||||
|
sql: `SELECT name FROM workspaces WHERE id = ? LIMIT 1`,
|
||||||
|
values: [Number(workspace_id)],
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.payload?.[0]?.name || null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import taskStatusLine from "./task-status-line";
|
||||||
|
|
||||||
|
describe("taskStatusLine", () => {
|
||||||
|
test("names the workspace a task runs in", () => {
|
||||||
|
expect(taskStatusLine({ workspace_name: "Launch" })).toBe("Working on a task in Launch workspace");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("says just working on a task outside a workspace", () => {
|
||||||
|
expect(taskStatusLine({})).toBe("Working on a task");
|
||||||
|
expect(taskStatusLine({ workspace_name: " " })).toBe("Working on a task");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { BotTaskStatusLine } from "@/src/dict/bot-queue-dict";
|
||||||
|
|
||||||
|
type Params = {
|
||||||
|
/**
|
||||||
|
* The workspace the task runs in, if any.
|
||||||
|
*/
|
||||||
|
workspace_name?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status line while a task runs, naming its workspace when it runs in
|
||||||
|
* one, so the bot's own chat says where the work is. Never the task.
|
||||||
|
*/
|
||||||
|
export default function taskStatusLine({ workspace_name }: Params) {
|
||||||
|
const name = workspace_name?.trim();
|
||||||
|
|
||||||
|
return name ? `${BotTaskStatusLine} in ${name} workspace` : BotTaskStatusLine;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user