Skip to content

Commit

Permalink
Merge branch 'trunk'
Browse files Browse the repository at this point in the history
  • Loading branch information
wong2 committed Oct 8, 2023
2 parents c5594d7 + 1f7e7af commit ffafd95
Show file tree
Hide file tree
Showing 61 changed files with 1,002 additions and 383 deletions.
18 changes: 16 additions & 2 deletions manifest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineManifest(async (env) => {
name: '__MSG_appName__',
description: '__MSG_appDesc__',
default_locale: 'en',
version: '1.35.5',
version: '1.38.1',
icons: {
'16': 'src/assets/icon.png',
'32': 'src/assets/icon.png',
Expand All @@ -23,8 +23,12 @@ export default defineManifest(async (env) => {
'https://*.openai.com/',
'https://bard.google.com/',
'https://*.chathub.gg/',
'https://*.duckduckgo.com/',
'https://*.poe.com/',
'https://*.anthropic.com/',
'https://*.claude.ai/',
],
optional_host_permissions: ['https://*/*'],
optional_host_permissions: ['https://*/*', 'wss://*/*'],
permissions: ['storage', 'unlimitedStorage', 'sidePanel', 'declarativeNetRequestWithHostAccess'],
content_scripts: [
{
Expand Down Expand Up @@ -58,6 +62,16 @@ export default defineManifest(async (env) => {
enabled: true,
path: 'src/rules/ddg.json',
},
{
id: 'ruleset_qianwen',
enabled: true,
path: 'src/rules/qianwen.json',
},
{
id: 'ruleset_baichuan',
enabled: true,
path: 'src/rules/baichuan.json',
},
],
},
}
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"devDependencies": {
"@crxjs/vite-plugin": "^2.0.0-beta.18",
"@headlessui/tailwindcss": "^0.2.0",
"@types/chrome": "^0.0.241",
"@types/humanize-duration": "^3.27.1",
"@types/lodash-es": "^4.17.8",
"@types/md5": "^2.3.2",
"@types/react": "^18.2.18",
Expand All @@ -20,11 +20,12 @@
"@types/react-scroll-to-bottom": "^4.2.1",
"@types/turndown": "^5.0.1",
"@types/uuid": "^9.0.2",
"@types/webextension-polyfill": "^0.10.1",
"@types/webextension-polyfill": "^0.10.2",
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"@vitejs/plugin-react": "^4.0.4",
"autoprefixer": "^10.4.14",
"chrome-types": "^0.1.231",
"eslint": "^8.46.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-react": "^7.33.1",
Expand Down Expand Up @@ -54,12 +55,14 @@
"cachified": "^3.5.4",
"clsx": "^2.0.0",
"cmdk": "^0.2.0",
"dayjs": "^1.11.9",
"eventsource-parser": "^1.0.0",
"framer-motion": "^10.16.0",
"fuse.js": "^6.6.2",
"github-markdown-css": "^5.2.0",
"gpt3-tokenizer": "^1.1.5",
"highlight.js": "^11.8.0",
"humanize-duration": "^3.29.0",
"i18next": "^23.4.2",
"i18next-browser-languagedetector": "^7.1.0",
"immer": "^9.0.19",
Expand All @@ -70,6 +73,7 @@
"lodash-es": "^4.17.21",
"lucide-react": "^0.264.0",
"md5": "^2.3.0",
"nanoid": "^4.0.2",
"ofetch": "^1.1.1",
"plausible-tracker": "^0.3.8",
"react": "^18.2.0",
Expand Down
35 changes: 35 additions & 0 deletions src/app/bots/baichuan/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ofetch } from 'ofetch'
import { customAlphabet } from 'nanoid'
import { ChatError, ErrorCode } from '~utils/errors'

interface UserInfo {
id: number
}

export async function getUserInfo(): Promise<UserInfo> {
const resp = await ofetch<{ data?: UserInfo; code: number; msg: string }>(
'https://www.baichuan-ai.com/api/user/user-info',
{ method: 'POST' },
)
if (resp.code === 401) {
throw new ChatError('请先登录百川账号', ErrorCode.BAICHUAN_WEB_UNAUTHORIZED)
}
if (resp.code !== 200) {
throw new Error(`Error: ${resp.code} ${resp.msg}`)
}
return resp.data!
}

const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789')

function randomString(length: number) {
return nanoid(length)
}

export function generateSessionId() {
return 'p' + randomString(10)
}

export function generateMessageId() {
return 'U' + randomString(14)
}
125 changes: 125 additions & 0 deletions src/app/bots/baichuan/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { AbstractBot, SendMessageParams } from '../abstract-bot'
import { requestHostPermission } from '~app/utils/permissions'
import { ChatError, ErrorCode } from '~utils/errors'
import { uuid } from '~utils'
import { generateMessageId, generateSessionId, getUserInfo } from './api'
import { streamAsyncIterable } from '~utils/stream-async-iterable'

interface Message {
id: string
createdAt: number
data: string
from: 0 | 1 // human | bot
}

interface ConversationContext {
conversationId: string
historyMessages: Message[]
userId: number
lastMessageId?: string
}

export class BaichuanWebBot extends AbstractBot {
private conversationContext?: ConversationContext

async doSendMessage(params: SendMessageParams) {
if (!(await requestHostPermission('https://*.baichuan-ai.com/'))) {
throw new ChatError('Missing baichuan-ai.com permission', ErrorCode.MISSING_HOST_PERMISSION)
}

if (!this.conversationContext) {
const conversationId = generateSessionId()
const userInfo = await getUserInfo()
this.conversationContext = { conversationId, historyMessages: [], userId: userInfo.id }
}

const { conversationId, lastMessageId, historyMessages, userId } = this.conversationContext

const message: Message = {
id: generateMessageId(),
createdAt: Date.now(),
data: params.prompt,
from: 0,
}

const resp = await fetch('https://www.baichuan-ai.com/api/chat/v1/chat', {
method: 'POST',
signal: params.signal,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
stream: true,
request_id: uuid(),
app_info: { id: 10001, name: 'baichuan_web' },
user_info: { id: userId, status: 1 },
prompt: {
id: message.id,
data: message.data,
from: message.from,
parent_id: lastMessageId || 0,
created_at: message.createdAt,
},
session_info: { id: conversationId, name: '新的对话', created_at: Date.now() },
parameters: {
repetition_penalty: -1,
temperature: -1,
top_k: -1,
top_p: -1,
max_new_tokens: -1,
do_sample: -1,
regenerate: 0,
},
history: historyMessages,
}),
})

const decoder = new TextDecoder()
let result = ''
let answerMessageId: string | undefined

for await (const uint8Array of streamAsyncIterable(resp.body!)) {
const str = decoder.decode(uint8Array)
console.debug('baichuan stream', str)
const lines = str.split('\n')
for (const line of lines) {
if (!line) {
continue
}
const data = JSON.parse(line)
if (!data.answer) {
continue
}
answerMessageId = data.answer.id
const text = data.answer.data
if (text) {
result += text
params.onEvent({ type: 'UPDATE_ANSWER', data: { text: result } })
}
}
}

this.conversationContext.historyMessages.push(message)
if (answerMessageId) {
this.conversationContext.lastMessageId = answerMessageId
if (result) {
this.conversationContext.historyMessages.push({
id: answerMessageId,
data: result,
createdAt: Date.now(),
from: 1,
})
}
}

params.onEvent({ type: 'DONE' })
}

resetConversation() {
this.conversationContext = undefined
}

get name() {
return '百川大模型'
}
}
31 changes: 20 additions & 11 deletions src/app/bots/bing/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { random } from 'lodash-es'
import { FetchError, ofetch } from 'ofetch'
import { FetchError, FetchResponse, ofetch } from 'ofetch'
import { uuid } from '~utils'
import { ChatError, ErrorCode } from '~utils/errors'
import { ConversationResponse } from './types'
Expand All @@ -14,32 +14,41 @@ const API_ENDPOINT = 'https://www.bing.com/turing/conversation/create'
export async function createConversation(): Promise<ConversationResponse> {
const headers = {
'x-ms-client-request-id': uuid(),
'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/Win32',
'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.3 OS/macOS',
}

let resp: ConversationResponse
let rawResponse: FetchResponse<ConversationResponse>
try {
resp = await ofetch(API_ENDPOINT, { headers, redirect: 'error' })
if (!resp.result) {
rawResponse = await ofetch.raw<ConversationResponse>(API_ENDPOINT, { headers, redirect: 'error' })
if (!rawResponse._data?.result) {
throw new Error('Invalid response')
}
} catch (err) {
console.error('retry bing create', err)
resp = await ofetch(API_ENDPOINT, {
rawResponse = await ofetch.raw<ConversationResponse>(API_ENDPOINT, {
headers: { ...headers, 'x-forwarded-for': randomIP() },
redirect: 'error',
})
if (!resp) {
if (!rawResponse._data) {
throw new FetchError(`Failed to fetch (${API_ENDPOINT})`)
}
}

if (resp.result.value !== 'Success') {
const message = `${resp.result.value}: ${resp.result.message}`
if (resp.result.value === 'UnauthorizedRequest') {
const data = rawResponse._data

if (data.result.value !== 'Success') {
const message = `${data.result.value}: ${data.result.message}`
if (data.result.value === 'UnauthorizedRequest') {
throw new ChatError(message, ErrorCode.BING_UNAUTHORIZED)
}
throw new Error(message)
}
return resp

const conversationSignature = rawResponse.headers.get('x-sydney-conversationsignature')!
const encryptedConversationSignature = rawResponse.headers.get('x-sydney-encryptedconversationsignature') || undefined

data.conversationSignature = data.conversationSignature || conversationSignature
data.encryptedConversationSignature = encryptedConversationSignature

return data
}
Loading

0 comments on commit ffafd95

Please sign in to comment.