From d7375d6b9991065fbcaa9e7433b530e5abd8fad6 Mon Sep 17 00:00:00 2001 From: Julian Jelfs Date: Fri, 20 Dec 2024 09:20:10 +0000 Subject: [PATCH 1/2] Update bot (#7099) --- backend/canisters/user_index/api/src/main.rs | 1 + frontend/app/src/components/Input.svelte | 6 + .../src/components/bots/AutoBotBuilder.svelte | 45 ++++- .../app/src/components/bots/BotAvatar.svelte | 12 ++ .../app/src/components/bots/BotBuilder.svelte | 3 +- .../components/bots/BotBuilderModal.svelte | 184 ++++++++++++++++-- .../src/components/bots/BotExplorer.svelte | 16 +- .../app/src/components/bots/BotMatch.svelte | 5 +- .../app/src/components/bots/BotMember.svelte | 12 +- .../app/src/components/bots/BotSummary.svelte | 7 +- .../components/bots/CommandSelector.svelte | 3 +- .../components/bots/ValidatingInput.svelte | 10 +- frontend/app/src/components/bots/botState.ts | 2 +- frontend/app/src/components/home/Home.svelte | 7 +- .../components/home/MakeProposalModal.svelte | 6 +- .../components/home/SingleUserSelector.svelte | 42 ++-- .../home/groupdetails/Members.svelte | 8 +- frontend/app/src/i18n/ar.json | 13 +- frontend/app/src/i18n/cn.json | 13 +- frontend/app/src/i18n/de.json | 13 +- frontend/app/src/i18n/en.json | 20 +- frontend/app/src/i18n/es.json | 13 +- frontend/app/src/i18n/fa.json | 13 +- frontend/app/src/i18n/fr.json | 13 +- frontend/app/src/i18n/hi.json | 13 +- frontend/app/src/i18n/it.json | 13 +- frontend/app/src/i18n/iw.json | 13 +- frontend/app/src/i18n/jp.json | 13 +- frontend/app/src/i18n/pl.json | 13 +- frontend/app/src/i18n/ru.json | 13 +- frontend/app/src/i18n/uk.json | 13 +- frontend/app/src/i18n/vi.json | 13 +- .../services/community/community.client.ts | 7 +- .../src/services/externalBot/externalBot.ts | 3 +- .../src/services/group/group.client.ts | 7 +- .../src/services/openchatAgent.ts | 38 +++- .../services/userIndex/userIndex.client.ts | 52 +++-- frontend/openchat-agent/src/typebox.ts | 41 ++-- frontend/openchat-client/src/openchat.ts | 32 ++- frontend/openchat-shared/src/domain/bots.ts | 34 ++-- frontend/openchat-shared/src/domain/worker.ts | 28 ++- frontend/openchat-worker/src/worker.ts | 28 ++- tsBindings/types.d.ts | 4 +- .../deleteUser/UserIndexDeleteUserArgs.ts | 4 - .../deleteUser/UserIndexDeleteUserResponse.ts | 3 - .../updateBot/UserIndexUpdateBotArgs.ts | 5 + .../updateBot/UserIndexUpdateBotResponse.ts | 3 + 47 files changed, 682 insertions(+), 178 deletions(-) create mode 100644 frontend/app/src/components/bots/BotAvatar.svelte delete mode 100644 tsBindings/userIndex/deleteUser/UserIndexDeleteUserArgs.ts delete mode 100644 tsBindings/userIndex/deleteUser/UserIndexDeleteUserResponse.ts create mode 100644 tsBindings/userIndex/updateBot/UserIndexUpdateBotArgs.ts create mode 100644 tsBindings/userIndex/updateBot/UserIndexUpdateBotResponse.ts diff --git a/backend/canisters/user_index/api/src/main.rs b/backend/canisters/user_index/api/src/main.rs index 2dc4afe948..4aad21f067 100644 --- a/backend/canisters/user_index/api/src/main.rs +++ b/backend/canisters/user_index/api/src/main.rs @@ -64,5 +64,6 @@ fn main() { generate_ts_method!(user_index, submit_proof_of_unique_personhood); generate_ts_method!(user_index, suspend_user); generate_ts_method!(user_index, unsuspend_user); + generate_ts_method!(user_index, update_bot); generate_ts_method!(user_index, update_diamond_membership_subscription); } diff --git a/frontend/app/src/components/Input.svelte b/frontend/app/src/components/Input.svelte index dfdcba3ba9..80e7c3546b 100644 --- a/frontend/app/src/components/Input.svelte +++ b/frontend/app/src/components/Input.svelte @@ -15,6 +15,8 @@ children?: Snippet; onblur?: () => void; onfocus?: () => void; + oninput?: () => void; + onenter?: () => void; } @@ -40,6 +42,8 @@ pattern = undefined, onblur = undefined, onfocus = undefined, + oninput = undefined, + onenter = undefined, children, }: InputProps = $props(); @@ -61,6 +65,7 @@ value = parseInt(e.currentTarget.value, 10); } dispatch("change", value); + oninput?.(); }; export function setValue(text: string) { @@ -70,6 +75,7 @@ function keyDown(e: KeyboardEvent) { if (e.key === "Enter") { dispatch("enter"); + onenter?.(); } } diff --git a/frontend/app/src/components/bots/AutoBotBuilder.svelte b/frontend/app/src/components/bots/AutoBotBuilder.svelte index 784cc6c24f..69ab28b304 100644 --- a/frontend/app/src/components/bots/AutoBotBuilder.svelte +++ b/frontend/app/src/components/bots/AutoBotBuilder.svelte @@ -2,13 +2,13 @@ import Reload from "svelte-material-icons/Reload.svelte"; import { validEndpoint, - emptyBotInstance, OpenChat, validateBot, ValidationErrors, type ExternalBot, type SlashCommandSchema, type ValidationErrorMessages, + userStore, } from "openchat-client"; import { i18nKey } from "../../i18n/i18n"; import Input from "../Input.svelte"; @@ -23,19 +23,21 @@ import HoverIcon from "../HoverIcon.svelte"; import { iconSize } from "../../stores/iconSize"; import CommandViewer from "./CommandViewer.svelte"; + import SingleUserSelector from "../home/SingleUserSelector.svelte"; const client = getContext("client"); interface Props { valid: boolean; onUpdate: (bot: ExternalBot) => void; + candidate: ExternalBot; + nameDirty: boolean; } - let { valid = $bindable(), onUpdate }: Props = $props(); + let { valid = $bindable(), onUpdate, candidate, nameDirty }: Props = $props(); let selectedCommand = $state(undefined); let selectedCommandIndex = $state(undefined); let debug = $state(false); - let candidate = $state(emptyBotInstance()); let schemaLoaded = $state(false); let schemaLoading = $state(false); let showNext = $derived( @@ -49,7 +51,7 @@ () => [$state.snapshot(candidate)], async () => { const errors = validateBot(candidate); - if (errors.get("bot_name").length == 0) { + if (errors.get("bot_name").length == 0 && nameDirty) { errors.addErrors("bot_name", await checkUsername(candidate.name)); } return errors; @@ -100,7 +102,7 @@ // let editing = $derived(bot !== undefined); $effect(() => { - const isValid = errors.size === 0; + const isValid = errors.size === 0 && schemaLoaded; if (isValid !== valid) { valid = isValid; } @@ -123,6 +125,15 @@ selectedCommandIndex = index; } + function endpointChanged() { + schemaLoaded = false; + candidate.definition = { + kind: "bot_definition", + description: "", + commands: [], + }; + } + function loadDefinition() { if (!schemaLoading && validEndpoint(candidate.endpoint)) { schemaLoading = true; @@ -173,6 +184,22 @@ bind:value={candidate.id}> + + (candidate.ownerId = ev.detail.userId)} + on:userRemoved={(_) => (candidate.ownerId = "")} + selectedReceiver={$userStore.get(candidate.ownerId)} + placeholder={"bots.builder.ownerLabel"} + autofocus={false} /> +
{#if !errors.has("bot_endpoint")} - - + + {/if}
diff --git a/frontend/app/src/components/bots/BotAvatar.svelte b/frontend/app/src/components/bots/BotAvatar.svelte new file mode 100644 index 0000000000..a00751a01e --- /dev/null +++ b/frontend/app/src/components/bots/BotAvatar.svelte @@ -0,0 +1,12 @@ + + + diff --git a/frontend/app/src/components/bots/BotBuilder.svelte b/frontend/app/src/components/bots/BotBuilder.svelte index c744d62671..a5301da0c8 100644 --- a/frontend/app/src/components/bots/BotBuilder.svelte +++ b/frontend/app/src/components/bots/BotBuilder.svelte @@ -1,5 +1,6 @@
- +
- (bot = b)} bind:valid /> + {#if step === "choose"} + {#if myBots.length === 0} + + + + {:else} +

+ +

+
+ {#each myBots as myBot} + + +
selectBot(myBot)} class="match"> + + + +
+

+ {myBot.name} +

+

+ {myBot.definition.description} +

+
+
+ {/each} +
+ {/if} + {:else if step === "edit" && botState.current !== undefined} + (botState.current = b)} + bind:valid /> + {/if}
+ + diff --git a/frontend/app/src/components/bots/BotExplorer.svelte b/frontend/app/src/components/bots/BotExplorer.svelte index 7cfadf5e69..7f84e72415 100644 --- a/frontend/app/src/components/bots/BotExplorer.svelte +++ b/frontend/app/src/components/bots/BotExplorer.svelte @@ -1,25 +1,19 @@
- + {#if firstError !== undefined && showError}
diff --git a/frontend/app/src/components/bots/botState.ts b/frontend/app/src/components/bots/botState.ts index 7c63c414dd..6b0926b3e8 100644 --- a/frontend/app/src/components/bots/botState.ts +++ b/frontend/app/src/components/bots/botState.ts @@ -79,7 +79,7 @@ export const commands = derived( ...c, kind: b.kind, botName: b.name, - botIcon: b.avatarUrl, + avatarUrl: b.avatarUrl, botId: b.id, botEndpoint: b.endpoint, botDescription: b.definition.description, diff --git a/frontend/app/src/components/home/Home.svelte b/frontend/app/src/components/home/Home.svelte index 785fcf2ecd..6ded09c3f7 100644 --- a/frontend/app/src/components/home/Home.svelte +++ b/frontend/app/src/components/home/Home.svelte @@ -182,6 +182,7 @@ | { kind: "verify_humanity" } | { kind: "select_chat" } | { kind: "register_bot" } + | { kind: "update_bot" } | { kind: "suspended" } | { kind: "no_access" } | { kind: "new_group"; embeddedContent: boolean; candidate: CandidateGroupChat } @@ -270,7 +271,7 @@ } else if (ev instanceof RegisterBot) { modal = { kind: "register_bot" }; } else if (ev instanceof UpdateBot) { - modal = { kind: "register_bot" }; + modal = { kind: "update_bot" }; } else if (ev instanceof SummonWitch) { summonWitch(); } else if (ev instanceof RemoteVideoCallStartedEvent) { @@ -1333,7 +1334,9 @@ {:else if modal.kind === "suspended"} {:else if modal.kind === "register_bot"} - + + {:else if modal.kind === "update_bot"} + {:else if modal.kind === "no_access"} {:else if modal.kind === "not_found"} diff --git a/frontend/app/src/components/home/MakeProposalModal.svelte b/frontend/app/src/components/home/MakeProposalModal.svelte index 64cf2e07db..34dc25f96e 100644 --- a/frontend/app/src/components/home/MakeProposalModal.svelte +++ b/frontend/app/src/components/home/MakeProposalModal.svelte @@ -14,8 +14,10 @@ type Treasury, currentUser as user, cryptoBalance as cryptoBalanceStore, + currentUser, } from "openchat-client"; import { + emptyBotInstance, isPrincipalValid, isSubAccountValid, isUrl, @@ -101,7 +103,7 @@ let refreshingBalance = false; let balanceWithRefresh: BalanceWithRefresh; let achivementName = ""; - let candidateBot: ExternalBot | undefined = undefined; + let candidateBot: ExternalBot = emptyBotInstance($currentUser.userId); let candidateBotValid = false; $: errorMessage = @@ -511,6 +513,8 @@