Add MindSpace visual page editor and Plaza local Tunnel deployment.

In-preview HTML editing with undo/redo sync replaces Agent patch auto-save; Plaza runs on local Mac via Cloudflare Tunnel with embed height and CSP fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
John
2026-06-15 22:57:22 -07:00
parent 6ee6fd64dd
commit 25d9c8c364
24 changed files with 1173 additions and 351 deletions
+6 -6
View File
@@ -67,28 +67,28 @@ export function usePageDraftHistory(initial: PageDraftSnapshot) {
[flushDebounced, snapshot],
);
const undo = useCallback(() => {
const undo = useCallback((): PageDraftSnapshot | null => {
flushDebounced();
const previous = pastRef.current[pastRef.current.length - 1];
if (!previous) return false;
if (!previous) return null;
pastRef.current = pastRef.current.slice(0, -1);
futureRef.current = [snapshot, ...futureRef.current];
stableRef.current = previous;
setSnapshot(previous);
bump();
return true;
return previous;
}, [flushDebounced, snapshot]);
const redo = useCallback(() => {
const redo = useCallback((): PageDraftSnapshot | null => {
flushDebounced();
const next = futureRef.current[0];
if (!next) return false;
if (!next) return null;
futureRef.current = futureRef.current.slice(1);
pastRef.current = [...pastRef.current, snapshot];
stableRef.current = next;
setSnapshot(next);
bump();
return true;
return next;
}, [flushDebounced, snapshot]);
const reset = useCallback(
-21
View File
@@ -19,7 +19,6 @@ import {
getToolConfirmation,
pushMessage,
} from '../utils/message';
import { extractMindSpacePagePatch, type MindSpacePagePatch } from '../utils/mindspacePagePatch';
function buildPageEditSummary(messages: Message[], pageTitle: string): string {
const lines = messages
@@ -45,7 +44,6 @@ export function usePageEditSubChat({
user,
enabled,
onSessionChange,
onPagePatch,
onForkUnavailable,
}: {
pageId: string;
@@ -55,7 +53,6 @@ export function usePageEditSubChat({
user?: PortalUser | null;
enabled: boolean;
onSessionChange?: (sessionId: string | null) => void;
onPagePatch?: (patch: MindSpacePagePatch) => void;
onForkUnavailable?: () => void;
}) {
const [session, setSession] = useState<Session | null>(null);
@@ -69,7 +66,6 @@ export function usePageEditSubChat({
const unsubscribeRef = useRef<(() => void) | null>(null);
const messagesRef = useRef<Message[]>([]);
const sessionRef = useRef<Session | null>(null);
const appliedPatchKeysRef = useRef(new Set<string>());
const closingRef = useRef(false);
useEffect(() => {
@@ -230,7 +226,6 @@ export function usePageEditSubChat({
setChatState('idle');
setPendingTool(null);
activeRequestId.current = null;
appliedPatchKeysRef.current.clear();
closingRef.current = false;
}
},
@@ -327,22 +322,6 @@ export function usePageEditSubChat({
};
}, [close, enabled, pageId, parentSessionId, start]);
useEffect(() => {
if (!onPagePatch) return;
if (chatState !== 'idle') return;
for (let i = messages.length - 1; i >= 0; i -= 1) {
const message = messages[i];
if (message.role !== 'assistant') continue;
const patch = extractMindSpacePagePatch(getDisplayText(message));
if (!patch) continue;
const key = `${message.id ?? i}:${JSON.stringify(patch)}`;
if (appliedPatchKeysRef.current.has(key)) return;
appliedPatchKeysRef.current.add(key);
onPagePatch(patch);
return;
}
}, [chatState, messages, onPagePatch]);
return {
session,
messages,