main
js 148 lines 4.1 KB
Raw
1 import { createStore } from "/js/AlpineStore.js";
2 import { callJsonApi } from "/js/api.js";
3 import { openModal, closeModal } from "/js/modals.js";
4 import {
5 toastFrontendError,
6 toastFrontendSuccess,
7 } from "/components/notifications/notification-store.js";
8 import { store as chatsStore } from "/components/sidebar/chats/chats-store.js";
9 import { store as sidebarStore } from "/components/sidebar/sidebar-store.js";
10 import { store as tasksStore } from "/components/sidebar/tasks/tasks-store.js";
11
12 const PLUGIN_ID = "_chat_naming";
13 const MODAL_PATH = `/plugins/${PLUGIN_ID}/webui/rename.html`;
14
15 const model = {
16 itemId: "",
17 kind: "chat",
18 name: "",
19 loading: false,
20 generating: false,
21 saving: false,
22
23 async openFromMenu(menuId, kind) {
24 const prefix = `${kind}:`;
25 if (typeof menuId !== "string" || !menuId.startsWith(prefix)) return;
26 this.itemId = menuId.slice(prefix.length);
27 this.kind = kind;
28 this.name = this.localName();
29 sidebarStore.rowMenuClose();
30 await openModal(MODAL_PATH);
31 },
32
33 async onOpen() {
34 if (!this.itemId) return;
35 this.loading = true;
36 try {
37 const response = await this.call("get");
38 this.name = response?.name || "";
39 } catch (error) {
40 void toastFrontendError(error?.message || "Failed to load the name.", "Chat Naming");
41 } finally {
42 this.loading = false;
43 }
44 },
45
46 async generate() {
47 if (!this.itemId || this.generating) return;
48 this.generating = true;
49 try {
50 const response = await this.call("generate");
51 this.name = response?.name || this.name;
52 } catch (error) {
53 void toastFrontendError(error?.message || "Failed to generate a name.", "Chat Naming");
54 } finally {
55 this.generating = false;
56 }
57 },
58
59 async openSettings() {
60 try {
61 const { store } = await import("/components/plugins/plugin-settings-store.js");
62 const item = this.localItem();
63 await store.openConfig(
64 PLUGIN_ID,
65 item?.project?.name || "",
66 item?.agent_profile || "",
67 );
68 } catch (error) {
69 void toastFrontendError(
70 error?.message || "Failed to open settings.",
71 "Chat Naming",
72 );
73 }
74 },
75
76 async save() {
77 const name = this.name.trim();
78 if (!this.itemId || !name || this.saving) return;
79 this.saving = true;
80 try {
81 const response = await this.call("save", { name });
82 this.name = response?.name || name;
83 this.updateLocalName(this.name);
84 await closeModal(MODAL_PATH);
85 void toastFrontendSuccess(
86 this.kind === "task" ? "Task renamed." : "Chat renamed.",
87 "Chat Naming",
88 );
89 } catch (error) {
90 void toastFrontendError(error?.message || "Failed to save the name.", "Chat Naming");
91 } finally {
92 this.saving = false;
93 }
94 },
95
96 close() {
97 return closeModal(MODAL_PATH);
98 },
99
100 call(action, extra = {}) {
101 return callJsonApi(`/plugins/${PLUGIN_ID}/chat_name`, {
102 action,
103 kind: this.kind,
104 item_id: this.itemId,
105 ...extra,
106 });
107 },
108
109 localName() {
110 const item = this.localItem();
111 return this.kind === "task" ? item?.task_name || "" : item?.name || "";
112 },
113
114 localItem() {
115 return this.kind === "task"
116 ? tasksStore.tasks.find((task) => task.id === this.itemId)
117 : chatsStore.contexts.find((context) => context.id === this.itemId);
118 },
119
120 updateLocalName(name) {
121 if (this.kind === "task") {
122 tasksStore.tasks = tasksStore.tasks.map((task) =>
123 task.id === this.itemId ? { ...task, name, task_name: name } : task,
124 );
125 return;
126 }
127 chatsStore.contexts = chatsStore.contexts.map((context) =>
128 context.id === this.itemId
129 ? {
130 ...context,
131 name,
132 ...(context.parent_context_id ? { parent_context_label: name } : {}),
133 }
134 : context,
135 );
136 if (chatsStore.selectedContext?.id === this.itemId) {
137 chatsStore.selectedContext = {
138 ...chatsStore.selectedContext,
139 name,
140 ...(chatsStore.selectedContext.parent_context_id
141 ? { parent_context_label: name }
142 : {}),
143 };
144 }
145 },
146 };
147
148 export const store = createStore("chatNaming", model);