mirror of
https://git.boos.lat/aibo/BossChat.git
synced 2026-10-30 23:26:09 +00:00
refactor: rebrand from cs-agent to BossChat
- Rename Go module: cs-agent → bosschat - Rename all import paths across 200+ Go files - Rename SDK: cs-ai-agent-sdk → bosschat-sdk - Rename message protocol: cs-agent:* → bosschat:* - Rename JS globals: CSAgentConfig → BossChatConfig - Rename CSS classes: cs-agent-* → bosschat-* - Update Makefile APP_NAME and ARCHIVE_NAME - Update logo assets - Fix display name: BoosChat → BossChat
This commit is contained in:
@@ -37,14 +37,14 @@ function createElement(tagName) {
|
||||
}
|
||||
|
||||
async function loadSdk(config) {
|
||||
const source = await readFile(new URL("./cs-ai-agent-sdk.ts", import.meta.url), "utf8")
|
||||
const source = await readFile(new URL("./bosschat-sdk.ts", import.meta.url), "utf8")
|
||||
const compiled = ts.transpileModule(source, {
|
||||
compilerOptions: {
|
||||
target: ts.ScriptTarget.ES2017,
|
||||
module: ts.ModuleKind.ESNext,
|
||||
importsNotUsedAsValues: ts.ImportsNotUsedAsValues.Remove,
|
||||
},
|
||||
fileName: "cs-ai-agent-sdk.ts",
|
||||
fileName: "bosschat-sdk.ts",
|
||||
})
|
||||
const body = createElement("body")
|
||||
const sandbox = {
|
||||
@@ -62,7 +62,7 @@ async function loadSdk(config) {
|
||||
document: {
|
||||
body,
|
||||
currentScript: {
|
||||
src: "https://chat.example/sdk/cs-ai-agent-sdk.min.js",
|
||||
src: "https://chat.example/sdk/bosschat-sdk.min.js",
|
||||
},
|
||||
createElement,
|
||||
createElementNS: (_namespace, tagName) => createElement(tagName),
|
||||
@@ -127,7 +127,7 @@ test("launcher click creates chat iframe with a freshly resolved userToken", asy
|
||||
})
|
||||
await flushPromises()
|
||||
const launcher = sandbox.document.body.children.find(
|
||||
(child) => child.dataset.csAgentWidget === "launcher"
|
||||
(child) => child.dataset.bossChatWidget === "launcher"
|
||||
)
|
||||
|
||||
assert.ok(launcher)
|
||||
@@ -136,7 +136,7 @@ test("launcher click creates chat iframe with a freshly resolved userToken", asy
|
||||
await flushPromises()
|
||||
|
||||
const frame = sandbox.document.body.children.find(
|
||||
(child) => child.dataset.csAgentWidget === "frame"
|
||||
(child) => child.dataset.bossChatWidget === "frame"
|
||||
)
|
||||
|
||||
assert.ok(frame)
|
||||
@@ -150,14 +150,14 @@ test("chat iframe layout uses dynamic viewport height for iOS browser chrome", a
|
||||
})
|
||||
await flushPromises()
|
||||
const launcher = sandbox.document.body.children.find(
|
||||
(child) => child.dataset.csAgentWidget === "launcher"
|
||||
(child) => child.dataset.bossChatWidget === "launcher"
|
||||
)
|
||||
|
||||
launcher.click()
|
||||
await flushPromises()
|
||||
|
||||
const frame = sandbox.document.body.children.find(
|
||||
(child) => child.dataset.csAgentWidget === "frame"
|
||||
(child) => child.dataset.bossChatWidget === "frame"
|
||||
)
|
||||
|
||||
assert.ok(frame)
|
||||
@@ -1,10 +1,10 @@
|
||||
import type {
|
||||
CSAgentConfig,
|
||||
CSAgentWidget,
|
||||
BossChatConfig,
|
||||
BossChatWidget,
|
||||
KefuChatRuntimeConfig,
|
||||
} from "./config-types"
|
||||
|
||||
type NormalizedCSAgentConfig = CSAgentConfig & {
|
||||
type NormalizedBossChatConfig = BossChatConfig & {
|
||||
baseUrl: string
|
||||
channelId: string
|
||||
position: "left" | "right"
|
||||
@@ -23,7 +23,7 @@ type WidgetState = {
|
||||
configLoading: boolean
|
||||
frameHideTimer: number | null
|
||||
frameDestroyTimer: number | null
|
||||
config: NormalizedCSAgentConfig | null
|
||||
config: NormalizedBossChatConfig | null
|
||||
frameConfig: KefuChatRuntimeConfig | null
|
||||
frameUrl: URL | null
|
||||
animationDuration: number
|
||||
@@ -33,20 +33,20 @@ type WidgetState = {
|
||||
type WidgetConfigResponse = {
|
||||
success?: boolean
|
||||
data?: Partial<Pick<
|
||||
CSAgentConfig,
|
||||
BossChatConfig,
|
||||
"title" | "subtitle" | "themeColor" | "position" | "width"
|
||||
>>
|
||||
}
|
||||
|
||||
type FrameMessage =
|
||||
| { type: "cs-agent:init"; payload: KefuChatRuntimeConfig }
|
||||
| { type: "cs-agent:open" }
|
||||
| { type: "cs-agent:minimize" }
|
||||
| { type: "cs-agent:maximized"; payload: { isMaximized: boolean } }
|
||||
| { type: "bosschat:init"; payload: KefuChatRuntimeConfig }
|
||||
| { type: "bosschat:open" }
|
||||
| { type: "bosschat:minimize" }
|
||||
| { type: "bosschat:maximized"; payload: { isMaximized: boolean } }
|
||||
|
||||
(function () {
|
||||
const DEFAULT_CONFIG: Pick<
|
||||
NormalizedCSAgentConfig,
|
||||
NormalizedBossChatConfig,
|
||||
"position" | "themeColor" | "width"
|
||||
> = {
|
||||
position: "right",
|
||||
@@ -54,7 +54,7 @@ type FrameMessage =
|
||||
width: "380px",
|
||||
}
|
||||
|
||||
const existingState = window.__CS_AGENT_WIDGET_STATE__ as WidgetState | undefined
|
||||
const existingState = window.__BOSSCHAT_WIDGET_STATE__ as WidgetState | undefined
|
||||
const state: WidgetState =
|
||||
existingState || {
|
||||
button: null,
|
||||
@@ -73,10 +73,10 @@ type FrameMessage =
|
||||
animationDuration: 260,
|
||||
}
|
||||
if (!existingState) {
|
||||
window.__CS_AGENT_WIDGET_STATE__ = state
|
||||
window.__BOSSCHAT_WIDGET_STATE__ = state
|
||||
}
|
||||
|
||||
function normalizeConfig(config?: CSAgentConfig): NormalizedCSAgentConfig {
|
||||
function normalizeConfig(config?: BossChatConfig): NormalizedBossChatConfig {
|
||||
const merged: Record<string, unknown> = { ...DEFAULT_CONFIG, ...(config || {}) }
|
||||
merged.baseUrl = String(merged.baseUrl || window.location.origin).replace(/\/$/, "")
|
||||
if (merged.apiBaseUrl) {
|
||||
@@ -91,18 +91,18 @@ type FrameMessage =
|
||||
if (typeof merged.getUserToken !== "function") {
|
||||
delete merged.getUserToken
|
||||
}
|
||||
return merged as NormalizedCSAgentConfig
|
||||
return merged as NormalizedBossChatConfig
|
||||
}
|
||||
|
||||
function resolveWidgetBaseUrl(config: NormalizedCSAgentConfig) {
|
||||
function resolveWidgetBaseUrl(config: NormalizedBossChatConfig) {
|
||||
const currentScript = document.currentScript as HTMLScriptElement | null
|
||||
if (currentScript?.src) {
|
||||
return currentScript.src.replace(/\/sdk\/cs-ai-agent-sdk\.min\.js(?:\?.*)?$/, "")
|
||||
return currentScript.src.replace(/\/sdk\/bosschat-sdk\.min\.js(?:\?.*)?$/, "")
|
||||
}
|
||||
return String(config.widgetBaseUrl || config.baseUrl || window.location.origin).replace(/\/$/, "")
|
||||
}
|
||||
|
||||
function createFrameUrl(config: NormalizedCSAgentConfig, userToken: string) {
|
||||
function createFrameUrl(config: NormalizedBossChatConfig, userToken: string) {
|
||||
const widgetBaseUrl = resolveWidgetBaseUrl(config)
|
||||
const frameUrl = new URL(`${widgetBaseUrl}/kefu/chat/`)
|
||||
frameUrl.searchParams.set("channelId", config.channelId)
|
||||
@@ -115,7 +115,7 @@ type FrameMessage =
|
||||
}
|
||||
|
||||
function createFrameConfig(
|
||||
config: NormalizedCSAgentConfig,
|
||||
config: NormalizedBossChatConfig,
|
||||
userToken: string
|
||||
): KefuChatRuntimeConfig {
|
||||
const { getUserToken: _getUserToken, ...payload } = config
|
||||
@@ -151,13 +151,13 @@ type FrameMessage =
|
||||
}
|
||||
|
||||
function mergeWidgetConfig(
|
||||
config: NormalizedCSAgentConfig,
|
||||
config: NormalizedBossChatConfig,
|
||||
remoteConfig?: WidgetConfigResponse["data"]
|
||||
) {
|
||||
if (!remoteConfig) {
|
||||
return config
|
||||
}
|
||||
const merged: NormalizedCSAgentConfig = { ...config }
|
||||
const merged: NormalizedBossChatConfig = { ...config }
|
||||
const remoteKeys = ["title", "subtitle", "themeColor", "position", "width"] as const
|
||||
remoteKeys.forEach((key) => {
|
||||
const value = remoteConfig[key]
|
||||
@@ -168,7 +168,7 @@ type FrameMessage =
|
||||
return merged
|
||||
}
|
||||
|
||||
function fetchWidgetConfig(config: NormalizedCSAgentConfig) {
|
||||
function fetchWidgetConfig(config: NormalizedBossChatConfig) {
|
||||
const baseUrl = String(config.apiBaseUrl || config.baseUrl || "").replace(/\/$/, "")
|
||||
if (!baseUrl || !config.channelId || typeof fetch !== "function") {
|
||||
return Promise.resolve(config)
|
||||
@@ -254,7 +254,7 @@ type FrameMessage =
|
||||
try {
|
||||
state.frame.contentWindow.postMessage(message, state.frameUrl.origin)
|
||||
} catch (error) {
|
||||
console.error("[cs-agent-widget] postMessage failed", error)
|
||||
console.error("[bosschat-widget] postMessage failed", error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,14 +266,14 @@ type FrameMessage =
|
||||
if (!state.initSent) {
|
||||
state.initSent = true
|
||||
postToFrame({
|
||||
type: "cs-agent:init",
|
||||
type: "bosschat:init",
|
||||
payload: state.frameConfig || createFrameConfig(state.config, ""),
|
||||
})
|
||||
}
|
||||
|
||||
postToFrame({ type: state.isOpen ? "cs-agent:open" : "cs-agent:minimize" })
|
||||
postToFrame({ type: state.isOpen ? "bosschat:open" : "bosschat:minimize" })
|
||||
postToFrame({
|
||||
type: "cs-agent:maximized",
|
||||
type: "bosschat:maximized",
|
||||
payload: { isMaximized: state.isMaximized },
|
||||
})
|
||||
}
|
||||
@@ -350,7 +350,7 @@ type FrameMessage =
|
||||
}
|
||||
|
||||
state.frame = document.createElement("iframe")
|
||||
state.frame.dataset.csAgentWidget = "frame"
|
||||
state.frame.dataset.bossChatWidget = "frame"
|
||||
state.frame.title = state.config.title || "在线客服"
|
||||
state.frame.src = state.frameUrl.toString()
|
||||
applyFrameLayout()
|
||||
@@ -374,24 +374,24 @@ type FrameMessage =
|
||||
}
|
||||
|
||||
const data = (event.data || {}) as { type?: string }
|
||||
if (data.type === "cs-agent:ready") {
|
||||
if (data.type === "bosschat:ready") {
|
||||
state.frameReady = true
|
||||
flushFrameState()
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === "cs-agent:request-minimize") {
|
||||
if (data.type === "bosschat:request-minimize") {
|
||||
state.isOpen = false
|
||||
syncFrameVisibility()
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === "cs-agent:request-close") {
|
||||
if (data.type === "bosschat:request-close") {
|
||||
destroyFrame()
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === "cs-agent:request-toggle-maximize") {
|
||||
if (data.type === "bosschat:request-toggle-maximize") {
|
||||
state.isMaximized = !state.isMaximized
|
||||
syncFrameVisibility()
|
||||
}
|
||||
@@ -416,7 +416,7 @@ type FrameMessage =
|
||||
]
|
||||
const text = document.createElement("span")
|
||||
button.type = "button"
|
||||
button.dataset.csAgentWidget = "launcher"
|
||||
button.dataset.bossChatWidget = "launcher"
|
||||
button.setAttribute("aria-label", config.title || "在线客服")
|
||||
icon.setAttribute("viewBox", "0 0 24 24")
|
||||
icon.setAttribute("fill", "none")
|
||||
@@ -473,15 +473,15 @@ type FrameMessage =
|
||||
return button
|
||||
}
|
||||
|
||||
function mount(config?: CSAgentConfig) {
|
||||
const rawConfig = config || window.CSAgentConfig || { channelId: "" }
|
||||
function mount(config?: BossChatConfig) {
|
||||
const rawConfig = config || window.BossChatConfig || { channelId: "" }
|
||||
state.config = normalizeConfig(rawConfig)
|
||||
const widgetBaseUrl = resolveWidgetBaseUrl(state.config)
|
||||
if (!rawConfig.baseUrl) {
|
||||
state.config.baseUrl = widgetBaseUrl
|
||||
}
|
||||
if (!state.config.channelId) {
|
||||
console.error("[cs-agent-widget] channelId is required")
|
||||
console.error("[bosschat-widget] channelId is required")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -530,11 +530,11 @@ type FrameMessage =
|
||||
syncFrameVisibility()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("[cs-agent-widget] open failed", error)
|
||||
console.error("[bosschat-widget] open failed", error)
|
||||
})
|
||||
}
|
||||
|
||||
window.CSAgentWidget = {
|
||||
window.BossChatWidget = {
|
||||
mount,
|
||||
destroy,
|
||||
open: () => openWidget(),
|
||||
@@ -544,21 +544,21 @@ type FrameMessage =
|
||||
},
|
||||
getChatUrl: () => {
|
||||
if (!state.config) {
|
||||
mount(window.CSAgentConfig || { channelId: "" })
|
||||
mount(window.BossChatConfig || { channelId: "" })
|
||||
}
|
||||
if (!state.config?.channelId) {
|
||||
return Promise.reject(new Error("channelId is required"))
|
||||
}
|
||||
return prepareFrameUrl().then((frameUrl) => frameUrl.toString())
|
||||
},
|
||||
} satisfies CSAgentWidget
|
||||
} satisfies BossChatWidget
|
||||
|
||||
if (!state.listenerBound) {
|
||||
window.addEventListener("message", handleWindowMessage)
|
||||
state.listenerBound = true
|
||||
}
|
||||
|
||||
if (window.CSAgentConfig) {
|
||||
mount(window.CSAgentConfig)
|
||||
if (window.BossChatConfig) {
|
||||
mount(window.BossChatConfig)
|
||||
}
|
||||
})()
|
||||
@@ -1,4 +1,4 @@
|
||||
export type CSAgentConfig = {
|
||||
export type BossChatConfig = {
|
||||
channelId: string
|
||||
baseUrl?: string
|
||||
apiBaseUrl?: string
|
||||
@@ -16,13 +16,13 @@ export type CSAgentConfig = {
|
||||
width?: string
|
||||
}
|
||||
|
||||
export type KefuChatRuntimeConfig = Omit<CSAgentConfig, "getUserToken"> & {
|
||||
/** 仅用于 /kefu/chat 运行时换取客服会话 token,不属于 CSAgentConfig 接入参数 */
|
||||
export type KefuChatRuntimeConfig = Omit<BossChatConfig, "getUserToken"> & {
|
||||
/** 仅用于 /kefu/chat 运行时换取客服会话 token,不属于 BossChatConfig 接入参数 */
|
||||
userToken?: string
|
||||
}
|
||||
|
||||
export type CSAgentWidget = {
|
||||
mount: (config?: CSAgentConfig) => void
|
||||
export type BossChatWidget = {
|
||||
mount: (config?: BossChatConfig) => void
|
||||
destroy: () => void
|
||||
open: () => Promise<void>
|
||||
close: () => void
|
||||
@@ -31,9 +31,9 @@ export type CSAgentWidget = {
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
CSAgentConfig?: CSAgentConfig
|
||||
CSAgentWidget?: CSAgentWidget
|
||||
__CS_AGENT_WIDGET_CONFIG__?: KefuChatRuntimeConfig
|
||||
__CS_AGENT_WIDGET_STATE__?: unknown
|
||||
BossChatConfig?: BossChatConfig
|
||||
BossChatWidget?: BossChatWidget
|
||||
__BOSSCHAT_WIDGET_CONFIG__?: KefuChatRuntimeConfig
|
||||
__BOSSCHAT_WIDGET_STATE__?: unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ export function readKefuChatRuntimeConfig(): KefuChatRuntimeConfig {
|
||||
width: query.get("width") ?? undefined,
|
||||
}
|
||||
|
||||
if (window.__CS_AGENT_WIDGET_CONFIG__) {
|
||||
return window.__CS_AGENT_WIDGET_CONFIG__
|
||||
if (window.__BOSSCHAT_WIDGET_CONFIG__) {
|
||||
return window.__BOSSCHAT_WIDGET_CONFIG__
|
||||
}
|
||||
if (window.CSAgentConfig) {
|
||||
const { getUserToken: _getUserToken, ...hostConfig } = window.CSAgentConfig
|
||||
if (window.BossChatConfig) {
|
||||
const { getUserToken: _getUserToken, ...hostConfig } = window.BossChatConfig
|
||||
return {
|
||||
...fallback,
|
||||
...hostConfig,
|
||||
@@ -50,5 +50,5 @@ export function setKefuChatRuntimeConfig(config: KefuChatRuntimeConfig) {
|
||||
if (typeof window === "undefined") {
|
||||
return
|
||||
}
|
||||
window.__CS_AGENT_WIDGET_CONFIG__ = config
|
||||
window.__BOSSCHAT_WIDGET_CONFIG__ = config
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user