This commit is contained in:
Niek van der Maas 2023-03-17 14:00:54 +01:00
parent ad8aa1bdf0
commit 6750a93cdb
4 changed files with 209 additions and 23 deletions

View File

@ -1,11 +1,9 @@
<script lang="ts"> <script lang="ts">
import Router, {location} from 'svelte-spa-router'; import Router, { location } from "svelte-spa-router";
import routes from "./routes"; import routes from "./routes";
import Navbar from "./lib/Navbar.svelte"; import Navbar from "./lib/Navbar.svelte";
import Sidebar from "./lib/Sidebar.svelte"; import Sidebar from "./lib/Sidebar.svelte";
import Home from "./lib/Home.svelte";
import Chat from "./lib/Chat.svelte";
import Footer from "./lib/Footer.svelte"; import Footer from "./lib/Footer.svelte";
import { apiKeyStorage, chatsStorage } from "./lib/Storage.svelte"; import { apiKeyStorage, chatsStorage } from "./lib/Storage.svelte";
@ -26,11 +24,11 @@
<div class="container is-fullhd"> <div class="container is-fullhd">
<div class="columns"> <div class="columns">
<div class="column is-one-fifth"> <div class="column is-one-fifth">
<Sidebar bind:apiKey bind:sortedChats /> <Sidebar bind:apiKey bind:sortedChats />
</div> </div>
<div class="column is-four-fifths"> <div class="column is-four-fifths">
{#key $location} {#key $location}
<Router {routes}/> <Router {routes} />
{/key} {/key}
</div> </div>
</div> </div>

195
src/lib/Bing.svelte Normal file
View File

@ -0,0 +1,195 @@
const sendRequestBing = async (messages: Message[]): Promise<Response> => {
const conversation = await (
await fetch("https://www.bing.com/turing/conversation/create", {
credentials: "include",
})
).json();
return await new Promise((resolve, reject) => {
const text = messages[messages.length - 1].content;
const invocationId = "0";
const terminalChar = "";
const result = {
author: "bot",
id: crypto.randomUUID(),
conversationId: conversation.conversationId,
clientId: conversation.clientId,
conversationSignature: conversation.conversationSignature,
invocationId: `${parseInt(invocationId, 10) + 1}`,
text: "",
detail: "",
conversationExpiryTime: null,
};
const ws = new WebSocket("wss://sydney.bing.com/sydney/ChatHub");
ws.onopen = () => {
ws.send(`{"protocol":"json","version":1}${terminalChar}`);
};
ws.onmessage = (event) => {
const objects = event.data.toString().split(terminalChar);
const messages = objects
.map((object) => {
try {
return JSON.parse(object);
} catch (_) {
return object;
}
})
.filter(Boolean);
if (!messages.length) {
return;
}
// Initial message
if (messages.length === 1 && Object.keys(messages[0]).length === 0) {
ws.send(`{"type":6}${terminalChar}`);
const params = {
arguments: [
{
source: "cib",
optionsSets: [
"nlu_direct_response_filter",
"deepleo",
"disable_emoji_spoken_text",
"responsible_ai_policy_235",
"enablemm",
"harmonyv3",
"h3ads",
"wlthrottle",
"cpcttl7d",
"blocklistv2",
"h3toppfp2",
"dv3sugg",
],
allowedMessageTypes: [
"Chat",
"InternalSearchQuery",
"InternalSearchResult",
"Disengaged",
"InternalLoaderMessage",
"RenderCardRequest",
"AdsQuery",
"SemanticSerp",
"GenerateContentQuery",
"SearchQuery",
],
sliceIds: [
"perfsvgopt",
"228h3ads",
"h3ads",
"0310wlthrot",
"307retryscs0",
"307retryscs0",
"cache0307",
"ssoverlap50",
"ssplon",
"sssreduce",
"sswebtop2",
"302blocklist",
"308disbings0",
"311h3toppfp2",
],
isStartOfSession: true,
message: {
locale: "en-US",
market: "en-US",
region: "US",
author: "user",
inputMethod: "Keyboard",
text,
},
conversationSignature: conversation.conversationSignature,
participant: {
id: conversation.clientId,
},
conversationId: conversation.conversationId,
},
],
invocationId,
target: "chat",
type: 4,
};
ws.send(`${JSON.stringify(params)}${terminalChar}`);
return;
}
for (const message of messages) {
if (message.type === 1) {
// Message in progress
const msg = message.arguments[0].messages[0];
if (!msg.messageType) {
result.author = msg.author;
result.text = msg.text;
result.detail = msg;
// Write to stdout
console.log(`\r${result.text}`);
}
} else if (message.type === 2) {
// Message complete
if (message.item.result.error) {
throw new Error(`Error message: ${message.item.result.error}`);
}
const validMessages = message.item.messages?.filter((m) => !m.messageType);
const lastMessage = validMessages?.[validMessages?.length - 1];
if (lastMessage) {
result.conversationId = message.item.conversationId;
result.conversationExpiryTime = message.item.conversationExpiryTime;
result.author = lastMessage.author;
result.text = lastMessage.text;
result.detail = lastMessage;
//resolve(result);
}
} else if (message.type === 3) {
// Conversation complete
const response: Response = {
id: result.id,
object: "response",
created: 1,
choices: [
{
index: 0,
message: {
role: "assistant",
content: result.text,
},
finish_reason: "stop",
},
],
usage: null,
error: null,
};
resolve(response);
ws.close();
return;
} else {
// TODO: handle other message types
// these may be for displaying "adaptive cards"
console.warn("Unexpected message type", message.type, message);
}
}
};
ws.onerror = (error) => {
console.log("WebSocket error:", error);
reject(error);
};
ws.onclose = (_event) => {
console.log("WebSocket closed");
};
});
};

View File

@ -6,7 +6,7 @@
import Code from "./Code.svelte"; import Code from "./Code.svelte";
import { afterUpdate, onMount } from "svelte"; import { afterUpdate, onMount } from "svelte";
import { replace } from 'svelte-spa-router' import { replace } from "svelte-spa-router";
import SvelteMarkdown from "svelte-markdown"; import SvelteMarkdown from "svelte-markdown";
export let params = {}; export let params = {};
@ -231,7 +231,7 @@
const deleteChat = () => { const deleteChat = () => {
if (confirm("Are you sure you want to delete this chat?")) { if (confirm("Are you sure you want to delete this chat?")) {
replace('/').then(() => { replace("/").then(() => {
chatsStorage.update((chats) => chats.filter((chat) => chat.id !== chatId)); chatsStorage.update((chats) => chats.filter((chat) => chat.id !== chatId));
}); });
} }

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import {params, replace} from 'svelte-spa-router'; import { params, replace } from "svelte-spa-router";
import { addChat, clearChats } from "./Storage.svelte"; import { clearChats } from "./Storage.svelte";
import { exportAsMarkdown } from "./Export.svelte"; import { exportAsMarkdown } from "./Export.svelte";
import type { Chat } from "./Types.svelte"; import type { Chat } from "./Types.svelte";
@ -21,10 +21,8 @@
<ul> <ul>
{#each sortedChats as chat} {#each sortedChats as chat}
<li> <li>
<a <a href={`#/chat/${chat.id}`} class:is-disabled={!apiKey} class:is-active={activeChatId === chat.id}
href={`#/chat/${chat.id}`} >{chat.name || `Chat ${chat.id}`}</a
class:is-disabled={!apiKey}
class:is-active={activeChatId === chat.id}>{chat.name || `Chat ${chat.id}`}</a
> >
</li> </li>
{/each} {/each}
@ -35,18 +33,13 @@
<p class="menu-label">Actions</p> <p class="menu-label">Actions</p>
<ul class="menu-list"> <ul class="menu-list">
<li> <li>
<a <a href={"#/"} class="panel-block" class:is-disabled={!apiKey} class:is-active={!activeChatId}
href={"#/"} ><span class="greyscale mr-2">🔑</span> API key</a
class="panel-block"
class:is-disabled={!apiKey}
class:is-active={!activeChatId}><span class="greyscale mr-2">🔑</span> API key</a
> >
</li> </li>
<li> <li>
<a <a href={"#/chat/new"} class="panel-block" class:is-disabled={!apiKey}
href={"#/chat/new"} ><span class="greyscale mr-2"></span> New chat</a
class="panel-block"
class:is-disabled={!apiKey}><span class="greyscale mr-2"></span> New chat</a
> >
</li> </li>
<li> <li>
@ -55,7 +48,7 @@
class="panel-block" class="panel-block"
class:is-disabled={!apiKey} class:is-disabled={!apiKey}
on:click={() => { on:click={() => {
replace('#/').then(() => { replace("#/").then(() => {
clearChats(); clearChats();
}); });
}}><span class="greyscale mr-2">🗑️</span> Clear chats</a }}><span class="greyscale mr-2">🗑️</span> Clear chats</a