Let crew managers edit a bot's workspace instructions where they work with it

A bot's instructions and memory for one workspace were only reachable
from the workspace's settings. The editor is now shared and also opens
from the conversation menu in that workspace ("Instructions here",
loaded on open through api/admin/workspaces/workspace-bot) and from the
workspace rows on the bot's settings page.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-25 13:17:32 +01:00
co-authored by Claude Opus 5.5
parent 84f8c0cac8
commit 2d85177c59
14 changed files with 431 additions and 87 deletions
@@ -0,0 +1,86 @@
import { useState } from "react";
import Form from "@moduletrace/twui/form/Form";
import CodeEditor from "@/src/components/general/code-editor";
import type { WorkspaceBot } from "@/src/types";
import postAdminApi from "@/src/layouts/bots/(functions)/post-admin-api";
import AddFormActions from "@/src/layouts/bots/(partials)/add-form-actions";
type Props = {
workspace_id: number;
bot_id: number;
bot_name?: string | null;
/**
* What the bot has for this workspace now.
*/
system_prompt?: string | null;
memory?: string | null;
onCancel: () => void;
/**
* After the save, with the workspace's crew as it is now.
*/
onSaved: (bots: WorkspaceBot[]) => void;
};
/**
* The form for what one bot has for a workspace alone: its instructions
* there, on top of its own, and its memory there
* (`api/admin/workspaces/update-bot`, crew managers). It asks first.
*/
export default function WorkspaceBotForm({
workspace_id,
bot_id,
bot_name,
system_prompt: initial_prompt,
memory: initial_memory,
onCancel,
onSaved,
}: Props) {
const [system_prompt, setSystemPrompt] = useState(initial_prompt || "");
const [memory, setMemory] = useState(initial_memory || "");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string>();
const submit = async () => {
if (loading) return;
if (!window.confirm(`Save ${bot_name || "this bot"}'s instructions and memory here?`)) return;
setLoading(true);
setError(undefined);
const res = await postAdminApi<WorkspaceBot>({
path: "workspaces/update-bot",
body: { workspace_id, bot_id, system_prompt, memory },
});
setLoading(false);
if (!res.success) {
setError(res.msg || "Couldn't save.");
return;
}
onSaved(res.payload || []);
};
return (
<Form className="w-full gap-4! items-stretch pt-4" onSubmit={submit}>
<CodeEditor
mode="markdown"
className="h-44"
title="Instructions here"
content={system_prompt}
placeholder="In this workspace, write for the marketing team: short, plain, no jargon."
onChange={(value) => setSystemPrompt(value)}
/>
<CodeEditor
mode="markdown"
className="h-32"
title="Memory here"
content={memory}
info="What it must remember in this workspace."
onChange={(value) => setMemory(value)}
/>
<AddFormActions submit_label="Save" loading={loading} error={error} onCancel={onCancel} />
</Form>
);
}
@@ -0,0 +1,58 @@
import type { WorkspaceBot } from "@/src/types";
import AddModalShell from "@/src/layouts/bots/(partials)/add-modal-shell";
import WorkspaceBotForm from "./workspace-bot-form";
type Props = {
workspace_id: number;
workspace_name?: string | null;
bot_id: number;
bot_name?: string | null;
/**
* What the bot has for this workspace now.
*/
system_prompt?: string | null;
memory?: string | null;
onClose: () => void;
onSaved: (bots: WorkspaceBot[]) => void;
};
/**
* What one bot has for this workspace alone: instructions on top of its
* own, and its memory here. The bot rewrites both as it learns; the
* coordinator can set the instructions too. Opened from the workspace's
* settings and from the bot's.
*/
export default function WorkspaceBotModal({
workspace_id,
workspace_name,
bot_id,
bot_name,
system_prompt,
memory,
onClose,
onSaved,
}: Props) {
const name = bot_name || "This bot";
return (
<AddModalShell
open
setOpen={(open) => !open && onClose()}
title={`${name} in ${workspace_name || "this workspace"}`}
description={`${name} keeps its own instructions and memory everywhere. These apply only here, and it updates them itself as it learns how this workspace works.`}
>
<WorkspaceBotForm
workspace_id={workspace_id}
bot_id={bot_id}
bot_name={bot_name}
system_prompt={system_prompt}
memory={memory}
onCancel={onClose}
onSaved={(bots) => {
onSaved(bots);
onClose();
}}
/>
</AddModalShell>
);
}