@elizaos/client 1.5.5-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +350 -0
- package/dist/assets/empty-module-CLMscLYw.js +1 -0
- package/dist/assets/main-BBZ_3lkn.css +5999 -0
- package/dist/assets/main-C5zNUkXH.js +7 -0
- package/dist/assets/main-Dz64ENQg.js +614 -0
- package/dist/assets/react-vendor-DM5m98rr.js +545 -0
- package/dist/assets/ui-vendor-BQCqNqg0.js +1 -0
- package/dist/elizaos-avatar.png +0 -0
- package/dist/elizaos-icon.png +0 -0
- package/dist/elizaos-logo-light.png +0 -0
- package/dist/elizaos.webp +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/images/agents/agent1.png +0 -0
- package/dist/images/agents/agent2.png +0 -0
- package/dist/images/agents/agent3.png +0 -0
- package/dist/images/agents/agent4.png +0 -0
- package/dist/images/agents/agent5.png +0 -0
- package/dist/index.html +14 -0
- package/index.html +24 -0
- package/package.json +159 -0
- package/postcss.config.js +3 -0
- package/public/elizaos-avatar.png +0 -0
- package/public/elizaos-icon.png +0 -0
- package/public/elizaos-logo-light.png +0 -0
- package/public/elizaos.webp +0 -0
- package/public/favicon.ico +0 -0
- package/public/images/agents/agent1.png +0 -0
- package/public/images/agents/agent2.png +0 -0
- package/public/images/agents/agent3.png +0 -0
- package/public/images/agents/agent4.png +0 -0
- package/public/images/agents/agent5.png +0 -0
- package/src/App.tsx +222 -0
- package/src/components/AgentDetailsPanel.tsx +147 -0
- package/src/components/ChatInputArea.tsx +196 -0
- package/src/components/ChatMessageListComponent.tsx +139 -0
- package/src/components/actionTool.tsx +186 -0
- package/src/components/add-agent-card.tsx +77 -0
- package/src/components/agent-action-viewer.tsx +816 -0
- package/src/components/agent-avatar-stack.tsx +121 -0
- package/src/components/agent-card.cy.tsx +259 -0
- package/src/components/agent-card.tsx +177 -0
- package/src/components/agent-creator.tsx +142 -0
- package/src/components/agent-log-viewer.tsx +645 -0
- package/src/components/agent-memory-edit-overlay.tsx +461 -0
- package/src/components/agent-memory-viewer.tsx +504 -0
- package/src/components/agent-settings.tsx +270 -0
- package/src/components/agent-sidebar.tsx +178 -0
- package/src/components/api-key-dialog.tsx +113 -0
- package/src/components/app-sidebar.tsx +685 -0
- package/src/components/array-input.tsx +116 -0
- package/src/components/audio-recorder.tsx +292 -0
- package/src/components/avatar-panel.tsx +141 -0
- package/src/components/character-form.tsx +1138 -0
- package/src/components/chat.tsx +1813 -0
- package/src/components/combobox.tsx +187 -0
- package/src/components/confirmation-dialog.tsx +59 -0
- package/src/components/connection-error-banner.tsx +101 -0
- package/src/components/connection-status.cy.tsx +73 -0
- package/src/components/connection-status.tsx +155 -0
- package/src/components/copy-button.tsx +35 -0
- package/src/components/delete-button.tsx +24 -0
- package/src/components/env-settings.tsx +261 -0
- package/src/components/group-card.tsx +160 -0
- package/src/components/group-panel.tsx +543 -0
- package/src/components/input-copy.tsx +21 -0
- package/src/components/logs-page.tsx +41 -0
- package/src/components/media-content.tsx +385 -0
- package/src/components/memory-graph.tsx +170 -0
- package/src/components/missing-secrets-dialog.tsx +72 -0
- package/src/components/onboarding-tour.tsx +247 -0
- package/src/components/page-title.tsx +8 -0
- package/src/components/plugins-panel.tsx +383 -0
- package/src/components/profile-card.tsx +66 -0
- package/src/components/profile-overlay.tsx +283 -0
- package/src/components/retry-button.tsx +28 -0
- package/src/components/secret-panel.tsx +1505 -0
- package/src/components/server-management.tsx +264 -0
- package/src/components/split-button.tsx +148 -0
- package/src/components/stop-agent-button.tsx +99 -0
- package/src/components/ui/alert-dialog.cy.tsx +333 -0
- package/src/components/ui/alert-dialog.tsx +115 -0
- package/src/components/ui/alert.tsx +49 -0
- package/src/components/ui/avatar.cy.tsx +180 -0
- package/src/components/ui/avatar.tsx +57 -0
- package/src/components/ui/badge.cy.tsx +146 -0
- package/src/components/ui/badge.tsx +43 -0
- package/src/components/ui/button.cy.tsx +177 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/card.cy.tsx +160 -0
- package/src/components/ui/card.tsx +73 -0
- package/src/components/ui/chat/animated-markdown.tsx +59 -0
- package/src/components/ui/chat/chat-bubble.tsx +178 -0
- package/src/components/ui/chat/chat-container.tsx +51 -0
- package/src/components/ui/chat/chat-input.cy.tsx +169 -0
- package/src/components/ui/chat/chat-input.tsx +47 -0
- package/src/components/ui/chat/chat-message-list.tsx +61 -0
- package/src/components/ui/chat/chat-tts-button.tsx +199 -0
- package/src/components/ui/chat/code-block.tsx +79 -0
- package/src/components/ui/chat/expandable-chat.tsx +131 -0
- package/src/components/ui/chat/hooks/useAutoScroll.ts +86 -0
- package/src/components/ui/chat/markdown.tsx +209 -0
- package/src/components/ui/chat/message-loading.tsx +48 -0
- package/src/components/ui/checkbox.cy.tsx +170 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/collapsible.cy.tsx +283 -0
- package/src/components/ui/collapsible.tsx +9 -0
- package/src/components/ui/command.cy.tsx +313 -0
- package/src/components/ui/command.tsx +143 -0
- package/src/components/ui/dialog.cy.tsx +279 -0
- package/src/components/ui/dialog.tsx +104 -0
- package/src/components/ui/dropdown-menu.cy.tsx +273 -0
- package/src/components/ui/dropdown-menu.tsx +281 -0
- package/src/components/ui/input.cy.tsx +82 -0
- package/src/components/ui/input.tsx +27 -0
- package/src/components/ui/label.cy.tsx +157 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/resizable.tsx +42 -0
- package/src/components/ui/scroll-area.cy.tsx +242 -0
- package/src/components/ui/scroll-area.tsx +46 -0
- package/src/components/ui/select.cy.tsx +277 -0
- package/src/components/ui/select.tsx +155 -0
- package/src/components/ui/separator.cy.tsx +145 -0
- package/src/components/ui/separator.tsx +29 -0
- package/src/components/ui/sheet.cy.tsx +324 -0
- package/src/components/ui/sheet.tsx +119 -0
- package/src/components/ui/sidebar.tsx +734 -0
- package/src/components/ui/skeleton.cy.tsx +149 -0
- package/src/components/ui/skeleton.tsx +17 -0
- package/src/components/ui/split-button.cy.tsx +274 -0
- package/src/components/ui/split-button.tsx +112 -0
- package/src/components/ui/switch.tsx +28 -0
- package/src/components/ui/tabs.cy.tsx +271 -0
- package/src/components/ui/tabs.tsx +53 -0
- package/src/components/ui/textarea.cy.tsx +136 -0
- package/src/components/ui/textarea.tsx +26 -0
- package/src/components/ui/toast.cy.tsx +209 -0
- package/src/components/ui/toast.tsx +126 -0
- package/src/components/ui/toaster.tsx +29 -0
- package/src/components/ui/tooltip.cy.tsx +244 -0
- package/src/components/ui/tooltip.tsx +30 -0
- package/src/config/agent-templates.ts +349 -0
- package/src/config/voice-models.ts +181 -0
- package/src/constants.ts +23 -0
- package/src/context/AuthContext.tsx +44 -0
- package/src/context/ConnectionContext.tsx +194 -0
- package/src/entry.tsx +9 -0
- package/src/hooks/__tests__/use-agent-tab-state.test.ts +137 -0
- package/src/hooks/__tests__/use-agent-update.test.tsx +250 -0
- package/src/hooks/__tests__/use-character-convert.test.ts +102 -0
- package/src/hooks/__tests__/use-panel-width-state.test.ts +243 -0
- package/src/hooks/__tests__/use-sidebar-state.test.ts +117 -0
- package/src/hooks/use-agent-management.ts +130 -0
- package/src/hooks/use-agent-tab-state.ts +74 -0
- package/src/hooks/use-agent-update.ts +469 -0
- package/src/hooks/use-character-convert.ts +138 -0
- package/src/hooks/use-confirmation.ts +55 -0
- package/src/hooks/use-delete-agent.ts +123 -0
- package/src/hooks/use-dm-channels.ts +198 -0
- package/src/hooks/use-elevenlabs-voices.ts +83 -0
- package/src/hooks/use-file-upload.ts +224 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/hooks/use-onboarding.tsx +49 -0
- package/src/hooks/use-panel-width-state.ts +147 -0
- package/src/hooks/use-partial-update.ts +288 -0
- package/src/hooks/use-plugin-details.ts +462 -0
- package/src/hooks/use-plugins.ts +119 -0
- package/src/hooks/use-query-hooks.ts +1263 -0
- package/src/hooks/use-server-agents.ts +62 -0
- package/src/hooks/use-server-version.tsx +47 -0
- package/src/hooks/use-sidebar-state.ts +50 -0
- package/src/hooks/use-socket-chat.ts +264 -0
- package/src/hooks/use-toast.ts +260 -0
- package/src/hooks/use-version.tsx +64 -0
- package/src/index.css +146 -0
- package/src/lib/api-client-config.ts +53 -0
- package/src/lib/api-type-mappers.ts +196 -0
- package/src/lib/export-utils.ts +123 -0
- package/src/lib/logger.ts +19 -0
- package/src/lib/media-utils.ts +170 -0
- package/src/lib/pca.test.ts +17 -0
- package/src/lib/pca.ts +52 -0
- package/src/lib/socketio-manager.ts +664 -0
- package/src/lib/utils.ts +168 -0
- package/src/main.tsx +16 -0
- package/src/mocks/empty-module.ts +12 -0
- package/src/mocks/node-module.ts +57 -0
- package/src/polyfills.ts +37 -0
- package/src/routes/agent-detail.tsx +30 -0
- package/src/routes/agent-list.tsx +27 -0
- package/src/routes/agent-settings.tsx +48 -0
- package/src/routes/character-detail.tsx +52 -0
- package/src/routes/character-form.tsx +79 -0
- package/src/routes/character-list.tsx +38 -0
- package/src/routes/chat.tsx +128 -0
- package/src/routes/createAgent.tsx +13 -0
- package/src/routes/group-new.tsx +50 -0
- package/src/routes/group.tsx +29 -0
- package/src/routes/home.tsx +218 -0
- package/src/routes/not-found.tsx +71 -0
- package/src/test/setup.ts +154 -0
- package/src/types/crypto-browserify.d.ts +4 -0
- package/src/types/index.ts +13 -0
- package/src/types/rooms.ts +8 -0
- package/src/types.ts +84 -0
- package/src/vite-env.d.ts +40 -0
- package/tailwind.config.ts +90 -0
- package/tsconfig.json +10 -0
- package/vite.config.ts +102 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { usePartialUpdate } from '@/hooks/use-partial-update';
|
|
2
|
+
import type { Agent, Character } from '@elizaos/core';
|
|
3
|
+
import { useCallback, useRef } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A custom hook for handling Agent updates with specific handling for JSONb fields.
|
|
7
|
+
* This hook builds on usePartialUpdate but adds Agent-specific convenience methods
|
|
8
|
+
* organized by the UI tabs (Basic Info, Content, Style, Plugins, etc.).
|
|
9
|
+
*
|
|
10
|
+
* @param initialAgent The initial Agent object
|
|
11
|
+
* @returns Object with agent state and update methods
|
|
12
|
+
*/
|
|
13
|
+
export function useAgentUpdate(initialAgent: Agent) {
|
|
14
|
+
// Keep reference to the initial state for comparison
|
|
15
|
+
const initialAgentRef = useRef<Agent>(JSON.parse(JSON.stringify(initialAgent)));
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
value: agent,
|
|
19
|
+
updateField,
|
|
20
|
+
addArrayItem,
|
|
21
|
+
removeArrayItem,
|
|
22
|
+
reset,
|
|
23
|
+
updateSettings,
|
|
24
|
+
} = usePartialUpdate(initialAgent);
|
|
25
|
+
|
|
26
|
+
// ==================== Template Import Function ====================
|
|
27
|
+
/**
|
|
28
|
+
* Imports a full agent template - overwrites all fields
|
|
29
|
+
*
|
|
30
|
+
* @param templateAgent The agent template to import
|
|
31
|
+
*/
|
|
32
|
+
const importAgent = useCallback(
|
|
33
|
+
(templateAgent: Character) => {
|
|
34
|
+
// For each top-level property in the template, update it in the current agent
|
|
35
|
+
Object.entries(templateAgent).forEach(([key, value]) => {
|
|
36
|
+
if (key === 'settings' && value) {
|
|
37
|
+
// Handle settings object specially to preserve existing settings not in template
|
|
38
|
+
updateSettings({
|
|
39
|
+
...agent.settings,
|
|
40
|
+
...value,
|
|
41
|
+
});
|
|
42
|
+
} else if (key === 'style' && value) {
|
|
43
|
+
// Handle style object specially - it's nested but needs direct update
|
|
44
|
+
updateField('style', {
|
|
45
|
+
all: value.all || [],
|
|
46
|
+
chat: value.chat || [],
|
|
47
|
+
post: value.post || [],
|
|
48
|
+
});
|
|
49
|
+
} else if (Array.isArray(value)) {
|
|
50
|
+
// Handle arrays directly to ensure they fully replace existing arrays
|
|
51
|
+
updateField(key, [...value]);
|
|
52
|
+
} else {
|
|
53
|
+
// For other fields, directly update
|
|
54
|
+
updateField(key, value);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
[agent.settings, updateField, updateSettings]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// ==================== Basic Info Tab ====================
|
|
62
|
+
/**
|
|
63
|
+
* Updates a field in the Agent's settings object
|
|
64
|
+
*
|
|
65
|
+
* @param path Path within settings (e.g., 'voice.model')
|
|
66
|
+
* @param value New value
|
|
67
|
+
*/
|
|
68
|
+
const updateSetting = useCallback(
|
|
69
|
+
<T>(path: string, value: T) => {
|
|
70
|
+
updateField(`settings.${path}`, value);
|
|
71
|
+
},
|
|
72
|
+
[updateField]
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Updates the entire settings object
|
|
77
|
+
*
|
|
78
|
+
* @param settings The new settings object
|
|
79
|
+
*/
|
|
80
|
+
const setSettings = useCallback(
|
|
81
|
+
(settings: any) => {
|
|
82
|
+
updateSettings(settings);
|
|
83
|
+
},
|
|
84
|
+
[updateSettings]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Updates the agent's system prompt
|
|
89
|
+
*
|
|
90
|
+
* @param systemPrompt The new system prompt
|
|
91
|
+
*/
|
|
92
|
+
const updateSystemPrompt = useCallback(
|
|
93
|
+
(systemPrompt: string) => {
|
|
94
|
+
updateField('system', systemPrompt);
|
|
95
|
+
},
|
|
96
|
+
[updateField]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// ==================== Secrets Tab ====================
|
|
100
|
+
/**
|
|
101
|
+
* Updates a secret in the Agent's settings.secrets object
|
|
102
|
+
*
|
|
103
|
+
* @param key Secret key
|
|
104
|
+
* @param value Secret value
|
|
105
|
+
*/
|
|
106
|
+
const updateSecret = useCallback(
|
|
107
|
+
(key: string, value: string) => {
|
|
108
|
+
// Handle nested secrets object properly
|
|
109
|
+
const currentSettings = agent.settings || {};
|
|
110
|
+
const currentSecretsRaw = currentSettings.secrets || {};
|
|
111
|
+
|
|
112
|
+
// Ensure currentSecrets is an object
|
|
113
|
+
const currentSecrets =
|
|
114
|
+
typeof currentSecretsRaw === 'object' &&
|
|
115
|
+
currentSecretsRaw !== null &&
|
|
116
|
+
!Array.isArray(currentSecretsRaw)
|
|
117
|
+
? (currentSecretsRaw as Record<string, any>)
|
|
118
|
+
: {};
|
|
119
|
+
|
|
120
|
+
const newSecrets = {
|
|
121
|
+
...currentSecrets,
|
|
122
|
+
[key]: value,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Update entire settings object for better change detection
|
|
126
|
+
updateSettings({
|
|
127
|
+
...currentSettings,
|
|
128
|
+
secrets: newSecrets,
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
[agent.settings, updateSettings]
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Removes a secret from the Agent's settings.secrets object
|
|
136
|
+
*
|
|
137
|
+
* @param key Secret key to remove
|
|
138
|
+
*/
|
|
139
|
+
const removeSecret = useCallback(
|
|
140
|
+
(key: string) => {
|
|
141
|
+
// Get the current secrets object
|
|
142
|
+
const currentSettings = agent.settings || {};
|
|
143
|
+
const currentSecretsRaw = currentSettings.secrets || {};
|
|
144
|
+
|
|
145
|
+
// Ensure currentSecrets is an object
|
|
146
|
+
const currentSecrets =
|
|
147
|
+
typeof currentSecretsRaw === 'object' &&
|
|
148
|
+
currentSecretsRaw !== null &&
|
|
149
|
+
!Array.isArray(currentSecretsRaw)
|
|
150
|
+
? (currentSecretsRaw as Record<string, any>)
|
|
151
|
+
: {};
|
|
152
|
+
|
|
153
|
+
// Create a new secrets object without the removed key
|
|
154
|
+
const newSecrets = { ...currentSecrets };
|
|
155
|
+
delete newSecrets[key];
|
|
156
|
+
|
|
157
|
+
// Update the entire settings object to ensure nested changes are detected
|
|
158
|
+
const updatedSettings = {
|
|
159
|
+
...currentSettings,
|
|
160
|
+
secrets: newSecrets,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Use updateSettings instead of updateField for better change detection
|
|
164
|
+
updateSettings(updatedSettings);
|
|
165
|
+
},
|
|
166
|
+
[agent.settings, updateSettings]
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// ==================== Content Tab ====================
|
|
170
|
+
/**
|
|
171
|
+
* Adds an item to a content array (bio, topics, adjectives)
|
|
172
|
+
*
|
|
173
|
+
* @param arrayName The name of the array field
|
|
174
|
+
* @param item The item to add
|
|
175
|
+
*/
|
|
176
|
+
const addContentItem = useCallback(
|
|
177
|
+
(arrayName: 'bio' | 'topics' | 'adjectives', item: string) => {
|
|
178
|
+
addArrayItem(arrayName, item);
|
|
179
|
+
},
|
|
180
|
+
[addArrayItem]
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Removes an item from a content array
|
|
185
|
+
*
|
|
186
|
+
* @param arrayName The name of the array field
|
|
187
|
+
* @param index The index of the item to remove
|
|
188
|
+
*/
|
|
189
|
+
const removeContentItem = useCallback(
|
|
190
|
+
(arrayName: 'bio' | 'topics' | 'adjectives', index: number) => {
|
|
191
|
+
removeArrayItem(arrayName, index);
|
|
192
|
+
},
|
|
193
|
+
[removeArrayItem]
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Updates an item in a content array
|
|
198
|
+
*
|
|
199
|
+
* @param arrayName The name of the array field
|
|
200
|
+
* @param index The index of the item to update
|
|
201
|
+
* @param value The new value
|
|
202
|
+
*/
|
|
203
|
+
const updateContentItem = useCallback(
|
|
204
|
+
(arrayName: 'bio' | 'topics' | 'adjectives', index: number, value: string) => {
|
|
205
|
+
updateField(`${arrayName}.${index}`, value);
|
|
206
|
+
},
|
|
207
|
+
[updateField]
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// ==================== Style Tab ====================
|
|
211
|
+
/**
|
|
212
|
+
* Adds a style rule to one of the style arrays
|
|
213
|
+
*
|
|
214
|
+
* @param styleType Type of style ('all', 'chat', 'post')
|
|
215
|
+
* @param rule The style rule to add
|
|
216
|
+
*/
|
|
217
|
+
const addStyleRule = useCallback(
|
|
218
|
+
(styleType: 'all' | 'chat' | 'post', rule: string) => {
|
|
219
|
+
addArrayItem(`style.${styleType}`, rule);
|
|
220
|
+
},
|
|
221
|
+
[addArrayItem]
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Removes a style rule from one of the style arrays
|
|
226
|
+
*
|
|
227
|
+
* @param styleType Type of style ('all', 'chat', 'post')
|
|
228
|
+
* @param index The index of the rule to remove
|
|
229
|
+
*/
|
|
230
|
+
const removeStyleRule = useCallback(
|
|
231
|
+
(styleType: 'all' | 'chat' | 'post', index: number) => {
|
|
232
|
+
removeArrayItem(`style.${styleType}`, index);
|
|
233
|
+
},
|
|
234
|
+
[removeArrayItem]
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Updates a style rule in one of the style arrays
|
|
239
|
+
*
|
|
240
|
+
* @param styleType Type of style ('all', 'chat', 'post')
|
|
241
|
+
* @param index The index of the rule to update
|
|
242
|
+
* @param value The new rule value
|
|
243
|
+
*/
|
|
244
|
+
const updateStyleRule = useCallback(
|
|
245
|
+
(styleType: 'all' | 'chat' | 'post', index: number, value: string) => {
|
|
246
|
+
updateField(`style.${styleType}.${index}`, value);
|
|
247
|
+
},
|
|
248
|
+
[updateField]
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Sets a complete style array
|
|
253
|
+
*
|
|
254
|
+
* @param styleType Type of style ('all', 'chat', 'post')
|
|
255
|
+
* @param values Array of style values
|
|
256
|
+
*/
|
|
257
|
+
const setStyleArray = useCallback(
|
|
258
|
+
(styleType: 'all' | 'chat' | 'post', values: string[]) => {
|
|
259
|
+
updateField(`style.${styleType}`, values);
|
|
260
|
+
},
|
|
261
|
+
[updateField]
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// ==================== Plugins Tab ====================
|
|
265
|
+
/**
|
|
266
|
+
* Adds a plugin to the agent's plugins array
|
|
267
|
+
*
|
|
268
|
+
* @param pluginId The plugin ID to add
|
|
269
|
+
*/
|
|
270
|
+
const addPlugin = useCallback(
|
|
271
|
+
(pluginId: string) => {
|
|
272
|
+
addArrayItem('plugins', pluginId);
|
|
273
|
+
},
|
|
274
|
+
[addArrayItem]
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Removes a plugin from the agent's plugins array
|
|
279
|
+
*
|
|
280
|
+
* @param index The index of the plugin to remove
|
|
281
|
+
*/
|
|
282
|
+
const removePlugin = useCallback(
|
|
283
|
+
(index: number) => {
|
|
284
|
+
removeArrayItem('plugins', index);
|
|
285
|
+
},
|
|
286
|
+
[removeArrayItem]
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Sets the entire plugins array
|
|
291
|
+
*
|
|
292
|
+
* @param plugins Array of plugin IDs
|
|
293
|
+
*/
|
|
294
|
+
const setPlugins = useCallback(
|
|
295
|
+
(plugins: string[]) => {
|
|
296
|
+
updateField('plugins', plugins);
|
|
297
|
+
},
|
|
298
|
+
[updateField]
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// ==================== Avatar Tab ====================
|
|
302
|
+
/**
|
|
303
|
+
* Updates the agent's avatar
|
|
304
|
+
*
|
|
305
|
+
* @param avatarUrl The URL of the avatar image
|
|
306
|
+
*/
|
|
307
|
+
const updateAvatar = useCallback(
|
|
308
|
+
(avatarUrl: string) => {
|
|
309
|
+
updateSetting('avatar', avatarUrl);
|
|
310
|
+
},
|
|
311
|
+
[updateSetting]
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Returns an object containing only the fields that have changed
|
|
316
|
+
* compared to the initial agent state
|
|
317
|
+
*/
|
|
318
|
+
const getChangedFields = useCallback(() => {
|
|
319
|
+
const changedFields: Partial<Agent> = {};
|
|
320
|
+
const current = agent;
|
|
321
|
+
const initial = initialAgentRef.current;
|
|
322
|
+
|
|
323
|
+
// Compare scalar properties
|
|
324
|
+
const scalarProps = ['name', 'username', 'system'] as const;
|
|
325
|
+
scalarProps.forEach((prop) => {
|
|
326
|
+
if (current[prop] !== initial[prop]) {
|
|
327
|
+
changedFields[prop] = current[prop];
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (current.enabled !== initial.enabled) {
|
|
332
|
+
changedFields.enabled = current.enabled;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Compare array properties with type safety
|
|
336
|
+
if (JSON.stringify(current.bio) !== JSON.stringify(initial.bio)) {
|
|
337
|
+
changedFields.bio = current.bio;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (JSON.stringify(current.topics) !== JSON.stringify(initial.topics)) {
|
|
341
|
+
changedFields.topics = current.topics;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (JSON.stringify(current.adjectives) !== JSON.stringify(initial.adjectives)) {
|
|
345
|
+
changedFields.adjectives = current.adjectives;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (JSON.stringify(current.plugins) !== JSON.stringify(initial.plugins)) {
|
|
349
|
+
changedFields.plugins = current.plugins;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Compare style object
|
|
353
|
+
if (JSON.stringify(current.style) !== JSON.stringify(initial.style)) {
|
|
354
|
+
changedFields.style = current.style;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// More granular comparison for settings object
|
|
358
|
+
const initialSettings = initial.settings || {};
|
|
359
|
+
const currentSettings = current.settings || {};
|
|
360
|
+
|
|
361
|
+
// Check if any settings changed
|
|
362
|
+
if (JSON.stringify(currentSettings) !== JSON.stringify(initialSettings)) {
|
|
363
|
+
// Create a partial settings object with only changed fields
|
|
364
|
+
changedFields.settings = {};
|
|
365
|
+
|
|
366
|
+
// Check avatar separately
|
|
367
|
+
if (currentSettings.avatar !== initialSettings.avatar) {
|
|
368
|
+
changedFields.settings.avatar = currentSettings.avatar;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Check voice settings
|
|
372
|
+
if (JSON.stringify(currentSettings.voice) !== JSON.stringify(initialSettings.voice)) {
|
|
373
|
+
changedFields.settings.voice = currentSettings.voice;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Check secrets with special handling
|
|
377
|
+
if (JSON.stringify(currentSettings.secrets) !== JSON.stringify(initialSettings.secrets)) {
|
|
378
|
+
const initialSecretsRaw = initialSettings.secrets || {};
|
|
379
|
+
const currentSecretsRaw = currentSettings.secrets || {};
|
|
380
|
+
|
|
381
|
+
// Ensure secrets are objects
|
|
382
|
+
const initialSecrets =
|
|
383
|
+
typeof initialSecretsRaw === 'object' &&
|
|
384
|
+
initialSecretsRaw !== null &&
|
|
385
|
+
!Array.isArray(initialSecretsRaw)
|
|
386
|
+
? (initialSecretsRaw as Record<string, any>)
|
|
387
|
+
: {};
|
|
388
|
+
const currentSecrets =
|
|
389
|
+
typeof currentSecretsRaw === 'object' &&
|
|
390
|
+
currentSecretsRaw !== null &&
|
|
391
|
+
!Array.isArray(currentSecretsRaw)
|
|
392
|
+
? (currentSecretsRaw as Record<string, any>)
|
|
393
|
+
: {};
|
|
394
|
+
|
|
395
|
+
// Only include secrets that were added or modified
|
|
396
|
+
const changedSecrets: Record<string, any> = {};
|
|
397
|
+
let hasSecretChanges = false;
|
|
398
|
+
|
|
399
|
+
// Find added or modified secrets
|
|
400
|
+
Object.entries(currentSecrets).forEach(([key, value]) => {
|
|
401
|
+
if (initialSecrets[key] !== value) {
|
|
402
|
+
changedSecrets[key] = value;
|
|
403
|
+
hasSecretChanges = true;
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// Find deleted secrets (null values indicate deletion)
|
|
408
|
+
Object.keys(initialSecrets).forEach((key) => {
|
|
409
|
+
if (currentSecrets[key] === undefined) {
|
|
410
|
+
changedSecrets[key] = null;
|
|
411
|
+
hasSecretChanges = true;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
if (hasSecretChanges) {
|
|
416
|
+
if (!changedFields.settings) changedFields.settings = {};
|
|
417
|
+
changedFields.settings.secrets = changedSecrets;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// If no specific settings changed, don't include settings object
|
|
422
|
+
if (Object.keys(changedFields.settings).length === 0) {
|
|
423
|
+
delete changedFields.settings;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return changedFields;
|
|
428
|
+
}, [agent]);
|
|
429
|
+
|
|
430
|
+
return {
|
|
431
|
+
agent,
|
|
432
|
+
updateField,
|
|
433
|
+
reset,
|
|
434
|
+
updateSettings,
|
|
435
|
+
setSettings,
|
|
436
|
+
|
|
437
|
+
// Method to get only changed fields
|
|
438
|
+
getChangedFields,
|
|
439
|
+
|
|
440
|
+
// Basic Info Tab
|
|
441
|
+
updateSetting,
|
|
442
|
+
updateSystemPrompt,
|
|
443
|
+
|
|
444
|
+
// Secrets Tab
|
|
445
|
+
updateSecret,
|
|
446
|
+
removeSecret,
|
|
447
|
+
|
|
448
|
+
// Content Tab
|
|
449
|
+
addContentItem,
|
|
450
|
+
removeContentItem,
|
|
451
|
+
updateContentItem,
|
|
452
|
+
|
|
453
|
+
// Style Tab
|
|
454
|
+
addStyleRule,
|
|
455
|
+
removeStyleRule,
|
|
456
|
+
updateStyleRule,
|
|
457
|
+
setStyleArray,
|
|
458
|
+
|
|
459
|
+
// Plugins Tab
|
|
460
|
+
addPlugin,
|
|
461
|
+
removePlugin,
|
|
462
|
+
setPlugins,
|
|
463
|
+
|
|
464
|
+
// Avatar Tab
|
|
465
|
+
updateAvatar,
|
|
466
|
+
|
|
467
|
+
importAgent,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Character, Content } from '@elizaos/core';
|
|
2
|
+
import { usePlugins } from '@/hooks/use-plugins';
|
|
3
|
+
|
|
4
|
+
const PROVIDER_PLUGIN_MAPPINGS: Record<string, string> = {
|
|
5
|
+
google: '@elizaos/plugin-google-genai',
|
|
6
|
+
llama_local: '@elizaos/plugin-ollama',
|
|
7
|
+
// extend as needed
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const CLIENT_PLUGIN_MAPPINGS: Record<string, string> = {
|
|
11
|
+
// add as needed
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const ESSENTIAL_PLUGINS = ['@elizaos/plugin-sql', '@elizaos/plugin-bootstrap'];
|
|
15
|
+
|
|
16
|
+
export interface V1Character {
|
|
17
|
+
name: string;
|
|
18
|
+
lore?: string[];
|
|
19
|
+
clients?: string[];
|
|
20
|
+
modelProvider?: string;
|
|
21
|
+
bio?: string | string[];
|
|
22
|
+
messageExamples?: any[][];
|
|
23
|
+
username?: string;
|
|
24
|
+
system?: string;
|
|
25
|
+
settings?: {
|
|
26
|
+
[key: string]: string | boolean | number | Record<string, any>;
|
|
27
|
+
};
|
|
28
|
+
topics?: string[];
|
|
29
|
+
style?: {
|
|
30
|
+
all?: string[];
|
|
31
|
+
chat?: string[];
|
|
32
|
+
post?: string[];
|
|
33
|
+
};
|
|
34
|
+
adjectives?: string[];
|
|
35
|
+
postExamples?: string[];
|
|
36
|
+
// Additional properties that might exist
|
|
37
|
+
[key: string]: any;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function useConvertCharacter() {
|
|
41
|
+
const { data: availablePlugins = [] } = usePlugins();
|
|
42
|
+
|
|
43
|
+
const matchPlugins = (v1: V1Character): string[] => {
|
|
44
|
+
const matched = new Set<string>();
|
|
45
|
+
|
|
46
|
+
// Clients
|
|
47
|
+
if (Array.isArray(v1.clients)) {
|
|
48
|
+
for (const client of v1.clients) {
|
|
49
|
+
const lower = client.toLowerCase();
|
|
50
|
+
const mapped = CLIENT_PLUGIN_MAPPINGS[lower];
|
|
51
|
+
if (mapped && availablePlugins.includes(mapped)) {
|
|
52
|
+
matched.add(mapped);
|
|
53
|
+
} else {
|
|
54
|
+
const constructed = `@elizaos/plugin-${lower}`;
|
|
55
|
+
if (availablePlugins.includes(constructed)) {
|
|
56
|
+
matched.add(constructed);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Model provider
|
|
63
|
+
let providerMatched = false;
|
|
64
|
+
if (typeof v1.modelProvider === 'string') {
|
|
65
|
+
const lower = v1.modelProvider.toLowerCase();
|
|
66
|
+
const mapped = PROVIDER_PLUGIN_MAPPINGS[lower];
|
|
67
|
+
if (mapped && availablePlugins.includes(mapped)) {
|
|
68
|
+
matched.add(mapped);
|
|
69
|
+
providerMatched = true;
|
|
70
|
+
} else {
|
|
71
|
+
const constructed = `@elizaos/plugin-${lower}`;
|
|
72
|
+
if (availablePlugins.includes(constructed)) {
|
|
73
|
+
matched.add(constructed);
|
|
74
|
+
providerMatched = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!providerMatched) {
|
|
78
|
+
if (availablePlugins.includes('@elizaos/plugin-openai')) {
|
|
79
|
+
matched.add('@elizaos/plugin-openai');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
// If no modelProvider specified, default to OpenAI
|
|
84
|
+
if (availablePlugins.includes('@elizaos/plugin-openai')) {
|
|
85
|
+
matched.add('@elizaos/plugin-openai');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Add essential plugins only if they exist in availablePlugins
|
|
90
|
+
for (const plugin of ESSENTIAL_PLUGINS) {
|
|
91
|
+
if (availablePlugins.includes(plugin)) {
|
|
92
|
+
matched.add(plugin);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return Array.from(matched).sort();
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
function isV1MessageExampleFormat(example: any): example is { user: string; content: Content } {
|
|
100
|
+
return typeof example === 'object' && example !== null && 'user' in example;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const convertCharacter = (v1: V1Character): Character => {
|
|
104
|
+
const bio = [...(Array.isArray(v1.bio) ? v1.bio : v1.bio ? [v1.bio] : []), ...(v1.lore ?? [])];
|
|
105
|
+
|
|
106
|
+
const messageExamples =
|
|
107
|
+
(v1.messageExamples ?? []).map((thread: any[]) =>
|
|
108
|
+
thread.map((msg: any) => {
|
|
109
|
+
if (isV1MessageExampleFormat(msg)) {
|
|
110
|
+
return {
|
|
111
|
+
name: msg.user,
|
|
112
|
+
content: msg.content,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return msg;
|
|
116
|
+
})
|
|
117
|
+
) ?? [];
|
|
118
|
+
|
|
119
|
+
const plugins = matchPlugins(v1);
|
|
120
|
+
const v2: Character = {
|
|
121
|
+
name: v1.name,
|
|
122
|
+
username: v1.username,
|
|
123
|
+
system: v1.system,
|
|
124
|
+
settings: v1.settings,
|
|
125
|
+
plugins,
|
|
126
|
+
bio,
|
|
127
|
+
topics: v1.topics,
|
|
128
|
+
style: v1.style,
|
|
129
|
+
adjectives: v1.adjectives,
|
|
130
|
+
messageExamples,
|
|
131
|
+
postExamples: v1.postExamples,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return v2;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return { convertCharacter };
|
|
138
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import ConfirmationDialog from '@/components/confirmation-dialog';
|
|
3
|
+
|
|
4
|
+
interface ConfirmationOptions {
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
confirmText?: string;
|
|
8
|
+
cancelText?: string;
|
|
9
|
+
variant?: 'default' | 'destructive';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useConfirmation() {
|
|
13
|
+
const [confirmationState, setConfirmationState] = useState<{
|
|
14
|
+
open: boolean;
|
|
15
|
+
options: ConfirmationOptions | null;
|
|
16
|
+
onConfirm: (() => void) | null;
|
|
17
|
+
}>({
|
|
18
|
+
open: false,
|
|
19
|
+
options: null,
|
|
20
|
+
onConfirm: null,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const confirm = useCallback((options: ConfirmationOptions, onConfirm: () => void) => {
|
|
24
|
+
setConfirmationState({
|
|
25
|
+
open: true,
|
|
26
|
+
options,
|
|
27
|
+
onConfirm,
|
|
28
|
+
});
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
const handleOpenChange = useCallback((open: boolean) => {
|
|
32
|
+
if (!open) {
|
|
33
|
+
setConfirmationState({
|
|
34
|
+
open: false,
|
|
35
|
+
options: null,
|
|
36
|
+
onConfirm: null,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const handleConfirm = useCallback(() => {
|
|
42
|
+
if (confirmationState.onConfirm) {
|
|
43
|
+
confirmationState.onConfirm();
|
|
44
|
+
}
|
|
45
|
+
handleOpenChange(false);
|
|
46
|
+
}, [confirmationState.onConfirm, handleOpenChange]);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
confirm,
|
|
50
|
+
isOpen: confirmationState.open,
|
|
51
|
+
onOpenChange: handleOpenChange,
|
|
52
|
+
onConfirm: handleConfirm,
|
|
53
|
+
options: confirmationState.options,
|
|
54
|
+
};
|
|
55
|
+
}
|