diff --git a/bun.lock b/bun.lock index faefb9e..9525f19 100644 --- a/bun.lock +++ b/bun.lock @@ -9,7 +9,7 @@ "@modelcontextprotocol/sdk": "^1.32.1", "@moduletrace/bun-sqlite": "^1.3.0", "@moduletrace/bunext": "^1.3.3", - "@moduletrace/twui": "^0.1.5", + "@moduletrace/twui": "^0.1.6", "@tiptap/extension-bubble-menu": "3.32.0", "@tiptap/extension-mention": "3.32.0", "@tiptap/extension-placeholder": "3.32.0", @@ -255,7 +255,7 @@ "@moduletrace/bunext": ["@moduletrace/bunext@1.3.3", "https://git.tben.me/api/packages/Moduletrace/npm/%40moduletrace%2Fbunext/-/1.3.3/bunext-1.3.3.tgz", { "dependencies": { "@tailwindcss/postcss": "^4.3.3", "@types/bun": "1.3.14", "@types/node": "^24.10.0", "@types/react": "^19.3.0", "@types/react-dom": "^19.3.0", "bun-plugin-tailwind": "^0.1.2", "chalk": "^5.6.2", "chokidar": "^5.0.0", "commander": "^14.0.2", "esbuild": "^0.28.2", "lightningcss-wasm": "^1.32.0", "lodash": "^4.18.1", "ora": "^9.0.0", "postcss": "^8.5.30", "react": "^19.3.0", "react-dom": "^19.3.0", "tailwindcss": "^4.3.3", "typescript": "^5.0.0", "uuid": "^14.0.2" }, "bin": { "bunext": "dist/commands/index.js" } }, "sha512-bbUtQaigsDPUQf6vtDOSCo8GYR7Gnw2ny1Fi3JtUnKsYsYQEcEadzmqntAgf7rLcKc12dadDUgFLxru+jiA92g=="], - "@moduletrace/twui": ["@moduletrace/twui@0.1.5", "https://git.tben.me/api/packages/Moduletrace/npm/%40moduletrace%2Ftwui/-/0.1.5/twui-0.1.5.tgz", { "dependencies": { "lodash": "^4.18.1", "tailwind-merge": "^3.7.0" }, "peerDependencies": { "ace-builds": "^1.40.0", "lucide-react": ">=0.577.0", "next-mdx-remote": "^6.0.0", "openai": ">=6.0.0", "react": ">=18", "react-dom": ">=18", "react-markdown": ">=9.0.0", "rehype-prism-plus": "^2.0.0", "remark-gfm": "^4.0.0", "tailwindcss": "^4" }, "optionalPeers": ["ace-builds", "next-mdx-remote", "openai", "react-markdown", "rehype-prism-plus", "remark-gfm"] }, "sha512-XwY5r6+a7G8lIaf6MqYxTXz3He6iKQbScCAWsDbX3QtPdWw1VcSpbTvqNk/hi9krobdA1DAjOzu1pg4AaOy9Rw=="], + "@moduletrace/twui": ["@moduletrace/twui@0.1.6", "https://git.tben.me/api/packages/Moduletrace/npm/%40moduletrace%2Ftwui/-/0.1.6/twui-0.1.6.tgz", { "dependencies": { "lodash": "^4.18.1", "tailwind-merge": "^3.7.0" }, "peerDependencies": { "ace-builds": "^1.40.0", "lucide-react": ">=0.577.0", "next-mdx-remote": "^6.0.0", "openai": ">=6.0.0", "react": ">=18", "react-dom": ">=18", "react-markdown": ">=9.0.0", "rehype-prism-plus": "^2.0.0", "remark-gfm": "^4.0.0", "tailwindcss": "^4" }, "optionalPeers": ["ace-builds", "next-mdx-remote", "openai", "react-markdown", "rehype-prism-plus", "remark-gfm"] }, "sha512-BFNIV1itkIYXmhq1rBJA8E8MjwN9AP7MESbOnzM0yUb6xbsOFIBbmlKfUu6kTr7QCl1TWNxWTGFPVmQ2S54cDA=="], "@next/mdx": ["@next/mdx@16.3.0", "", { "dependencies": { "source-map": "^0.7.0" }, "peerDependencies": { "@mdx-js/loader": ">=0.15.0", "@mdx-js/react": ">=0.15.0" }, "optionalPeers": ["@mdx-js/loader", "@mdx-js/react"] }, "sha512-Vpfuf928ACvx4AOdDXWx/cj13Ak6xlvMn3QCkjvfQMmLnQWCesQTeY01CPDbIyZvjY+NOwP7bvbvJ2ghkj/3GA=="], diff --git a/package.json b/package.json index 57d2fa4..8d7cd3a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@modelcontextprotocol/sdk": "^1.32.1", "@moduletrace/bun-sqlite": "^1.3.0", "@moduletrace/bunext": "^1.3.3", - "@moduletrace/twui": "^0.1.5", + "@moduletrace/twui": "^0.1.6", "@tiptap/extension-bubble-menu": "3.32.0", "@tiptap/extension-mention": "3.32.0", "@tiptap/extension-placeholder": "3.32.0", diff --git a/src/pages/admin/settings/general/(partials)/storage-quota-form.tsx b/src/pages/admin/settings/general/(partials)/storage-quota-form.tsx index dbcb1b0..190d1d6 100644 --- a/src/pages/admin/settings/general/(partials)/storage-quota-form.tsx +++ b/src/pages/admin/settings/general/(partials)/storage-quota-form.tsx @@ -21,7 +21,11 @@ export default function StorageQuotaForm({ storage }: Props) { const [dirty, setDirty] = useState(false); const [value, setValue] = useState(String(storage?.quota_mb ?? "")); const [loading, setLoading] = useState(false); - const [status, setStatus] = useState<{ msg?: string; error?: boolean; success?: boolean }>(); + const [status, setStatus] = useState<{ + msg?: string; + error?: boolean; + success?: boolean; + }>(); const save = async () => { setLoading(true); @@ -35,14 +39,20 @@ export default function StorageQuotaForm({ storage }: Props) { setLoading(false); if (!res?.success || !res.singleRes) { - setStatus({ error: true, msg: res?.msg || `Couldn't save the quota.` }); + setStatus({ + error: true, + msg: res?.msg || `Couldn't save the quota.`, + }); return; } setOverview(res.singleRes); setValue(String(res.singleRes.quota_mb)); setDirty(false); - setStatus({ success: true, msg: `Saved: ${res.singleRes.quota_mb} MB per folder.` }); + setStatus({ + success: true, + msg: `Saved: ${res.singleRes.quota_mb} MB per folder.`, + }); }; return ( @@ -58,13 +68,16 @@ export default function StorageQuotaForm({ storage }: Props) { label="Megabytes per folder" type="number" min={0} - step={1} - value={value} + step={8} + numberText + rawNumber + defaultValue={value} onChange={(event) => { setValue(event.target.value); setDirty(true); setStatus(undefined); }} + suffix={`MB`} info="A bot's own folder and each workspace's folder each get this much. A write past it is refused, so the bot clears space first." /> {overview ? ( diff --git a/src/pages/admin/settings/general/(partials)/system-prompt-append-form.tsx b/src/pages/admin/settings/general/(partials)/system-prompt-append-form.tsx index 5cc5885..fac5ba7 100644 --- a/src/pages/admin/settings/general/(partials)/system-prompt-append-form.tsx +++ b/src/pages/admin/settings/general/(partials)/system-prompt-append-form.tsx @@ -2,9 +2,9 @@ import { useState } from "react"; import fetchApi from "@moduletrace/twui/utils/fetch/fetchApi"; import type { APIResponseObject } from "@moduletrace/bunext/types"; import Form from "@moduletrace/twui/form/Form"; -import Textarea from "@moduletrace/twui/form/Textarea"; import Span from "@moduletrace/twui/layout/Span"; import Stack from "@moduletrace/twui/layout/Stack"; +import CodeEditor from "@/src/components/general/code-editor"; import { AppData } from "@/src/data/app-data"; import type { SystemPromptAppendOverview } from "@/src/functions/backend/db/app-settings/grab-system-prompt-append"; import SettingsSaveBar from "../../(partials)/settings-save-bar"; @@ -21,6 +21,11 @@ export default function SystemPromptAppendForm({ appendix }: Props) { const [overview, setOverview] = useState(appendix || undefined); const [dirty, setDirty] = useState(false); const [value, setValue] = useState(appendix?.text ?? ""); + /** + * The editor only reads `content` when it mounts, so a discard remounts + * it with the saved text. + */ + const [editor_key, setEditorKey] = useState(0); const [loading, setLoading] = useState(false); const [status, setStatus] = useState<{ msg?: string; error?: boolean; success?: boolean }>(); @@ -60,16 +65,15 @@ export default function SystemPromptAppendForm({ appendix }: Props) { className="w-full gap-3! items-stretch" > -