Add bot schedules (routines), open Activity, add Help and a Desktop computer view
Bots create, list, update and delete schedules (cron_jobs, Bun.cron in UTC); a per-minute cron queues due runs as tasks. Routines, Activity (super admins) and Help get their own rail aside. Help covers familiar problems, starting with signing in to Google through Cookie-Editor over the new Desktop (noVNC) view. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -14,7 +14,7 @@ export default function ComposerAttachments({ pending, onRemove }: Props) {
|
||||
if (!pending.length) return null;
|
||||
|
||||
return (
|
||||
<Row className="w-full max-w-[760px] mx-auto gap-2! px-6 pb-3">
|
||||
<Row className="w-full max-w-container mx-auto gap-2! px-6 pb-3">
|
||||
{pending.map((item) => (
|
||||
<ComposerAttachmentChip
|
||||
key={item.key}
|
||||
|
||||
@@ -2,7 +2,10 @@ import { useState, type KeyboardEvent } from "react";
|
||||
import Row from "@moduletrace/twui/layout/Row";
|
||||
import Stack from "@moduletrace/twui/layout/Stack";
|
||||
import Textarea from "@moduletrace/twui/form/Textarea";
|
||||
import type { BotMessageWithAttachments, BotWithLastMessage } from "@/src/types";
|
||||
import type {
|
||||
BotMessageWithAttachments,
|
||||
BotWithLastMessage,
|
||||
} from "@/src/types";
|
||||
import sendBotMessage from "../(functions)/send-bot-message";
|
||||
import useComposerAttachments from "../(hooks)/use-composer-attachments";
|
||||
import ComposerAttachButton from "./composer-attach-button";
|
||||
@@ -30,7 +33,9 @@ export default function Composer({ bot, workspace_id, onSent }: Props) {
|
||||
const files = useComposerAttachments();
|
||||
|
||||
const can_send =
|
||||
Boolean(text.trim() || files.media_ids.length) && !sending && !files.uploading;
|
||||
Boolean(text.trim() || files.media_ids.length) &&
|
||||
!sending &&
|
||||
!files.uploading;
|
||||
|
||||
async function send() {
|
||||
if (!can_send || !bot.id) return;
|
||||
@@ -57,7 +62,9 @@ export default function Composer({ bot, workspace_id, onSent }: Props) {
|
||||
onSent({ message: res.singleRes });
|
||||
}
|
||||
|
||||
function handleKeyDown(e: KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>) {
|
||||
function handleKeyDown(
|
||||
e: KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>,
|
||||
) {
|
||||
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
||||
e.preventDefault();
|
||||
send();
|
||||
@@ -77,10 +84,16 @@ export default function Composer({ bot, workspace_id, onSent }: Props) {
|
||||
files.add({ files: [...e.dataTransfer.files] });
|
||||
}}
|
||||
>
|
||||
<ComposerAttachments pending={files.pending} onRemove={files.remove} />
|
||||
<ComposerAttachments
|
||||
pending={files.pending}
|
||||
onRemove={files.remove}
|
||||
/>
|
||||
<Stack className="shrink-0 gap-0! items-stretch border-0 border-t border-solid border-hairline">
|
||||
<Row className="w-full max-w-[760px] mx-auto h-[88px] gap-4! flex-nowrap items-center px-6">
|
||||
<ComposerAttachButton disabled={files.full} onFiles={files.add} />
|
||||
<Row className="w-full max-w-container mx-auto h-[88px] gap-4! flex-nowrap items-center px-6">
|
||||
<ComposerAttachButton
|
||||
disabled={files.full}
|
||||
onFiles={files.add}
|
||||
/>
|
||||
<Textarea
|
||||
name="message"
|
||||
aria-label={`Message ${bot.name}`}
|
||||
@@ -106,7 +119,11 @@ export default function Composer({ bot, workspace_id, onSent }: Props) {
|
||||
"p-0! outline-0! border-0! bg-transparent! dark:bg-transparent! rounded-none",
|
||||
}}
|
||||
/>
|
||||
<ComposerSendButton disabled={!can_send} loading={sending || files.uploading} onClick={send} />
|
||||
<ComposerSendButton
|
||||
disabled={!can_send}
|
||||
loading={sending || files.uploading}
|
||||
onClick={send}
|
||||
/>
|
||||
</Row>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import Stack from "@moduletrace/twui/layout/Stack";
|
||||
import type { BotMessageWithAttachments, BotWithLastMessage } from "@/src/types";
|
||||
import type {
|
||||
BotMessageWithAttachments,
|
||||
BotWithLastMessage,
|
||||
} from "@/src/types";
|
||||
import groupMessages from "../(utils)/group-messages";
|
||||
import BotThinkingRow from "./bot-thinking-row";
|
||||
import MessageGroupBlock from "./message-group-block";
|
||||
@@ -28,10 +31,14 @@ export default function MessageThread({ bot, messages, progress }: Props) {
|
||||
role="log"
|
||||
aria-live="polite"
|
||||
aria-label={`Conversation with ${bot.name}`}
|
||||
className="w-full max-w-[760px] mx-auto gap-4! items-stretch px-6 pt-6 pb-6"
|
||||
className="w-full max-w-container mx-auto gap-4! items-stretch px-6 pt-6 pb-6"
|
||||
>
|
||||
{groups.map((group) => (
|
||||
<MessageGroupBlock key={group.key} bot={bot} group={group} />
|
||||
<MessageGroupBlock
|
||||
key={group.key}
|
||||
bot={bot}
|
||||
group={group}
|
||||
/>
|
||||
))}
|
||||
<BotThinkingRow bot={bot} progress={progress} />
|
||||
</Stack>
|
||||
|
||||
Reference in New Issue
Block a user