|
|
|
@@ -0,0 +1,624 @@
|
|
|
|
|
import { pushRecord, setAbortController } from './shared.mjs'
|
|
|
|
|
import { Models, setUserConfig } from '../../config/index.mjs'
|
|
|
|
|
import { fetchSSE } from '../../utils/fetch-sse'
|
|
|
|
|
import { isEmpty } from 'lodash-es'
|
|
|
|
|
|
|
|
|
|
export class MoonshotWeb {
|
|
|
|
|
/**
|
|
|
|
|
* If the moonshot client has initialized yet (call `init()` if you haven't and this is false)
|
|
|
|
|
* @property {boolean}
|
|
|
|
|
*/
|
|
|
|
|
ready
|
|
|
|
|
/**
|
|
|
|
|
* A proxy function/string to connect via
|
|
|
|
|
* @property {({endpoint: string, options: Object}) => {endpoint: string, options: Object} | string}
|
|
|
|
|
*/
|
|
|
|
|
proxy
|
|
|
|
|
/**
|
|
|
|
|
* A fetch function, defaults to globalThis.fetch
|
|
|
|
|
* @property {Function}
|
|
|
|
|
*/
|
|
|
|
|
fetch
|
|
|
|
|
/**
|
|
|
|
|
* @property {UserConfig}
|
|
|
|
|
*/
|
|
|
|
|
config
|
|
|
|
|
|
|
|
|
|
refreshToken
|
|
|
|
|
|
|
|
|
|
accessToken
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new moonshot API client instance.
|
|
|
|
|
* @param {Object} options - Options
|
|
|
|
|
* @param {UserConfig} options.config
|
|
|
|
|
* @param {function} [options.fetch] - Fetch function
|
|
|
|
|
* @example
|
|
|
|
|
* const moonshot = new moonshot({
|
|
|
|
|
* sessionKey: 'sk-ant-sid01-*****',
|
|
|
|
|
* fetch: globalThis.fetch
|
|
|
|
|
* })
|
|
|
|
|
*
|
|
|
|
|
* await moonshot.init();
|
|
|
|
|
* moonshot.sendMessage('Hello world').then(console.log)
|
|
|
|
|
*/
|
|
|
|
|
constructor({ config, fetch }) {
|
|
|
|
|
if (fetch) {
|
|
|
|
|
this.fetch = fetch
|
|
|
|
|
}
|
|
|
|
|
this.config = config
|
|
|
|
|
this.refreshToken = config.kimiMoonShotRefreshToken
|
|
|
|
|
this.accessToken = config.kimiMoonShotAccessToken
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Get available models.
|
|
|
|
|
* @returns {string[]} Array of model names
|
|
|
|
|
*/
|
|
|
|
|
models() {
|
|
|
|
|
return ['']
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Get the default model.
|
|
|
|
|
* @returns {string} Default model name
|
|
|
|
|
*/
|
|
|
|
|
defaultModel() {
|
|
|
|
|
return this.models()[0]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* todo: mod
|
|
|
|
|
* Send a message to a new or existing conversation.
|
|
|
|
|
* @param {string} message - Initial message
|
|
|
|
|
* @param {SendMessageParams} [params] - Additional parameters
|
|
|
|
|
* @param {string} [params.conversation] - Existing conversation ID
|
|
|
|
|
* @param {boolean} [params.temporary=true] - Delete after getting response
|
|
|
|
|
* @returns {Promise<MessageStreamChunk>} Result message
|
|
|
|
|
*/
|
|
|
|
|
async sendMessage(message, { conversation = null, temporary = true, ...params }) {
|
|
|
|
|
if (!this.ready) {
|
|
|
|
|
await this.init()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!conversation) {
|
|
|
|
|
let out
|
|
|
|
|
let convo = await this.startConversation(message, {
|
|
|
|
|
...params,
|
|
|
|
|
done: (a) => {
|
|
|
|
|
if (params.done) {
|
|
|
|
|
params.done(a)
|
|
|
|
|
}
|
|
|
|
|
out = a
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if (temporary) {
|
|
|
|
|
await convo.delete()
|
|
|
|
|
}
|
|
|
|
|
return out
|
|
|
|
|
} else {
|
|
|
|
|
return (await this.getConversation(conversation)).sendMessage(message, {
|
|
|
|
|
...params,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Make an API request.
|
|
|
|
|
* @param {string} endpoint - API endpoint
|
|
|
|
|
* @param {Object} options - Request options
|
|
|
|
|
* @returns {Promise<Response>} Fetch response
|
|
|
|
|
* @example
|
|
|
|
|
* await a.request('/api/chat/cnor0teaofogidj025b0/completion/stream').then(r => r.json())
|
|
|
|
|
*/
|
|
|
|
|
request(endpoint, options) {
|
|
|
|
|
// Can't figure out a way to test this so I'm just assuming it works
|
|
|
|
|
if (!(this.fetch || globalThis.fetch)) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`No fetch available in your environment. Use node-18 or later, a modern browser, or add the following code to your project:\n\nimport "isomorphic-fetch";\nconst moonshot = new moonshot({fetch: fetch, sessionKey: "sk-ant-sid01-*****"});`,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
if (!this.proxy) {
|
|
|
|
|
this.proxy = ({ endpoint, options }) => ({
|
|
|
|
|
endpoint: 'https://kimi.moonshot.cn' + endpoint,
|
|
|
|
|
options,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if (typeof this.proxy === 'string') {
|
|
|
|
|
const HOST = this.proxy
|
|
|
|
|
this.proxy = ({ endpoint, options }) => ({ endpoint: HOST + endpoint, options })
|
|
|
|
|
}
|
|
|
|
|
const proxied = this.proxy({ endpoint, options })
|
|
|
|
|
return (this.fetch || globalThis.fetch)(proxied.endpoint, proxied.options)
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the client.
|
|
|
|
|
* @async
|
|
|
|
|
* @returns {Promise<void>} Void
|
|
|
|
|
*/
|
|
|
|
|
async init() {
|
|
|
|
|
const response = this.request('/api/user', {
|
|
|
|
|
headers: {
|
|
|
|
|
accept: '*/*',
|
|
|
|
|
Authorization: `Bearer ${this.accessToken}`,
|
|
|
|
|
Origin: 'https://kimi.moonshot.cn',
|
|
|
|
|
},
|
|
|
|
|
method: 'GET',
|
|
|
|
|
})
|
|
|
|
|
if ((await response).status === 200) {
|
|
|
|
|
this.ready = true
|
|
|
|
|
} else {
|
|
|
|
|
const { access_token, refresh_token } = await this.request('/api/auth/token/refresh', {
|
|
|
|
|
headers: {
|
|
|
|
|
accept: '*/*',
|
|
|
|
|
Authorization: `Bearer ${this.refreshToken}`,
|
|
|
|
|
Origin: 'https://kimi.moonshot.cn',
|
|
|
|
|
},
|
|
|
|
|
method: 'GET',
|
|
|
|
|
})
|
|
|
|
|
.then((r) => r.json())
|
|
|
|
|
.catch(errorHandle('get kimi.moonshoot.cn access_token'))
|
|
|
|
|
this.accessToken = access_token
|
|
|
|
|
this.refreshToken = refresh_token
|
|
|
|
|
this.config.kimiMoonShotAccessToken = access_token
|
|
|
|
|
this.config.kimiMoonShotRefreshToken = refresh_token
|
|
|
|
|
await setUserConfig({
|
|
|
|
|
kimiMoonShotAccessToken: access_token,
|
|
|
|
|
kimiMoonShotRefreshToken: refresh_token,
|
|
|
|
|
})
|
|
|
|
|
this.ready = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Start a new conversation
|
|
|
|
|
* @param {String} message The message to send to start the conversation
|
|
|
|
|
* @param {SendMessageParams} [params={}] Message params passed to Conversation.sendMessage
|
|
|
|
|
* @returns {Promise<Conversation>}
|
|
|
|
|
* @async
|
|
|
|
|
* @example
|
|
|
|
|
* const conversation = await moonshot.startConversation("Hello! How are you?")
|
|
|
|
|
* console.log(await conversation.getInfo());
|
|
|
|
|
*/
|
|
|
|
|
async startConversation(message, params = {}) {
|
|
|
|
|
if (!this.ready) {
|
|
|
|
|
await this.init()
|
|
|
|
|
}
|
|
|
|
|
const { id, name, created_at } = await this.request('/api/chat', {
|
|
|
|
|
headers: {
|
|
|
|
|
accept: '*/*',
|
|
|
|
|
'content-type': 'application/json',
|
|
|
|
|
Authorization: `Bearer ${this.accessToken}`,
|
|
|
|
|
Origin: 'https://kimi.moonshot.cn',
|
|
|
|
|
},
|
|
|
|
|
method: 'POST',
|
|
|
|
|
signal: params.signal,
|
|
|
|
|
body: JSON.stringify({ name: '未命名会话', is_example: false }),
|
|
|
|
|
})
|
|
|
|
|
.then((r) => r.json())
|
|
|
|
|
.catch(errorHandle('startConversation create'))
|
|
|
|
|
const convo = new Conversation(this, {
|
|
|
|
|
conversationId: id,
|
|
|
|
|
name,
|
|
|
|
|
created_at,
|
|
|
|
|
})
|
|
|
|
|
await convo.sendMessage(message, params)
|
|
|
|
|
return convo
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Get a conversation by its ID
|
|
|
|
|
* @param {UUID} id The uuid of the conversation (Conversation.uuid or Conversation.conversationId)
|
|
|
|
|
* @async
|
|
|
|
|
* @returns {Conversation | null} The conversation
|
|
|
|
|
* @example
|
|
|
|
|
* const conversation = await moonshot.getConversation("222aa20a-bc79-48d2-8f6d-c819a1b5eaed");
|
|
|
|
|
*/
|
|
|
|
|
async getConversation(id) {
|
|
|
|
|
if (id instanceof Conversation || id.conversationId) {
|
|
|
|
|
return new Conversation(this, { conversationId: id.conversationId })
|
|
|
|
|
}
|
|
|
|
|
return new Conversation(this, { conversationId: id })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @typedef SendMessageParams
|
|
|
|
|
* @property {Boolean} [retry=false] Whether to retry the most recent message in the conversation instead of sending a new one
|
|
|
|
|
* @property {String} [timezone="America/New_York"] The timezone
|
|
|
|
|
* @property {Attachment[]} [attachments=[]] Attachments
|
|
|
|
|
* @property {doneCallback} [done] Callback when done receiving the message response
|
|
|
|
|
* @property {progressCallback} [progress] Callback on message response progress
|
|
|
|
|
* @property {string} [model=moonshot.defaultModel()] The model to use
|
|
|
|
|
*/
|
|
|
|
|
/**
|
|
|
|
|
* A moonshot conversation instance.
|
|
|
|
|
* @class
|
|
|
|
|
* @typedef Conversation
|
|
|
|
|
* @classdesc Represents an active moonshot conversation.
|
|
|
|
|
*/
|
|
|
|
|
export class Conversation {
|
|
|
|
|
/**
|
|
|
|
|
* The conversation ID
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
conversationId
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The conversation name
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
name
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The conversation summary (usually empty)
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
summary
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The conversation created at
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
created_at
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The conversation updated at
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
updated_at
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The request function (from parent moonshot instance)
|
|
|
|
|
* @property {(url: string, options: object) => Response}
|
|
|
|
|
*/
|
|
|
|
|
request
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The current model
|
|
|
|
|
* @property {string}
|
|
|
|
|
*/
|
|
|
|
|
model
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If the moonshot client has initialized yet (call `init()` if you haven't and this is false)
|
|
|
|
|
* @property {boolean}
|
|
|
|
|
*/
|
|
|
|
|
ready
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A proxy function/string to connect via
|
|
|
|
|
* @property {({endpoint: string, options: Object}) => {endpoint: string, options: Object} | string}
|
|
|
|
|
*/
|
|
|
|
|
proxy
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A fetch function, defaults to globalThis.fetch
|
|
|
|
|
* @property {Function}
|
|
|
|
|
*/
|
|
|
|
|
fetch
|
|
|
|
|
/**
|
|
|
|
|
* Create a Conversation instance.
|
|
|
|
|
* @param {MoonshotWeb} moonshot - moonshot client instance
|
|
|
|
|
* @param {Object} options - Options
|
|
|
|
|
* @param {String} options.conversationId - Conversation ID
|
|
|
|
|
* @param {String} [options.name] - Conversation name
|
|
|
|
|
* @param {String} [options.summary] - Conversation summary
|
|
|
|
|
* @param {String} [options.created_at] - Conversation created at
|
|
|
|
|
* @param {String} [options.updated_at] - Conversation updated at
|
|
|
|
|
* @param {String} [options.model] - moonshot model
|
|
|
|
|
*/
|
|
|
|
|
constructor(
|
|
|
|
|
moonshot,
|
|
|
|
|
{ model = 'default', conversationId, name = '', summary = '', created_at, updated_at },
|
|
|
|
|
) {
|
|
|
|
|
this.moonshot = moonshot
|
|
|
|
|
this.conversationId = conversationId
|
|
|
|
|
this.request = moonshot.request
|
|
|
|
|
if (!this.moonshot) {
|
|
|
|
|
throw new Error('moonshot not initialized')
|
|
|
|
|
}
|
|
|
|
|
if (!this.moonshot.refreshToken) {
|
|
|
|
|
throw new Error('moonshot token required, please login at https://kimi.moonshot.cn first')
|
|
|
|
|
}
|
|
|
|
|
if (!this.conversationId) {
|
|
|
|
|
throw new Error('Conversation ID required, are you calling `await moonshot.init()`?')
|
|
|
|
|
}
|
|
|
|
|
if (model === 'default') {
|
|
|
|
|
model = this.moonshot.defaultModel()
|
|
|
|
|
}
|
|
|
|
|
this.model = model || this.moonshot.defaultModel()
|
|
|
|
|
Object.assign(this, {
|
|
|
|
|
name,
|
|
|
|
|
summary,
|
|
|
|
|
created_at: created_at || new Date().toISOString(),
|
|
|
|
|
updated_at: updated_at || new Date().toISOString(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Convert the conversation to a JSON object
|
|
|
|
|
* @returns {Conversation} The serializable object
|
|
|
|
|
*/
|
|
|
|
|
toJSON() {
|
|
|
|
|
return {
|
|
|
|
|
conversationId: this.conversationId,
|
|
|
|
|
name: this.name,
|
|
|
|
|
summary: this.summary,
|
|
|
|
|
created_at: this.created_at,
|
|
|
|
|
updated_at: this.updated_at,
|
|
|
|
|
model: this.model,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Retry the last message in the conversation
|
|
|
|
|
* @param {SendMessageParams} [params={}]
|
|
|
|
|
* @returns {Promise<MessageStreamChunk>}
|
|
|
|
|
*/
|
|
|
|
|
async retry(params) {
|
|
|
|
|
return this.sendMessage('', { ...params, retry: true })
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Send a message to this conversation
|
|
|
|
|
* @param {String} message
|
|
|
|
|
* @async
|
|
|
|
|
* @param {SendMessageParams} params The parameters to send along with the message
|
|
|
|
|
* @returns {Promise<MessageStreamChunk>}
|
|
|
|
|
*/
|
|
|
|
|
async sendMessage(
|
|
|
|
|
message,
|
|
|
|
|
{
|
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
|
retry = false,
|
|
|
|
|
model = 'default',
|
|
|
|
|
done = () => {},
|
|
|
|
|
progress = () => {},
|
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
|
rawResponse = () => {},
|
|
|
|
|
signal = null,
|
|
|
|
|
} = {},
|
|
|
|
|
) {
|
|
|
|
|
if (model === 'default') {
|
|
|
|
|
model = this.moonshot.defaultModel()
|
|
|
|
|
}
|
|
|
|
|
// {"messages":[{"role":"user","content":"hello"}],"refs":[],"use_search":true}
|
|
|
|
|
const body = { messages: [{ role: 'user', content: message }], refs: [], use_search: true }
|
|
|
|
|
let resolve, reject
|
|
|
|
|
let returnPromise = new Promise((r, j) => {
|
|
|
|
|
resolve = r
|
|
|
|
|
reject = j
|
|
|
|
|
})
|
|
|
|
|
let fullResponse = ''
|
|
|
|
|
await fetchSSE(`https://kimi.moonshot.cn/api/chat/${this.conversationId}/completion/stream`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
accept: '*/*',
|
|
|
|
|
'content-type': 'application/json',
|
|
|
|
|
Authorization: `Bearer ${this.moonshot.accessToken}`,
|
|
|
|
|
},
|
|
|
|
|
signal: signal,
|
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
|
onMessage(message) {
|
|
|
|
|
console.debug('sse message', message)
|
|
|
|
|
let parsed
|
|
|
|
|
try {
|
|
|
|
|
parsed = JSON.parse(message)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.debug('json error', error)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (parsed.event === 'cmpl' && parsed.text) fullResponse += parsed.text
|
|
|
|
|
const PROGRESS_OBJECT = {
|
|
|
|
|
...parsed,
|
|
|
|
|
completion: fullResponse,
|
|
|
|
|
delta: parsed.text || '',
|
|
|
|
|
}
|
|
|
|
|
progress(PROGRESS_OBJECT)
|
|
|
|
|
if (parsed.event === 'all_done') {
|
|
|
|
|
done(PROGRESS_OBJECT)
|
|
|
|
|
resolve(PROGRESS_OBJECT)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async onStart() {},
|
|
|
|
|
async onEnd() {
|
|
|
|
|
resolve({
|
|
|
|
|
completion: fullResponse,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
async onError(resp) {
|
|
|
|
|
if (resp instanceof Error) {
|
|
|
|
|
reject(resp)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const error = await resp.json().catch(() => ({}))
|
|
|
|
|
reject(
|
|
|
|
|
new Error(!isEmpty(error) ? JSON.stringify(error) : `${resp.status} ${resp.statusText}`),
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
return returnPromise
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete the conversation
|
|
|
|
|
* @async
|
|
|
|
|
* @returns Promise<Response>
|
|
|
|
|
*/
|
|
|
|
|
async delete() {
|
|
|
|
|
return await this.request(`/api/chat/chat_conversations/${this.conversationId}`, {
|
|
|
|
|
headers: {
|
|
|
|
|
accept: '*/*',
|
|
|
|
|
Authorization: `Bearer ${this.moonshot.accessToken}`,
|
|
|
|
|
Origin: 'https://kimi.moonshot.cn',
|
|
|
|
|
},
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
}).catch(errorHandle('Delete conversation ' + this.conversationId))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get all messages in the conversation
|
|
|
|
|
* @async
|
|
|
|
|
* @returns {Promise<Message[]>}
|
|
|
|
|
*/
|
|
|
|
|
getMessages() {
|
|
|
|
|
return this.getInfo()
|
|
|
|
|
.then((a) => a.chat_messages)
|
|
|
|
|
.catch(errorHandle('getMessages'))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A function that handles errors.
|
|
|
|
|
*
|
|
|
|
|
* @param {string} msg - The error message.
|
|
|
|
|
* @return {function} - A function that logs the error message and exits the process.
|
|
|
|
|
*/
|
|
|
|
|
function errorHandle(msg) {
|
|
|
|
|
return (e) => {
|
|
|
|
|
console.error(`Error at: ${msg}`)
|
|
|
|
|
console.error(e)
|
|
|
|
|
// process.exit(0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @typedef JSONResponse
|
|
|
|
|
* @property {'human' | 'assistant'} sender The sender
|
|
|
|
|
* @property {string} text The text
|
|
|
|
|
* @property {UUID} uuid msg uuid
|
|
|
|
|
* @property {string} created_at The message created at
|
|
|
|
|
* @property {string} updated_at The message updated at
|
|
|
|
|
* @property {string} edited_at When the message was last edited (no editing support via api/web client)
|
|
|
|
|
* @property {Attachment[]} attachments The attachments
|
|
|
|
|
* @property {string} chat_feedback Feedback
|
|
|
|
|
*/
|
|
|
|
|
/**
|
|
|
|
|
* Message class
|
|
|
|
|
* @class
|
|
|
|
|
* @classdesc A class representing a message in a Conversation
|
|
|
|
|
* @property {Function} request The request function (inherited from moonshot instance)
|
|
|
|
|
* @property {JSONResponse} json The JSON representation
|
|
|
|
|
* @property {moonshot} moonshot The moonshot instance
|
|
|
|
|
* @property {Conversation} conversation The conversation this message belongs to
|
|
|
|
|
* @property {UUID} uuid The message uuid
|
|
|
|
|
*/
|
|
|
|
|
export class Message {
|
|
|
|
|
/**
|
|
|
|
|
* Create a Message instance.
|
|
|
|
|
* @param {Object} params - Params
|
|
|
|
|
* @param {Conversation} params.conversation - Conversation instance
|
|
|
|
|
* @param {moonshot} params.moonshot - moonshot instance
|
|
|
|
|
* @param {Message} message - Message data
|
|
|
|
|
*/
|
|
|
|
|
constructor(
|
|
|
|
|
{ conversation, moonshot },
|
|
|
|
|
{ uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments },
|
|
|
|
|
) {
|
|
|
|
|
if (!moonshot) {
|
|
|
|
|
throw new Error('moonshot not initialized')
|
|
|
|
|
}
|
|
|
|
|
if (!conversation) {
|
|
|
|
|
throw new Error('Conversation not initialized')
|
|
|
|
|
}
|
|
|
|
|
Object.assign(this, { conversation, moonshot })
|
|
|
|
|
this.request = moonshot.request
|
|
|
|
|
this.json = { uuid, text, sender, index, updated_at, edited_at, chat_feedback, attachments }
|
|
|
|
|
Object.assign(this, this.json)
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Convert this message to a JSON representation
|
|
|
|
|
* Necessary to prevent circular JSON errors
|
|
|
|
|
* @returns {Message}
|
|
|
|
|
*/
|
|
|
|
|
toJSON() {
|
|
|
|
|
return this.json
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Returns the value of the "created_at" property as a Date object.
|
|
|
|
|
*
|
|
|
|
|
* @return {Date} The value of the "created_at" property as a Date object.
|
|
|
|
|
*/
|
|
|
|
|
get createdAt() {
|
|
|
|
|
return new Date(this.json.created_at)
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Returns the value of the "updated_at" property as a Date object.
|
|
|
|
|
*
|
|
|
|
|
* @return {Date} The value of the "updated_at" property as a Date object.
|
|
|
|
|
*/
|
|
|
|
|
get updatedAt() {
|
|
|
|
|
return new Date(this.json.updated_at)
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Returns the value of the "edited_at" property as a Date object.
|
|
|
|
|
*
|
|
|
|
|
* @return {Date} The value of the "edited_at" property as a Date object.
|
|
|
|
|
*/
|
|
|
|
|
get editedAt() {
|
|
|
|
|
return new Date(this.json.edited_at)
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Get if message is from the assistant.
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
|
|
|
|
get isBot() {
|
|
|
|
|
return this.sender === 'assistant'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Runtime.Port} port
|
|
|
|
|
* @param {string} question
|
|
|
|
|
* @param {Session} session
|
|
|
|
|
* @param {UserConfig} config
|
|
|
|
|
* @param {string} modelName
|
|
|
|
|
*/
|
|
|
|
|
export async function generateAnswersWithMoonshotWebApi(
|
|
|
|
|
port,
|
|
|
|
|
question,
|
|
|
|
|
session,
|
|
|
|
|
config,
|
|
|
|
|
modelName,
|
|
|
|
|
) {
|
|
|
|
|
const bot = new MoonshotWeb({ config })
|
|
|
|
|
await bot.init()
|
|
|
|
|
const { controller, cleanController } = setAbortController(port)
|
|
|
|
|
|
|
|
|
|
let answer = ''
|
|
|
|
|
const progressFunc = ({ completion }) => {
|
|
|
|
|
answer = completion
|
|
|
|
|
port.postMessage({ answer: answer, done: false, session: null })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const doneFunc = () => {
|
|
|
|
|
pushRecord(session, question, answer)
|
|
|
|
|
console.debug('conversation history', { content: session.conversationRecords })
|
|
|
|
|
port.postMessage({ answer: answer, done: true, session: session })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
|
progress: progressFunc,
|
|
|
|
|
done: doneFunc,
|
|
|
|
|
model: Models[modelName].value,
|
|
|
|
|
signal: controller.signal,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!session.moonshot_conversation)
|
|
|
|
|
await bot
|
|
|
|
|
.startConversation(question, params)
|
|
|
|
|
.then((conversation) => {
|
|
|
|
|
session.moonshot_conversation = conversation
|
|
|
|
|
port.postMessage({ answer: answer, done: true, session: session })
|
|
|
|
|
cleanController()
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
cleanController()
|
|
|
|
|
throw err
|
|
|
|
|
})
|
|
|
|
|
else
|
|
|
|
|
await bot
|
|
|
|
|
.sendMessage(question, {
|
|
|
|
|
conversation: session.moonshot_conversation,
|
|
|
|
|
...params,
|
|
|
|
|
})
|
|
|
|
|
.then(cleanController)
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
cleanController()
|
|
|
|
|
throw err
|
|
|
|
|
})
|
|
|
|
|
}
|