فهرست منبع

chore(studio): remove dead BookFormCard create_book toolCall path

ChatPage 通过 /api/v1/agent 走的是 pi-agent loop,工具集是
sub_agent / write_truth_file / read / edit / grep / ls 等,从来不会
返回 toolCall.name === "create_book"。BookFormCard 的渲染条件因此
永远不成立,相关的 pendingBookArgs / bookCreating / handleCreateBook /
createProgress 一整套 store 状态也都是死代码。

实际建书走 BookCreate 独立表单页 → POST /api/v1/books/create,与
本次清理无关;CLI 仍在用的 develop_book / CREATE_BOOK_TOOL /
developBookDraft 全都在 core 端,未触动。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fanghanjun 6 ماه پیش
والد
کامیت
a85b4d1741

+ 0 - 199
packages/studio/src/components/chat/BookFormCard.tsx

@@ -1,199 +0,0 @@
-import type { Theme } from "../../hooks/use-theme";
-import { cn } from "../../lib/utils";
-import { Tool, ToolHeader, ToolContent } from "../ai-elements/tool";
-import { Loader2 } from "lucide-react";
-
-export interface BookFormArgs {
-  title?: string;
-  genre?: string;
-  platform?: string;
-  targetChapters?: number;
-  chapterWordCount?: number;
-  language?: string;
-  brief?: string;
-}
-
-export interface BookFormCardProps {
-  readonly args: BookFormArgs;
-  readonly onArgsChange: (args: BookFormArgs) => void;
-  readonly onConfirm: () => void;
-  readonly confirming: boolean;
-  readonly theme: Theme;
-}
-
-const PLATFORM_OPTIONS = [
-  { label: "番茄小说", value: "tomato" },
-  { label: "起点中文网", value: "qidian" },
-  { label: "飞卢", value: "feilu" },
-  { label: "其他", value: "other" },
-] as const;
-
-const LANGUAGE_OPTIONS = [
-  { label: "中文", value: "zh" },
-  { label: "English", value: "en" },
-] as const;
-
-const labelClass = "text-[10px] uppercase tracking-[0.18em] text-muted-foreground font-semibold";
-
-const inputClass = cn(
-  "w-full rounded-lg border border-border/60 bg-background/80 px-3 py-1.5 text-sm",
-  "outline-none focus:border-primary/50 focus:ring-2 focus:ring-primary/10 transition-all",
-  "placeholder:text-muted-foreground/40",
-);
-
-function RadioGroup({
-  options,
-  value,
-  onChange,
-  disabled,
-}: {
-  readonly options: ReadonlyArray<{ readonly label: string; readonly value: string }>;
-  readonly value: string | undefined;
-  readonly onChange: (v: string) => void;
-  readonly disabled?: boolean;
-}) {
-  return (
-    <div className="flex flex-wrap gap-2">
-      {options.map((opt) => (
-        <button
-          key={opt.value}
-          type="button"
-          onClick={() => onChange(opt.value)}
-          disabled={disabled}
-          className={cn(
-            "px-3 py-1 rounded-lg text-xs font-medium border transition-all",
-            value === opt.value
-              ? "border-primary bg-primary/10 text-primary"
-              : "border-border/60 bg-background/60 text-muted-foreground hover:border-primary/30",
-            disabled && "opacity-50 cursor-not-allowed",
-          )}
-        >
-          {opt.label}
-        </button>
-      ))}
-    </div>
-  );
-}
-
-export function BookFormCard({ args, onArgsChange, onConfirm, confirming }: BookFormCardProps) {
-  const disabled = confirming;
-  const update = <K extends keyof BookFormArgs>(key: K, value: BookFormArgs[K]) => {
-    if (disabled) return;
-    onArgsChange({ ...args, [key]: value });
-  };
-
-  const disabledInput = disabled ? "opacity-60 cursor-not-allowed" : "";
-  const toolState = confirming ? "input-available" : "approval-requested";
-
-  return (
-    <Tool defaultOpen>
-      <ToolHeader
-        title="创建新书"
-        type="tool-invocation"
-        state={toolState}
-      />
-      <ToolContent>
-        <div className={cn("space-y-4", disabled && "pointer-events-none opacity-80")}>
-          {/* 书名 */}
-          <div className="space-y-1.5">
-            <label className={labelClass}>书名</label>
-            <input
-              type="text"
-              value={args.title ?? ""}
-              onChange={(e) => update("title", e.target.value)}
-              placeholder="输入书名"
-              disabled={disabled}
-              className={cn(inputClass, disabledInput)}
-            />
-          </div>
-
-          {/* 题材 */}
-          <div className="space-y-1.5">
-            <label className={labelClass}>题材</label>
-            <input
-              type="text"
-              value={args.genre ?? ""}
-              onChange={(e) => update("genre", e.target.value)}
-              placeholder="如 xuanhuan、urban、romance"
-              disabled={disabled}
-              className={cn(inputClass, disabledInput)}
-            />
-          </div>
-
-          {/* 目标平台 */}
-          <div className="space-y-1.5">
-            <label className={labelClass}>目标平台</label>
-            <RadioGroup
-              options={PLATFORM_OPTIONS}
-              value={args.platform}
-              onChange={(v) => update("platform", v)}
-              disabled={disabled}
-            />
-          </div>
-
-          {/* 目标章数 + 每章字数 */}
-          <div className="grid grid-cols-2 gap-3">
-            <div className="space-y-1.5">
-              <label className={labelClass}>目标章数</label>
-              <input
-                type="number"
-                value={args.targetChapters ?? ""}
-                onChange={(e) => update("targetChapters", e.target.value ? Number(e.target.value) : undefined)}
-                placeholder="如 200"
-                disabled={disabled}
-                className={cn(inputClass, disabledInput)}
-              />
-            </div>
-            <div className="space-y-1.5">
-              <label className={labelClass}>每章字数</label>
-              <input
-                type="number"
-                value={args.chapterWordCount ?? ""}
-                onChange={(e) => update("chapterWordCount", e.target.value ? Number(e.target.value) : undefined)}
-                placeholder="如 2000"
-                disabled={disabled}
-                className={cn(inputClass, disabledInput)}
-              />
-            </div>
-          </div>
-
-          {/* 写作语言 */}
-          <div className="space-y-1.5">
-            <label className={labelClass}>写作语言</label>
-            <RadioGroup
-              options={LANGUAGE_OPTIONS}
-              value={args.language}
-              onChange={(v) => update("language", v)}
-              disabled={disabled}
-            />
-          </div>
-
-          {/* 创意简述 */}
-          <div className="space-y-1.5">
-            <label className={labelClass}>创意简述</label>
-            <div className={cn(
-              "rounded-lg border border-border/60 bg-background/80 px-3 py-2 text-sm leading-7 whitespace-pre-wrap",
-              disabled ? "opacity-60" : "",
-            )}>
-              {args.brief || <span className="text-muted-foreground/40">AI 会根据你的描述自动生成</span>}
-            </div>
-          </div>
-        </div>
-
-        {/* 确认按钮 */}
-        <div className="flex items-center justify-between pt-4 border-t border-border/40 mt-4">
-          <p className="text-xs text-muted-foreground">确认后将由 Architect 生成完整 foundation</p>
-          <button
-            type="button"
-            onClick={onConfirm}
-            disabled={confirming}
-            className="flex items-center gap-1.5 px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-medium hover:opacity-90 active:scale-[0.98] transition-all disabled:opacity-50 disabled:cursor-not-allowed"
-          >
-            {confirming && <Loader2 size={14} className="animate-spin" />}
-            {confirming ? "创建中…" : "开始写这本书"}
-          </button>
-        </div>
-      </ToolContent>
-    </Tool>
-  );
-}

+ 1 - 37
packages/studio/src/components/chat/ChatMessage.tsx

@@ -1,51 +1,25 @@
 import type { Theme } from "../../hooks/use-theme";
-import { cn } from "../../lib/utils";
 import {
   Message,
   MessageContent,
   MessageResponse,
 } from "../ai-elements/message";
-import { BookFormCard } from "./BookFormCard";
-import type { BookFormArgs } from "./BookFormCard";
-import {
-  CheckCircle2,
-  XCircle,
-  Loader2,
-} from "lucide-react";
-
-export interface ToolCall {
-  readonly name: string;
-  readonly arguments: Record<string, unknown>;
-}
+import { XCircle } from "lucide-react";
 
 export interface ChatMessageProps {
   readonly role: "user" | "assistant";
   readonly content: string;
   readonly timestamp: number;
   readonly theme: Theme;
-  readonly toolCall?: ToolCall;
-  readonly onArgsChange?: (args: Record<string, unknown>) => void;
-  readonly onConfirm?: () => void;
-  readonly confirming?: boolean;
 }
 
 export function ChatMessage({
   role,
   content,
-  timestamp,
-  theme,
-  toolCall,
-  onArgsChange,
-  onConfirm,
-  confirming,
 }: ChatMessageProps) {
   const isUser = role === "user";
-  const isStatus = content.startsWith("\u22EF");
-  const isSuccess = content.startsWith("\u2713");
   const isError = content.startsWith("\u2717");
 
-  const hasBookForm = toolCall?.name === "create_book" && onArgsChange && onConfirm;
-
   return (
     <Message from={role}>
       <MessageContent>
@@ -60,16 +34,6 @@ export function ChatMessage({
           <MessageResponse>{content}</MessageResponse>
         )}
       </MessageContent>
-
-      {hasBookForm && (
-        <BookFormCard
-          args={toolCall.arguments as BookFormArgs}
-          onArgsChange={(a) => onArgsChange(a as Record<string, unknown>)}
-          onConfirm={onConfirm}
-          confirming={confirming ?? false}
-          theme={theme}
-        />
-      )}
     </Message>
   );
 }

+ 2 - 110
packages/studio/src/pages/ChatPage.tsx

@@ -2,7 +2,6 @@ import { useRef, useEffect, useMemo, useState } from "react";
 import type { Theme } from "../hooks/use-theme";
 import type { TFunction } from "../hooks/use-i18n";
 import type { SSEMessage } from "../hooks/use-sse";
-import { useApi } from "../hooks/use-api";
 import { chatSelectors, useChatStore } from "../store/chat";
 import { useServiceStore } from "../store/service";
 import {
@@ -32,7 +31,6 @@ import {
   MessageContent,
 } from "../components/ai-elements/message";
 import {
-  clearBookCreateSessionId,
   filterModelGroups,
   getBookCreateSessionId,
   setBookCreateSessionId,
@@ -58,22 +56,15 @@ export interface ChatPageProps {
 
 export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPageProps) {
   // -- Store selectors --
-  const activeSession = useChatStore(chatSelectors.activeSession);
   const messages = useChatStore(chatSelectors.activeMessages);
   const activeSessionId = useChatStore((s) => s.activeSessionId);
   const input = useChatStore((s) => s.input);
   const loading = useChatStore(chatSelectors.isActiveSessionStreaming);
-  const pendingBookArgs = activeSession?.pendingBookArgs ?? null;
-  const bookCreating = useChatStore((s) => s.bookCreating);
-  const createProgress = useChatStore((s) => s.createProgress);
   const selectedModel = useChatStore((s) => s.selectedModel);
   const selectedService = useChatStore((s) => s.selectedService);
   // -- Store actions --
   const setInput = useChatStore((s) => s.setInput);
   const sendMessage = useChatStore((s) => s.sendMessage);
-  const setPendingBookArgs = useChatStore((s) => s.setPendingBookArgs);
-  const handleCreateBook = useChatStore((s) => s.handleCreateBook);
-  const setCreateProgress = useChatStore((s) => s.setCreateProgress);
   const setSelectedModel = useChatStore((s) => s.setSelectedModel);
   const loadSessionList = useChatStore((s) => s.loadSessionList);
   const createSession = useChatStore((s) => s.createSession);
@@ -142,29 +133,12 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
     el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
   }, [input]);
 
-  // Auto-scroll on new messages or progress updates
+  // Auto-scroll on new messages
   useEffect(() => {
     if (scrollRef.current) {
       scrollRef.current.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" });
     }
-  }, [messages, createProgress]);
-
-  // Listen for pipeline log events during book creation
-  useEffect(() => {
-    if (!bookCreating) {
-      setCreateProgress("");
-      return;
-    }
-    const es = new EventSource("/api/v1/events");
-    es.addEventListener("log", (e: MessageEvent) => {
-      try {
-        const data = e.data ? JSON.parse(e.data) : null;
-        const msg = data?.message as string | undefined;
-        if (msg) setCreateProgress(msg);
-      } catch { /* ignore */ }
-    });
-    return () => { es.close(); };
-  }, [bookCreating, setCreateProgress]);
+  }, [messages]);
 
   // Entering a book loads its latest session; book-create mode persists its orphan session in localStorage.
   useEffect(() => {
@@ -221,15 +195,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
     void sendMessage(activeSessionId, text, activeBookId);
   };
 
-  const onCreateBook = async () => {
-    if (!activeSessionId) return;
-    const newBookId = await handleCreateBook(activeSessionId, activeBookId);
-    if (newBookId) {
-      clearBookCreateSessionId();
-      nav.toBook(newBookId);
-    }
-  };
-
   const handleQuickAction = (command: string) => {
     if (!activeSessionId) return;
     void sendMessage(activeSessionId, command, activeBookId);
@@ -312,16 +277,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
                               content={item.part.content}
                               timestamp={msg.timestamp}
                               theme={theme}
-                              toolCall={msg.toolCall?.name === "create_book" && pendingBookArgs
-                                ? { name: msg.toolCall.name, arguments: pendingBookArgs }
-                                : msg.toolCall}
-                              onArgsChange={msg.toolCall?.name === "create_book"
-                                ? (args) => setPendingBookArgs(args)
-                                : undefined}
-                              onConfirm={msg.toolCall?.name === "create_book"
-                                ? () => void onCreateBook()
-                                : undefined}
-                              confirming={msg.toolCall?.name === "create_book" ? bookCreating : undefined}
                             />
                           );
                         }
@@ -336,16 +291,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
                     content={msg.content}
                     timestamp={msg.timestamp}
                     theme={theme}
-                    toolCall={msg.toolCall?.name === "create_book" && pendingBookArgs
-                      ? { name: msg.toolCall.name, arguments: pendingBookArgs }
-                      : msg.toolCall}
-                    onArgsChange={msg.toolCall?.name === "create_book"
-                      ? (args) => setPendingBookArgs(args)
-                      : undefined}
-                    onConfirm={msg.toolCall?.name === "create_book"
-                      ? () => void onCreateBook()
-                      : undefined}
-                    confirming={msg.toolCall?.name === "create_book" ? bookCreating : undefined}
                   />
                 )}
               </div>
@@ -362,22 +307,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
               </Message>
             )}
 
-            {/* Book creation progress */}
-            {bookCreating && (
-              <div className="flex gap-3 items-start">
-                <div className="w-7 h-7 rounded-lg bg-primary/10 flex items-center justify-center shrink-0">
-                  <Loader2 size={14} className="text-primary animate-spin" />
-                </div>
-                <div className="bg-card border border-border/50 px-4 py-3 rounded-2xl rounded-tl-sm text-sm space-y-1">
-                  <div className="font-medium text-foreground">{isZh ? "\u6B63\u5728\u521B\u5EFA\u4E66\u7C4D..." : "Creating book..."}</div>
-                  {createProgress && (
-                    <div className="text-xs text-muted-foreground font-mono truncate max-w-md">
-                      {createProgress}
-                    </div>
-                  )}
-                </div>
-              </div>
-            )}
           </div>
         )}
       </div>
@@ -396,42 +325,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
       {/* Input area */}
       <div className="shrink-0 border-t border-border/40 px-4 py-3">
         <div className="max-w-3xl mx-auto">
-          {pendingBookArgs && !loading ? (
-            /* create_book tool call pending — show action buttons */
-            <div className="flex items-center gap-3">
-              <button
-                type="button"
-                onClick={() => void onCreateBook()}
-                disabled={bookCreating}
-                className="flex items-center gap-1.5 px-5 py-2.5 rounded-xl bg-primary text-primary-foreground text-sm font-medium hover:opacity-90 active:scale-[0.98] transition-all disabled:opacity-50"
-              >
-                {bookCreating && <Loader2 size={14} className="animate-spin" />}
-                {bookCreating ? "创建中…" : "开始写这本书"}
-              </button>
-              <div className="flex-1 flex items-center gap-2 rounded-xl border border-border/40 bg-secondary/30 px-3 py-2">
-                <input
-                  type="text"
-                  value={input}
-                  onChange={(e) => setInput(e.target.value)}
-                  onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); onSend(input); } }}
-                  placeholder={isZh ? "或输入修改要求…" : "Or type changes..."}
-                  disabled={!activeSessionId}
-                  className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground/50"
-                />
-                {input.trim() && (
-                  <button
-                    type="button"
-                    onClick={() => onSend(input)}
-                    disabled={!activeSessionId}
-                    className="w-7 h-7 rounded-lg bg-primary text-primary-foreground flex items-center justify-center shrink-0 hover:scale-105 active:scale-95 transition-all"
-                  >
-                    <ArrowUp size={12} strokeWidth={2.5} />
-                  </button>
-                )}
-              </div>
-            </div>
-          ) : (
-            /* Normal input */
             <div className="rounded-xl bg-secondary/30 transition-all">
               <div className="flex items-center gap-2 px-3 py-2">
                 <textarea
@@ -482,7 +375,6 @@ export function ChatPage({ activeBookId, nav, theme, t, sse: _sse }: ChatPagePro
                 )}
               </div>
             </div>
-          )}
         </div>
       </div>
     </div>

+ 0 - 3
packages/studio/src/store/chat/selectors.ts

@@ -3,9 +3,6 @@ import type { ChatState } from "./types";
 const EMPTY_MESSAGES: readonly [] = [];
 
 export const chatSelectors = {
-  hasPendingTool: (s: ChatState) =>
-    Boolean(s.activeSessionId && s.sessions[s.activeSessionId]?.pendingBookArgs),
-  isCreating: (s: ChatState) => s.bookCreating,
   activeSession: (s: ChatState) => (s.activeSessionId ? s.sessions[s.activeSessionId] ?? null : null),
   activeMessages: (s: ChatState) =>
     (s.activeSessionId ? s.sessions[s.activeSessionId]?.messages : undefined) ?? EMPTY_MESSAGES,

+ 2 - 81
packages/studio/src/store/chat/slices/create/action.ts

@@ -1,89 +1,10 @@
 import type { StateCreator } from "zustand";
-import type { ChatStore, CreateActions, AgentResponse } from "../../types";
-import { fetchJson } from "../../../../hooks/use-api";
-import { bookKey } from "../message/runtime";
-
-export const createCreateSlice: StateCreator<ChatStore, [], [], CreateActions> = (set, get) => ({
-  setPendingBookArgs: (args) =>
-    set((state) => {
-      if (!state.activeSessionId) return {};
-      return {
-        sessions: {
-          ...state.sessions,
-          [state.activeSessionId]: {
-            ...state.sessions[state.activeSessionId],
-            pendingBookArgs: args,
-          },
-        },
-      };
-    }),
-  setBookCreating: (creating) => set({ bookCreating: creating }),
-  setCreateProgress: (progress) => set({ createProgress: progress }),
+import type { ChatStore, CreateActions } from "../../types";
 
+export const createCreateSlice: StateCreator<ChatStore, [], [], CreateActions> = (set) => ({
   bumpBookDataVersion: () => set((s) => ({ bookDataVersion: s.bookDataVersion + 1 })),
   openArtifact: (file) => set({ sidebarView: "artifact", artifactFile: file, artifactChapter: null }),
   openChapterArtifact: (chapterNum) => set({ sidebarView: "artifact", artifactFile: null, artifactChapter: chapterNum }),
   closeArtifact: () => set({ sidebarView: "panel", artifactFile: null, artifactChapter: null }),
   setBookSummary: (summary) => set({ bookSummary: summary }),
-
-  handleCreateBook: async (sessionId, activeBookId) => {
-    const session = get().sessions[sessionId];
-    if (!session?.pendingBookArgs) return null;
-
-    set({ bookCreating: true });
-    try {
-      const data = await fetchJson<AgentResponse>("/agent", {
-        method: "POST",
-        headers: { "Content-Type": "application/json" },
-        body: JSON.stringify({ instruction: "/create", activeBookId, sessionId }),
-      });
-      const newBookId = data.session?.activeBookId ?? null;
-      if (newBookId) {
-        set((state) => {
-          const session = state.sessions[sessionId];
-          if (!session) {
-            return {};
-          }
-
-          const previousIds = state.sessionIdsByBook[bookKey(session.bookId)] ?? [];
-          const nextIds = state.sessionIdsByBook[newBookId] ?? [];
-
-          return {
-            sessions: {
-              ...state.sessions,
-              [sessionId]: {
-                ...session,
-                bookId: newBookId,
-                pendingBookArgs: null,
-              },
-            },
-            sessionIdsByBook: {
-              ...state.sessionIdsByBook,
-              [bookKey(session.bookId)]: previousIds.filter((id) => id !== sessionId),
-              [newBookId]: nextIds.includes(sessionId) ? nextIds : [sessionId, ...nextIds],
-            },
-          };
-        });
-        get().bumpBookDataVersion();
-      }
-      set((state) => {
-        if (!state.sessions[sessionId]) return {};
-        return {
-          sessions: {
-            ...state.sessions,
-            [sessionId]: {
-              ...state.sessions[sessionId],
-              pendingBookArgs: null,
-            },
-          },
-        };
-      });
-      return newBookId;
-    } catch (e) {
-      get().addErrorMessage(sessionId, e instanceof Error ? e.message : String(e));
-      return null;
-    } finally {
-      set({ bookCreating: false });
-    }
-  },
 });

+ 0 - 2
packages/studio/src/store/chat/slices/create/initialState.ts

@@ -1,8 +1,6 @@
 import type { CreateState } from "../../types";
 
 export const initialCreateState: CreateState = {
-  bookCreating: false,
-  createProgress: "",
   bookDataVersion: 0,
   sidebarView: "panel",
   artifactFile: null,

+ 0 - 7
packages/studio/src/store/chat/slices/message/action.ts

@@ -385,13 +385,6 @@ export const createMessageSlice: StateCreator<ChatStore, [], [], MessageActions>
             })),
           }));
         }
-        if (toolCall?.name === "create_book") {
-          set((state) => ({
-            sessions: updateSession(state.sessions, sessionId, () => ({
-              pendingBookArgs: { ...toolCall.arguments },
-            })),
-          }));
-        }
       } else {
         const emptyMessage = "模型未返回文本内容。请检查协议类型(chat/responses)、流式开关或上游服务兼容性。";
         if (hasStream) {

+ 0 - 1
packages/studio/src/store/chat/slices/message/runtime.ts

@@ -139,7 +139,6 @@ export function createSessionRuntime(input: {
     stream: null,
     isStreaming: false,
     lastError: null,
-    pendingBookArgs: null,
     isDraft: input.isDraft ?? false,
   };
 }

+ 0 - 7
packages/studio/src/store/chat/types.ts

@@ -110,7 +110,6 @@ export interface SessionRuntime {
   readonly stream: EventSource | null;
   readonly isStreaming: boolean;
   readonly lastError: string | null;
-  readonly pendingBookArgs: Record<string, unknown> | null;
   // 仅前端存在、尚未持久化到磁盘的草稿会话。发送第一条消息时才调 POST /sessions 把它落盘。
   readonly isDraft: boolean;
 }
@@ -125,8 +124,6 @@ export interface MessageState {
 }
 
 export interface CreateState {
-  bookCreating: boolean;
-  createProgress: string;
   bookDataVersion: number;
   sidebarView: "panel" | "artifact";
   artifactFile: string | null;         // foundation file name, e.g. "story_bible.md"
@@ -158,10 +155,6 @@ export interface MessageActions {
 }
 
 export interface CreateActions {
-  setPendingBookArgs: (args: Record<string, unknown> | null) => void;
-  setBookCreating: (creating: boolean) => void;
-  setCreateProgress: (progress: string) => void;
-  handleCreateBook: (sessionId: string, activeBookId?: string) => Promise<string | null>;
   bumpBookDataVersion: () => void;
   openArtifact: (file: string) => void;
   openChapterArtifact: (chapterNum: number) => void;