Edit the prompt appendix as markdown, bump twui
The install-wide appendix now uses the shared CodeEditor (AceEditor, markdown mode) instead of a plain textarea, discarding by remounting the editor with the saved text. The storage quota field moves to the twui 0.1.6 number input, so the dependency is bumped with it.
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
"@modelcontextprotocol/sdk": "^1.32.1",
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
||||||
"@moduletrace/bun-sqlite": "^1.3.0",
|
"@moduletrace/bun-sqlite": "^1.3.0",
|
||||||
"@moduletrace/bunext": "^1.3.3",
|
"@moduletrace/bunext": "^1.3.3",
|
||||||
"@moduletrace/twui": "^0.1.5",
|
"@moduletrace/twui": "^0.1.6",
|
||||||
"@tiptap/extension-bubble-menu": "3.32.0",
|
"@tiptap/extension-bubble-menu": "3.32.0",
|
||||||
"@tiptap/extension-mention": "3.32.0",
|
"@tiptap/extension-mention": "3.32.0",
|
||||||
"@tiptap/extension-placeholder": "3.32.0",
|
"@tiptap/extension-placeholder": "3.32.0",
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
|
|
||||||
"@moduletrace/bunext": ["@moduletrace/[email protected]", "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/bunext": ["@moduletrace/[email protected]", "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/[email protected].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/[email protected].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/[email protected]", "", { "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=="],
|
"@next/mdx": ["@next/[email protected]", "", { "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=="],
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@
|
|||||||
"@modelcontextprotocol/sdk": "^1.32.1",
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
||||||
"@moduletrace/bun-sqlite": "^1.3.0",
|
"@moduletrace/bun-sqlite": "^1.3.0",
|
||||||
"@moduletrace/bunext": "^1.3.3",
|
"@moduletrace/bunext": "^1.3.3",
|
||||||
"@moduletrace/twui": "^0.1.5",
|
"@moduletrace/twui": "^0.1.6",
|
||||||
"@tiptap/extension-bubble-menu": "3.32.0",
|
"@tiptap/extension-bubble-menu": "3.32.0",
|
||||||
"@tiptap/extension-mention": "3.32.0",
|
"@tiptap/extension-mention": "3.32.0",
|
||||||
"@tiptap/extension-placeholder": "3.32.0",
|
"@tiptap/extension-placeholder": "3.32.0",
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ export default function StorageQuotaForm({ storage }: Props) {
|
|||||||
const [dirty, setDirty] = useState(false);
|
const [dirty, setDirty] = useState(false);
|
||||||
const [value, setValue] = useState(String(storage?.quota_mb ?? ""));
|
const [value, setValue] = useState(String(storage?.quota_mb ?? ""));
|
||||||
const [loading, setLoading] = useState(false);
|
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 () => {
|
const save = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -35,14 +39,20 @@ export default function StorageQuotaForm({ storage }: Props) {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
if (!res?.success || !res.singleRes) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverview(res.singleRes);
|
setOverview(res.singleRes);
|
||||||
setValue(String(res.singleRes.quota_mb));
|
setValue(String(res.singleRes.quota_mb));
|
||||||
setDirty(false);
|
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 (
|
return (
|
||||||
@@ -58,13 +68,16 @@ export default function StorageQuotaForm({ storage }: Props) {
|
|||||||
label="Megabytes per folder"
|
label="Megabytes per folder"
|
||||||
type="number"
|
type="number"
|
||||||
min={0}
|
min={0}
|
||||||
step={1}
|
step={8}
|
||||||
value={value}
|
numberText
|
||||||
|
rawNumber
|
||||||
|
defaultValue={value}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setValue(event.target.value);
|
setValue(event.target.value);
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
setStatus(undefined);
|
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."
|
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 ? (
|
{overview ? (
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { useState } from "react";
|
|||||||
import fetchApi from "@moduletrace/twui/utils/fetch/fetchApi";
|
import fetchApi from "@moduletrace/twui/utils/fetch/fetchApi";
|
||||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
import Form from "@moduletrace/twui/form/Form";
|
import Form from "@moduletrace/twui/form/Form";
|
||||||
import Textarea from "@moduletrace/twui/form/Textarea";
|
|
||||||
import Span from "@moduletrace/twui/layout/Span";
|
import Span from "@moduletrace/twui/layout/Span";
|
||||||
import Stack from "@moduletrace/twui/layout/Stack";
|
import Stack from "@moduletrace/twui/layout/Stack";
|
||||||
|
import CodeEditor from "@/src/components/general/code-editor";
|
||||||
import { AppData } from "@/src/data/app-data";
|
import { AppData } from "@/src/data/app-data";
|
||||||
import type { SystemPromptAppendOverview } from "@/src/functions/backend/db/app-settings/grab-system-prompt-append";
|
import type { SystemPromptAppendOverview } from "@/src/functions/backend/db/app-settings/grab-system-prompt-append";
|
||||||
import SettingsSaveBar from "../../(partials)/settings-save-bar";
|
import SettingsSaveBar from "../../(partials)/settings-save-bar";
|
||||||
@@ -21,6 +21,11 @@ export default function SystemPromptAppendForm({ appendix }: Props) {
|
|||||||
const [overview, setOverview] = useState(appendix || undefined);
|
const [overview, setOverview] = useState(appendix || undefined);
|
||||||
const [dirty, setDirty] = useState(false);
|
const [dirty, setDirty] = useState(false);
|
||||||
const [value, setValue] = useState(appendix?.text ?? "");
|
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 [loading, setLoading] = useState(false);
|
||||||
const [status, setStatus] = useState<{ msg?: string; error?: boolean; success?: boolean }>();
|
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"
|
className="w-full gap-3! items-stretch"
|
||||||
>
|
>
|
||||||
<Stack className="w-full gap-1! items-stretch">
|
<Stack className="w-full gap-1! items-stretch">
|
||||||
<Textarea
|
<CodeEditor
|
||||||
id="system-prompt-append"
|
key={`appendix-${editor_key}`}
|
||||||
label="Appendix"
|
mode="markdown"
|
||||||
|
className="h-52"
|
||||||
title="Appendix"
|
title="Appendix"
|
||||||
showLabel
|
|
||||||
rows={6}
|
|
||||||
placeholder={"Never invent sources.\nAlways say which computer a task ran on."}
|
placeholder={"Never invent sources.\nAlways say which computer a task ran on."}
|
||||||
value={value}
|
content={value}
|
||||||
onChange={(event) => {
|
onChange={(next) => {
|
||||||
setValue(event.target.value);
|
setValue(next);
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
setStatus(undefined);
|
setStatus(undefined);
|
||||||
}}
|
}}
|
||||||
@@ -86,6 +90,7 @@ export default function SystemPromptAppendForm({ appendix }: Props) {
|
|||||||
save_label="Save appendix"
|
save_label="Save appendix"
|
||||||
onDiscard={() => {
|
onDiscard={() => {
|
||||||
setValue(overview?.text ?? "");
|
setValue(overview?.text ?? "");
|
||||||
|
setEditorKey((prev) => prev + 1);
|
||||||
setDirty(false);
|
setDirty(false);
|
||||||
setStatus(undefined);
|
setStatus(undefined);
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user