Skip to content

Commit

Permalink
feat: Retry and Edit Message (#345)
Browse files Browse the repository at this point in the history
* wip

* feat: retry

* fix

* feat: retry

* fixes

* feat: retry interactions

* ui improvements

* ui improvements

* fix

* feat: edit message

* i18n

* fixes

* set default value

* fix

---------

Co-authored-by: paulclindo <[email protected]>
  • Loading branch information
nicarq and paulclindo authored Jun 28, 2024
1 parent f62cd53 commit bcb17d3
Show file tree
Hide file tree
Showing 18 changed files with 467 additions and 59 deletions.
23 changes: 23 additions & 0 deletions apps/shinkai-desktop/src/pages/chat/chat-conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,27 @@ const ChatConversation = () => {
},
});

const regenerateMessage = async (content: string, parentHash: string) => {
setMessageContent(''); // trick to clear the ws stream message
if (!auth) return;
const decodedInboxId = decodeURIComponent(inboxId);
const jobId = extractJobIdFromInbox(decodedInboxId);
await sendMessageToJob({
nodeAddress: auth.node_address,
jobId,
message: content,
files_inbox: '',
parent: parentHash,
shinkaiIdentity: auth.shinkai_identity,
profile: auth.profile,
my_device_encryption_sk: auth.my_device_encryption_sk,
my_device_identity_sk: auth.my_device_identity_sk,
node_encryption_pk: auth.node_encryption_pk,
profile_encryption_sk: auth.profile_encryption_sk,
profile_identity_sk: auth.profile_identity_sk,
});
};

const onSubmit = async (data: ChatMessageFormSchema) => {
setMessageContent(''); // trick to clear the ws stream message
if (!auth || data.message.trim() === '') return;
Expand Down Expand Up @@ -346,6 +367,7 @@ const ChatConversation = () => {
lastMessageContent={messageContent}
noMoreMessageLabel={t('chat.allMessagesLoaded')}
paginatedMessages={data}
regenerateMessage={regenerateMessage}
/>
{isLimitReachedErrorLastMessage && (
<Alert className="mx-auto w-[98%] shadow-lg" variant="destructive">
Expand Down Expand Up @@ -410,6 +432,7 @@ const ChatConversation = () => {
</TooltipProvider>
</div>
<ChatInputArea
autoFocus
bottomAddons={
<Button
className="h-[40px] w-[40px] self-end rounded-xl p-3"
Expand Down
24 changes: 23 additions & 1 deletion apps/shinkai-visor/src/components/inbox/inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,27 @@ export const Inbox = () => {
const [isJobProcessingFile, setIsJobProcessingFile] =
useState<boolean>(false);

const regenerateMessage = async (content: string, parentHash: string) => {
setMessageContent(''); // trick to clear the ws stream message
if (!auth) return;
const decodedInboxId = decodeURIComponent(inboxId);
const jobId = extractJobIdFromInbox(decodedInboxId);
await sendMessageToJob({
nodeAddress: auth.node_address,
jobId,
message: content,
files_inbox: '',
parent: parentHash,
shinkaiIdentity: auth.shinkai_identity,
profile: auth.profile,
my_device_encryption_sk: auth.my_device_encryption_sk,
my_device_identity_sk: auth.my_device_identity_sk,
node_encryption_pk: auth.node_encryption_pk,
profile_encryption_sk: auth.profile_encryption_sk,
profile_identity_sk: auth.profile_identity_sk,
});
};

const onSubmit = async (data: ChatMessageFormSchema) => {
setMessageContent(''); // trick to clear the ws stream message
if (!auth || data.message.trim() === '') return;
Expand Down Expand Up @@ -429,6 +450,7 @@ export const Inbox = () => {
lastMessageContent={messageContent}
noMoreMessageLabel="All previous messages have been loaded ✅"
paginatedMessages={data}
regenerateMessage={regenerateMessage}
/>
{isJobProcessingFile && (
<Alert className="shadow-lg">
Expand Down Expand Up @@ -519,7 +541,7 @@ export const Inbox = () => {
</Button>
}
disabled={isLoadingMessage}
isLoading={isLoadingMessage}
// isLoading={isLoadingMessage}
onChange={field.onChange}
onSubmit={chatForm.handleSubmit(onSubmit)}
topAddons={
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
"notFound": "No archived conversations found.",
"success": "Your conversation has been archived",
"error": "Error archiving job"
},
"editMessage": {
"warning": "This will restart your conversation from here."
}
},
"aiFilesSearch": {
Expand Down Expand Up @@ -278,6 +281,8 @@
"search": "Search",
"next": "Next",
"restore": "Restore",
"retry": "Retry",
"copy": "Copy",
"reset": "Reset",
"clickToUpload": "Click to upload or drag and drop",
"upload": "Upload",
Expand All @@ -300,6 +305,8 @@
"soon": "soon",
"back": "Back",
"edit": "Edit",
"send": "Send",
"editMessage": "Edit Message",
"delete": "Delete",
"update": "Update",
"moreOptions": "More Options",
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/locales/es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"title": "Contexto de la Conversación"
},
"create": "Crear Chat de IA",
"editMessage": {
"warning": "Esto reiniciará tu conversación desde aquí."
},
"emptyStateDescription": "Prueba con “Cómo hacer una solicitud HTTP en JavaScript”, “Dame las 10 mejores canciones de rock de los 80”, “Explícame cómo funciona internet”",
"emptyStateTitle": "Pregunta a Shinkai IA",
"enterMessage": "Introducir Mensaje",
Expand Down Expand Up @@ -69,10 +72,12 @@
"comingSoon": "Próximamente - Principios de Julio",
"connect": "Conectar",
"continue": "Continuar",
"copy": "Copiar",
"delete": "Eliminar",
"disconnect": "Desconectar",
"done": "Hecho",
"edit": "Editar",
"editMessage": "Editar mensaje",
"file": "Archivo",
"fileWithCount_one": "{{count}} Archivo",
"fileWithCount_other": "{{count}} Archivos",
Expand All @@ -99,10 +104,12 @@
"reset": "Restablecer",
"resetFilters": "Restablecer filtros",
"restore": "Restaurar",
"retry": "Reintentar",
"save": "Guardar",
"search": "Buscar",
"searchPlaceholder": "Buscar...",
"seeOptions": "Ver Opciones",
"send": "Enviar",
"shinkaiPrivate": "Shinkai Privado (Local)",
"signUpShinkaiHosting": "Registrarse en Shinkai Hosting",
"soon": "pronto",
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/locales/id-ID.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"title": "Konteks Percakapan"
},
"create": "Buat Obrolan AI",
"editMessage": {
"warning": "Ini akan memulai ulang percakapan Anda dari sini."
},
"emptyStateDescription": "Coba “Bagaimana cara membuat permintaan HTTP dalam JavaScript”, “Beri saya 10 musik rock teratas di tahun 80an”, “Jelaskan bagaimana internet bekerja”",
"emptyStateTitle": "Tanyakan kepada Shinkai AI",
"enterMessage": "Masukkan Pesan",
Expand Down Expand Up @@ -69,10 +72,12 @@
"comingSoon": "Segera hadir - Awal Juli",
"connect": "Hubungkan",
"continue": "Lanjutkan",
"copy": "Salin",
"delete": "Hapus",
"disconnect": "Putuskan Koneksi",
"done": "Selesai",
"edit": "Edit",
"editMessage": "Edit Pesan",
"file": "Berkas",
"fileWithCount_one": "{{count}} Berkas",
"fileWithCount_other": "{{count}} Berkas",
Expand All @@ -99,10 +104,12 @@
"reset": "Reset",
"resetFilters": "Reset Filter",
"restore": "Pulihkan",
"retry": "Coba lagi",
"save": "Simpan",
"search": "Cari",
"searchPlaceholder": "Cari...",
"seeOptions": "Lihat Opsi",
"send": "Kirim",
"shinkaiPrivate": "Shinkai Pribadi (Lokal)",
"signUpShinkaiHosting": "Daftar untuk Hosting Shinkai",
"soon": "segera",
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"title": "会話コンテキスト"
},
"create": "AIチャットを作成",
"editMessage": {
"warning": "ここから会話をやり直します。"
},
"emptyStateDescription": "「JavaScriptでHTTPリクエストを作成する方法」、「80年代のロック音楽のトップ10を教えて」、「インターネットの仕組みを説明して」などをお試しください",
"emptyStateTitle": "Shinkai AIに質問してみてください",
"enterMessage": "メッセージを入力",
Expand Down Expand Up @@ -69,10 +72,12 @@
"comingSoon": "近日公開 - 7月上旬",
"connect": "接続",
"continue": "続行",
"copy": "コピー",
"delete": "削除",
"disconnect": "切断",
"done": "完了",
"edit": "編集",
"editMessage": "メッセージを編集",
"file": "ファイル",
"fileWithCount_one": "{{count}} ファイル",
"fileWithCount_other": "{{count}} ファイル",
Expand All @@ -99,10 +104,12 @@
"reset": "リセット",
"resetFilters": "フィルターをリセット",
"restore": "復元",
"retry": "再試行",
"save": "保存",
"search": "検索",
"searchPlaceholder": "検索...",
"seeOptions": "オプションを表示",
"send": "送信",
"shinkaiPrivate": "Shinkaiプライベート(ローカル)",
"signUpShinkaiHosting": "Shinkai Hostingにサインアップ",
"soon": "近日公開",
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"title": "对话上下文"
},
"create": "创建 AI 聊天",
"editMessage": {
"warning": "这将重新开始您的对话。"
},
"emptyStateDescription": "尝试 “如何在 JavaScript 中进行 HTTP 请求”, “给我 80 年代十大摇滚音乐”, “解释互联网的工作原理”",
"emptyStateTitle": "询问 Shinkai AI",
"enterMessage": "输入消息",
Expand Down Expand Up @@ -69,10 +72,12 @@
"comingSoon": "即将到来 - 七月初",
"connect": "连接",
"continue": "继续",
"copy": "复制",
"delete": "删除",
"disconnect": "断开连接",
"done": "完成",
"edit": "编辑",
"editMessage": "编辑消息",
"file": "文件",
"fileWithCount_one": "{{count}} 个文件",
"fileWithCount_other": "{{count}} 个文件",
Expand All @@ -99,10 +104,12 @@
"reset": "重置",
"resetFilters": "重置筛选器",
"restore": "恢复",
"retry": "重试",
"save": "保存",
"search": "搜索",
"searchPlaceholder": "搜索...",
"seeOptions": "查看选项",
"send": "发送",
"shinkaiPrivate": "Shinkai私有(本地)",
"signUpShinkaiHosting": "注册Shinkai Hosting",
"soon": "即将",
Expand Down
7 changes: 7 additions & 0 deletions libs/shinkai-i18n/src/lib/default/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export default {
success: 'Your conversation has been archived',
error: 'Error archiving job',
},
editMessage: {
warning: 'This will restart your conversation from here.',
},
},
aiFilesSearch: {
label: 'AI Files Content Search',
Expand Down Expand Up @@ -296,6 +299,8 @@ export default {
search: 'Search',
next: 'Next',
restore: 'Restore',
retry: 'Retry',
copy: 'Copy',
reset: 'Reset',
clickToUpload: 'Click to upload or drag and drop',
upload: 'Upload',
Expand All @@ -318,6 +323,8 @@ export default {
soon: 'soon',
back: 'Back',
edit: 'Edit',
send: 'Send',
editMessage: 'Edit Message',
delete: 'Delete',
update: 'Update',
moreOptions: 'More Options',
Expand Down
33 changes: 33 additions & 0 deletions libs/shinkai-message-ts/src/api/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1572,3 +1572,36 @@ export const addOllamaModels = async (
const data = response.data;
return data;
};

export const getLastMessagesFromInboxWithBranches = async (
nodeAddress: string,
inbox: string,
count: number,
lastKey: string | undefined,
setupDetailsState: LastMessagesFromInboxCredentialsPayload,
) => {
const messageStr = ShinkaiMessageBuilderWrapper.get_last_messages_from_inbox(
setupDetailsState.profile_encryption_sk,
setupDetailsState.profile_identity_sk,
setupDetailsState.node_encryption_pk,
inbox,
count,
lastKey,
setupDetailsState.shinkai_identity,
setupDetailsState.profile,
setupDetailsState.shinkai_identity,
);

const message = JSON.parse(messageStr);

const response = await httpClient.post(
urlJoin(nodeAddress, '/v1/last_messages_from_inbox_with_branches'),
message,

{
responseType: 'json',
},
);
const data = response.data.data;
return data;
};
1 change: 1 addition & 0 deletions libs/shinkai-node-state/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export enum FunctionKey {
GET_INBOXES = 'GET_INBOXES',
GET_CHAT_CONVERSATION = 'GET_CHAT_CONVERSATION',
GET_CHAT_CONVERSATION_PAGINATION = 'GET_CHAT_CONVERSATION_PAGINATION',
GET_CHAT_CONVERSATION_BRANCHES = 'GET_CHAT_CONVERSATION_BRANCHES',
GET_NODE_FILES = 'GET_NODE_FILES',
GET_VR_FILES = 'GET_VR_FILES',
GET_VR_FILES_SEARCH = 'GET_VR_FILES_SEARCH',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
getFileNames,
getLastMessagesFromInbox,
getLastMessagesFromInboxWithBranches,
} from '@shinkai_network/shinkai-message-ts/api';
import type { ShinkaiMessage } from '@shinkai_network/shinkai-message-ts/models';
import {
Expand All @@ -27,7 +27,7 @@ export const getChatConversation = async ({
profile_identity_sk,
node_encryption_pk,
}: GetChatConversationInput): Promise<GetChatConversationOutput> => {
const data: ShinkaiMessage[] = await getLastMessagesFromInbox(
const data: ShinkaiMessage[][] = await getLastMessagesFromInboxWithBranches(
nodeAddress,
inboxId,
count,
Expand All @@ -40,8 +40,10 @@ export const getChatConversation = async ({
node_encryption_pk,
},
);
const flattenMessages: ShinkaiMessage[] = data.flat(1);

const transformedMessagePromises: Promise<ChatConversationMessage>[] =
data.map(async (shinkaiMessage) => {
flattenMessages.map(async (shinkaiMessage) => {
const filesInbox = getMessageFilesInbox(shinkaiMessage);
const content = getMessageContent(shinkaiMessage);
const isLocal = isLocalMessage(shinkaiMessage, shinkaiIdentity, profile);
Expand All @@ -51,6 +53,11 @@ export const getChatConversation = async ({
? shinkaiMessage.body.unencrypted.internal_metadata?.node_api_data
?.node_message_hash
: '',
parentHash:
shinkaiMessage.body && 'unencrypted' in shinkaiMessage.body
? shinkaiMessage.body.unencrypted.internal_metadata?.node_api_data
?.parent_hash
: '',
inboxId,
content,
sender: {
Expand Down Expand Up @@ -86,5 +93,12 @@ export const getChatConversation = async ({
}
return message;
});
return Promise.all(transformedMessagePromises);

const messages = await Promise.all(transformedMessagePromises);
// filter out messages if a message is repeated by its parent-hash
const uniqueMessages = messages.filter(
(message, index, self) =>
index === self.findIndex((t) => t.parentHash === message.parentHash),
);
return uniqueMessages;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type GetChatConversationInput = JobCredentialsPayload & {

export type ChatConversationMessage = {
hash: string;
parentHash: string;
inboxId: string;
scheduledTime: string | undefined;
content: string;
Expand Down
Loading

0 comments on commit bcb17d3

Please sign in to comment.