@blade-hq/agent-react 2612.0.0-beta.54 → 2612.0.0-beta.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +13 -0
  2. package/dist/{chunk-OQQCJD3L.js → chunk-2U5HZ3PG.js} +6 -4
  3. package/dist/{chunk-OQQCJD3L.js.map → chunk-2U5HZ3PG.js.map} +1 -1
  4. package/dist/chunk-BQ6CUOP7.js +1904 -0
  5. package/dist/chunk-BQ6CUOP7.js.map +1 -0
  6. package/dist/{chunk-YP64AL24.js → chunk-FLNFZVZF.js} +2 -2
  7. package/dist/{chunk-VUDRKCD4.js → chunk-HS5G33FO.js} +379 -5149
  8. package/dist/chunk-HS5G33FO.js.map +1 -0
  9. package/dist/{chunk-NPIUZZET.js → chunk-IQMQB6Y6.js} +28 -7
  10. package/dist/chunk-IQMQB6Y6.js.map +1 -0
  11. package/dist/chunk-PMNUGFTJ.js +4978 -0
  12. package/dist/chunk-PMNUGFTJ.js.map +1 -0
  13. package/dist/{chunk-APE7QR3M.js → chunk-WA2DQEKV.js} +8 -6
  14. package/dist/{chunk-APE7QR3M.js.map → chunk-WA2DQEKV.js.map} +1 -1
  15. package/dist/components/ConnectorRuntimeDiagnostics.d.ts +5 -0
  16. package/dist/components/DeviceConnection.d.ts +15 -0
  17. package/dist/components/FeishuCapabilitySelection.d.ts +14 -0
  18. package/dist/connectors.d.ts +1 -0
  19. package/dist/connectors.js +9 -0
  20. package/dist/connectors.js.map +1 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +9 -4
  23. package/dist/internal.js +16 -10
  24. package/dist/internal.js.map +1 -1
  25. package/dist/questions.js +6 -4
  26. package/dist/questions.js.map +1 -1
  27. package/dist/rich-input.js +9 -6
  28. package/dist/rich-input.js.map +1 -1
  29. package/dist/style.full.css +1 -1
  30. package/package.json +7 -3
  31. package/public-api.md +7 -1
  32. package/dist/chunk-NPIUZZET.js.map +0 -1
  33. package/dist/chunk-VUDRKCD4.js.map +0 -1
  34. /package/dist/{chunk-YP64AL24.js.map → chunk-FLNFZVZF.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blade-hq/agent-react",
3
- "version": "2612.0.0-beta.54",
3
+ "version": "2612.0.0-beta.56",
4
4
  "description": "Blade Agent React 绑定:BladeProvider、useAgentSession、开箱即用的 ChatView 聊天界面。",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,11 @@
28
28
  },
29
29
  "./style.css": "./dist/style.css",
30
30
  "./style.full.css": "./dist/style.full.css",
31
- "./chat.css": "./dist/chat.css"
31
+ "./chat.css": "./dist/chat.css",
32
+ "./connectors": {
33
+ "types": "./dist/connectors.d.ts",
34
+ "import": "./dist/connectors.js"
35
+ }
32
36
  },
33
37
  "files": [
34
38
  "dist",
@@ -44,7 +48,7 @@
44
48
  "access": "public"
45
49
  },
46
50
  "dependencies": {
47
- "@blade-hq/agent-client": "2612.0.0-beta.54",
51
+ "@blade-hq/agent-client": "2612.0.0-beta.56",
48
52
  "@radix-ui/react-collapsible": "1.1.12",
49
53
  "@tiptap/core": "3.20.4",
50
54
  "@tiptap/extension-mention": "3.20.4",
package/public-api.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > 本文件由 `scripts/public-api-report.mjs` 生成,请勿手改。
4
4
  > 公共面变更时重新生成本报告,并同步更新 README 对应章节——CI 会校验两者。
5
5
 
6
- 共 40 个公开声明。
6
+ 共 41 个公开声明。
7
7
 
8
8
  ## `AskUserQuestionData` (interface)
9
9
 
@@ -138,6 +138,12 @@ footer: ReactNode
138
138
  header: ReactNode
139
139
  ```
140
140
 
141
+ ## `DeviceConnection` (function)
142
+
143
+ ```ts
144
+ DeviceConnection: ({ read, act, diagnostics, onChanged, bindDelivery, onDisable, initialPage, authorizationCapabilities, autoAuthorize }: { read: () => Promise<ConnectorAuthorization>; act: (action: ConnectorAuthorizationAction, options?: ConnectorAuthorizationOptions) => Promise<ConnectorAuthorization>; plan?: (capabilities: string[]) => Promise<ConnectorAuthorizationPlan>; diagnostics?: () => Promise<ConnectorDiagnostics>; onChanged: () => Promise<unknown>; bindDelivery?: boolean; onDisable?: () => Promise<unknown>; initialPage?: "connection" | "manage"; authorizationCapabilities?: string[]; autoAuthorize?: boolean; }) => JSX.Element
145
+ ```
146
+
141
147
  ## `FollowupInteractionEvent` (type)
142
148
 
143
149
  ```ts
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/connector-panel-types.ts","../src/components/AccountConnectors.tsx","../src/components/ConnectorPanel.tsx","../src/components/PluginTriggerStack.tsx"],"sourcesContent":["import type { PluginConnectorItem } from \"./plugin-connector\"\n\n/**\n * 首页选中的一个待选插件。\n *\n * 带上展示名和图标是为了两件事:后续的配置弹窗与失败提示能一直用业务名(只传技术\n * ID 的话,用户在面板里看到「示例登录」、在弹窗标题里看到 `demo-login`,等于要他认\n * 两遍),以及不用打开面板就能在触发器上看到自己选了什么。\n *\n * 技术 ID 仍是路径、授权、缓存与调用的权威。\n */\nexport interface PluginConnectorSelection {\n name: string\n displayName: string | null\n icon: string | null\n iconSource: PluginConnectorItem[\"iconSource\"]\n}\n\n/** 面板一行 → 待选条目。 */\nexport function selectionFromItem(item: PluginConnectorItem): PluginConnectorSelection {\n return {\n name: item.name,\n displayName: item.display_name ?? null,\n icon: item.icon,\n iconSource: item.iconSource,\n }\n}\n\n/** 触发器上最多直接显示几个插件头像,其余折成数量。 */\nexport const TRIGGER_ICON_LIMIT = 3\n\n/** 触发器上的头像堆叠内容:前三个 + 折起来的数量。 */\nexport interface TriggerSummary {\n /** 前 TRIGGER_ICON_LIMIT 个选中项,**不管有没有图标 token**。 */\n visible: Array<Pick<PluginConnectorSelection, \"name\" | \"displayName\" | \"icon\" | \"iconSource\">>\n /** 超出 TRIGGER_ICON_LIMIT 的数量;0 表示不显示 `+N`。 */\n overflow: number\n /** 已选/已启用的总数,用于无障碍标签与提示。 */\n total: number\n}\n\n/**\n * 把一份插件列表折成触发器上的头像堆叠。\n *\n * 前三项都占位,**不管有没有图标 token**:没有图标的用显示名首字起头的圆形占位,\n * 「选了哪个」照样看得见。早先的实现把无图标的项从图标位里剔掉、还把它们算进\n * `overflow`,于是选中一个没有图标的插件时触发器毫无变化——选择在入口上不可见。\n */\nexport function triggerSummary(\n items: Array<Pick<PluginConnectorSelection, \"name\" | \"displayName\" | \"icon\" | \"iconSource\">>,\n): TriggerSummary {\n const visible = items.slice(0, TRIGGER_ICON_LIMIT)\n return {\n visible,\n overflow: items.length - visible.length,\n total: items.length,\n }\n}\n","import { isLocalConnectorName } from \"@blade-hq/agent-client/internal\"\nimport type { AccountConnector, BladeClient, ConnectorConnectionView } from \"@blade-hq/agent-client/internal\"\nimport { Check, Pencil, Plug, RefreshCw, Trash2, Unplug } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { BrowserConnectionDialog } from \"./BrowserConnectionDialog\"\nimport { SessionPluginConfigForm } from \"./SessionPluginConfigForm\"\n\nconst actionBaseClass = \"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--background))] text-xs font-medium text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))] focus-visible:outline-2 focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50\"\nconst actionClass = `${actionBaseClass} px-3`\nconst iconActionClass = `${actionBaseClass} w-8 p-0`\n\nasync function failureMessage(error: unknown): Promise<string> {\n const response = (error as { response?: Response })?.response\n if (response) {\n try {\n const body = await response.json()\n if (typeof body.detail === \"string\") return body.detail\n if (typeof body.detail?.message === \"string\") return body.detail.message\n } catch { /* Use a stable message without response contents. */ }\n }\n return \"操作未完成,请重试\"\n}\n\nfunction ConnectionDialog({ client, connector, onConnected, onClose }: {\n client: BladeClient\n connector: AccountConnector\n onConnected: () => Promise<void>\n onClose: () => void\n}) {\n const [view, setView] = useState<ConnectorConnectionView | null>(null)\n const [failure, setFailure] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const [connected, setConnected] = useState(false)\n const dialog = useRef<HTMLDialogElement | null>(null)\n const connectionRequest = useRef<AbortController | null>(null)\n useEffect(() => () => connectionRequest.current?.abort(), [])\n useEffect(() => {\n const element = dialog.current\n element?.showModal()\n return () => element?.close()\n }, [])\n useEffect(() => {\n const abort = new AbortController()\n client.connectors.read(connector.name, { signal: abort.signal }).then((value) => {\n if (!abort.signal.aborted) setView(value)\n }).catch(async (error) => {\n const message = await failureMessage(error)\n if (!abort.signal.aborted) setFailure(message)\n })\n return () => abort.abort()\n }, [client, connector.name])\n\n return (\n <dialog\n ref={dialog} aria-label={`连接 ${connector.display_name || connector.name}`}\n className=\"fixed inset-0 m-0 h-full max-h-none w-full max-w-none items-center justify-center border-0 bg-black/40 p-0 open:flex\"\n onCancel={(event) => { event.preventDefault(); if (!submitting) onClose() }}\n >\n <div className=\"max-h-[80vh] w-[min(448px,calc(100%_-_32px))] overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-4 text-[hsl(var(--popover-foreground))] shadow-lg\">\n <div className=\"mb-3 text-sm font-medium\">连接 {connector.display_name || connector.name}</div>\n <p className=\"mb-3 text-xs text-[hsl(var(--muted-foreground))]\">{view?.config.state === \"not_required\" ? \"无需填写账号,验证连接后即可使用。\" : \"填写你的账号信息,验证通过后可在对话中使用。\"}</p>\n {!view ? <div className=\"text-xs\">{failure || \"正在获取认证表单…\"}</div> : !connected ? (\n <SessionPluginConfigForm\n config={view.config} submitting={submitting} errors={[]} failure={failure}\n submitLabel=\"连接并验证\" submittingLabel=\"正在连接…\" onCancel={onClose}\n onSubmit={async (draft) => {\n setSubmitting(true)\n setFailure(null)\n const request = new AbortController()\n connectionRequest.current = request\n try {\n const connected = await client.connectors.connect(connector.name, {\n expected_revision: view.config.revision, set: draft.set, remove: draft.remove,\n }, { signal: request.signal })\n if (request.signal.aborted) return\n setView(connected)\n setConnected(true)\n try { await onConnected() }\n catch { if(!request.signal.aborted)setFailure(\"已连接,但列表或对话状态未能刷新。请返回后重试刷新或启用。\"); return }\n if (!request.signal.aborted) onClose()\n } catch (error) {\n if (request.signal.aborted) return\n setFailure(await failureMessage(error))\n // A failed login may still have saved the configuration. Reload\n // its revision so retry doesn't submit a stale version.\n try { setView(await client.connectors.read(connector.name)) } catch { /* Keep the form. */ }\n } finally { if (!request.signal.aborted) setSubmitting(false) }\n }}\n />\n ) : null}\n {connected ? <output className=\"block text-sm\">{failure || \"账号已连接。\"}</output> : null}\n {!view || connected ? <button type=\"button\" className={`${actionClass} mt-3`} onClick={onClose}>关闭</button> : null}\n </div>\n </dialog>\n )\n}\n\nexport function AccountConnectors({ client, query = \"\", sessionId = null, pending, onUse, onSelectedChange, disabledReason, catalog = false, manage = false, onEdit }: {\n client: BladeClient\n query?: string\n sessionId?: string | null\n pending?: Set<string>\n onUse?: (name: string, label: string, enabled: boolean) => Promise<void>\n onSelectedChange?: (items: AccountConnector[]) => void\n disabledReason?: string | null\n manage?: boolean\n onEdit?: (item: AccountConnector) => void\n catalog?: boolean\n}) {\n const [items, setItems] = useState<AccountConnector[]>([])\n const [editing, setEditing] = useState<AccountConnector | null>(null)\n const [failure, setFailure] = useState<string | null>(null)\n const [loading, setLoading] = useState(true)\n const deleteDialog = useRef<HTMLDialogElement>(null)\n const [deleting, setDeleting] = useState<AccountConnector | null>(null)\n const [busy, setBusy] = useState(false)\n useEffect(() => {\n if (!deleting) return\n const element = deleteDialog.current\n element?.showModal()\n return () => element?.close()\n }, [deleting])\n const lifetime = useRef<AbortController | null>(null)\n const load = useCallback((signal?: AbortSignal) => sessionId\n ? client.connectors.listForSession(sessionId, { signal })\n : client.connectors.list({ signal }), [client, sessionId])\n const reload = useCallback(async () => {\n const scope = lifetime.current\n const result = await load(scope?.signal)\n if (scope === lifetime.current && !scope?.signal.aborted) { setItems(result.connectors); setFailure(null) }\n }, [load])\n useEffect(() => {\n const abort = new AbortController()\n lifetime.current = abort\n setItems([])\n setEditing(null)\n setLoading(true)\n setFailure(null)\n load(abort.signal).then((value) => {\n if (!abort.signal.aborted) setItems(value.connectors)\n }).catch(async (error) => {\n const message = await failureMessage(error)\n if (!abort.signal.aborted) setFailure(message)\n }).finally(() => { if (!abort.signal.aborted) setLoading(false) })\n return () => abort.abort()\n }, [load])\n const visible = useMemo(() => {\n const result=items.map((item)=>({...item,active:sessionId?item.active:Boolean(pending?.has(item.name))}))\n if(!sessionId)for(const name of pending??[])if(isLocalConnectorName(name)&&!result.some((item)=>item.name===name))result.push({name,display_name:name.split(\".\").slice(2).join(\".\"),description:\"连接器已移除或暂不可用,可取消选择后继续。\",source:name.startsWith(\"connector.builtin.\")?\"builtin\":\"personal\",operations:0,available:false,active:true,connection:{status:\"disconnected\",revision:0,account_label:\"\",verified_at:\"\"}})\n return result\n },[items,pending,sessionId])\n const selected = useRef(onSelectedChange)\n selected.current = onSelectedChange\n useEffect(() => { selected.current?.(visible.filter((item) => item.active)) }, [visible])\n const matching = visible.filter((item) => `${item.display_name} ${item.description}`.toLowerCase().includes(query.trim().toLowerCase()))\n\n return (\n <div className={catalog ? \"grid gap-4 sm:grid-cols-2 xl:grid-cols-3\" : undefined}>\n {!catalog ? <div className=\"px-3 pt-1 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">连接器</div> : null}\n {loading ? <p className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">正在读取连接器…</p> : null}\n {!loading && !failure && matching.length === 0 ? <p className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">{query.trim() ? \"没有匹配的连接器\" : \"暂无连接器\"}</p> : null}\n {matching.map((item) => {\n const connected = item.connection.status === \"connected\"\n const label = item.display_name || item.name\n const ConnectIcon = connected ? RefreshCw : Plug\n const connectionClass = `${actionClass} ${!connected ? \"border-transparent bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] hover:bg-[hsl(var(--primary)/0.9)]\" : \"\"}`\n const connectAction = (\n <button type=\"button\" disabled={busy || item.available === false} className={connectionClass} onClick={() => { setFailure(null); setEditing(item) }}><ConnectIcon size={14} aria-hidden=\"true\" />{connected ? \"重新连接\" : \"连接\"}</button>\n )\n const useAction = onUse && (item.active || connected && item.operations > 0) ? (\n <button type=\"button\" disabled={busy || Boolean(disabledReason)} title={disabledReason ?? undefined} className={actionClass} onClick={async () => {\n const scope = lifetime.current\n setBusy(true)\n setFailure(null)\n try {\n await onUse(item.name, label, !item.active)\n if (sessionId) await reload()\n } catch (error) {\n const message = await failureMessage(error)\n if (scope === lifetime.current && !scope?.signal.aborted) setFailure(message)\n }\n finally { if (scope === lifetime.current && !scope?.signal.aborted) setBusy(false) }\n }}>{item.active ? <Check size={14} aria-hidden=\"true\" /> : null}{item.active ? \"已启用\" : \"使用\"}</button>\n ) : null\n return (\n <div key={item.name} className={catalog ? \"flex flex-col rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-5\" : \"px-3 py-1.5\"}>\n <div className={`flex items-center gap-2 ${catalog ? \"text-sm\" : \"text-[11px]\"}`}>\n <span className=\"min-w-0 flex-1 truncate font-medium\" title={label}>{label}</span>\n <span className=\"shrink-0 rounded-md bg-[hsl(var(--muted))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">{item.source === \"builtin\" ? \"内置\" : \"我创建的\"}</span>\n {!catalog ? <>{connectAction}{useAction}</> : null}\n </div>\n {catalog ? <p className=\"mt-2 flex-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]\">{item.description}</p> : null}\n <div className=\"mt-3 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]\">\n <span aria-hidden=\"true\" className={`size-1.5 shrink-0 rounded-full ${connected ? \"bg-emerald-500\" : \"bg-[hsl(var(--muted-foreground)/0.4)]\"}`} />\n {connected ? `已连接${item.connection.account_label ? ` · ${item.connection.account_label}` : \"\"}${item.operations === 0 ? \",尚未配置业务操作\" : \"\"}` : item.connection.status === \"auth_required\" ? \"需要重新认证\" : \"未连接\"}\n </div>\n {catalog ? <div className=\"mt-4 flex items-center gap-2 border-t border-[hsl(var(--border))] pt-4\">\n {connectAction}{useAction}\n {manage ? <div className=\"ml-auto flex items-center gap-1.5\">\n {<button type=\"button\" disabled={busy} aria-label=\"断开\" title=\"断开连接\" className={iconActionClass} onClick={async () => {\n setBusy(true)\n try { await client.connectors.disconnect(item.name); await reload() }\n catch (error) { setFailure(await failureMessage(error)) }\n finally { setBusy(false) }\n }}><Unplug size={15} aria-hidden=\"true\" /></button>}\n {item.source === \"personal\" ? <>\n <button type=\"button\" disabled={busy} aria-label=\"编辑\" title=\"编辑连接器\" className={iconActionClass} onClick={() => onEdit?.(item)}><Pencil size={15} aria-hidden=\"true\" /></button>\n <button type=\"button\" disabled={busy} aria-label=\"删除\" title=\"删除连接器\" className={`${iconActionClass} text-[hsl(var(--destructive))] hover:border-[hsl(var(--destructive)/0.3)] hover:bg-[hsl(var(--destructive)/0.08)]`} onClick={() => setDeleting(item)}><Trash2 size={15} aria-hidden=\"true\" /></button>\n </> : null}\n </div> : null}\n </div> : null}\n </div>\n )\n })}\n {deleting ? <dialog ref={deleteDialog} onCancel={(event) => { event.preventDefault(); if (!busy) setDeleting(null) }} aria-label=\"删除连接器\" className=\"fixed inset-0 z-50 m-auto w-[min(420px,calc(100%_-_32px))] rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-5 text-[hsl(var(--popover-foreground))] shadow-xl\">\n <p className=\"text-sm\">删除「{deleting.display_name || deleting.name}」及其连接信息?需要使用时可以重新创建。</p>\n <div className=\"mt-4 flex justify-end gap-3\">\n <button type=\"button\" disabled={busy} className={actionClass} onClick={() => setDeleting(null)}>取消</button>\n <button type=\"button\" disabled={busy} className={`${actionClass} border-transparent bg-[hsl(var(--destructive))] text-white hover:bg-[hsl(var(--destructive)/0.9)]`} onClick={async () => {\n setBusy(true)\n try { await client.connectors.delete(deleting.name); setDeleting(null); await reload() }\n catch (error) { setFailure(await failureMessage(error)); setDeleting(null) }\n finally { setBusy(false) }\n }}>{busy ? \"正在删除…\" : \"确认删除\"}</button>\n </div>\n </dialog> : null}\n {failure ? <div role=\"alert\" className=\"px-3 py-1 text-xs text-[hsl(var(--destructive))]\">{failure}<button type=\"button\" className={`${actionClass} ml-2`} onClick={() => { void reload().catch(() => setFailure(\"读取失败,请重试\")) }}>重试</button></div> : null}\n {editing?.authorization?.type === \"browser\" ? <BrowserConnectionDialog key={editing.name} client={client} name={editing.name} label={editing.display_name || editing.name} onClose={() => {\n setEditing(null)\n void reload().catch(() => setFailure(\"读取失败,请重试\"))\n }} /> : editing ? <ConnectionDialog key={editing.name} client={client} connector={editing} onClose={() => setEditing(null)} onConnected={async () => {\n const scope = lifetime.current\n await reload()\n if (scope !== lifetime.current || scope?.signal.aborted) return\n if (onUse && editing.operations > 0 && !disabledReason) {\n await onUse(editing.name, editing.display_name || editing.name, true)\n if (sessionId) await reload()\n }\n }} /> : null}\n </div>\n )\n}\n","import { isLocalConnectorName } from \"@blade-hq/agent-client/internal\"\nimport type { AccountConnector, BladeClient, PluginCatalogEntry, SessionPluginActivation } from \"@blade-hq/agent-client/internal\"\nimport { Loader2, Search } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\"\nimport { PluginConnectorList } from \"./PluginConnectorList\"\nimport { useSessionPluginActivation } from \"./use-session-plugin-activation\"\nimport { catalogToConnectorItems, filterConnectorItems, type PluginConnectorItem } from \"./plugin-connector\"\nimport { selectionFromItem, type PluginConnectorSelection } from \"./connector-panel-types\"\nimport { AccountConnectors } from \"./AccountConnectors\"\n\nexport interface ConnectorPanelProps {\n client: BladeClient\n /**\n * `null` 表示首页:插件开关只记下本次输入的待选,不激活任何东西、不建会话、\n * 不启动沙盒或 MCP。待选项随首条消息一起交给宿主处理。\n */\n sessionId: string | null\n /** 首页待选插件;`sessionId` 为 null 时使用。 */\n pendingPlugins?: PluginConnectorSelection[]\n onPendingPluginsChange?: (next: PluginConnectorSelection[]) => void\n /** 首页候选开关不可用时的说明(例如软件工厂模式会先建项目再启动)。 */\n pendingDisabledReason?: string | null\n /** 会话内插件启用/停用结果;宿主据此刷新技能统计。 */\n onPluginsChanged?: (plugin: SessionPluginActivation) => void\n /**\n * 当前已选(首页待选 / 会话内已启用)的插件,按行原样报给宿主。\n *\n * 触发器要在不打开面板时就能显示「选了哪几个、几个」,它自己拿不到这份状态,\n * 所以由面板单向汇报;面板未挂载时宿主保留上一次的结果。\n */\n onSelectedChange?: (items: PluginConnectorItem[]) => void\n /** 宿主注入:电脑分区。参数是搜索词,宿主自己决定怎么过滤。 */\n renderComputerSection?: (query: string) => ReactNode\n /** 宿主注入:手机分区,渲染在电脑下面。参数是搜索词。 */\n renderPhoneSection?: (query: string) => ReactNode\n /** 宿主注入:外部账号分区(飞书 / GitHub 等固定连接入口)。 */\n renderExternalAccounts?: (query: string) => ReactNode\n /** 宿主注入:底部操作区;不注入就不渲染这一块。 */\n renderFooterActions?: () => ReactNode\n className?: string\n}\n\nfunction PanelDivider() {\n return <div className=\"my-1 border-[hsl(var(--border))] border-t\" />\n}\n\nfunction PanelTitle({ children }: { children: ReactNode }) {\n return (\n <div className=\"px-3 pt-1 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">\n {children}\n </div>\n )\n}\n\n/**\n * 统一连接器面板:顶部搜索、按「电脑 / 插件 / 外部账号」分区、底部添加与管理。\n *\n * 插件分区是这一层唯一的共享实现:首页和会话用同一个列表、同一套启用判定,\n * 判定不各写一份。电脑与外部账号由宿主注入——那些入口需要宿主的路由与 CLI\n * 引导,SDK 不硬编码内部路径,也不替第三方决定跳到哪里。\n */\nexport function ConnectorPanel({\n client,\n sessionId,\n pendingPlugins,\n onPendingPluginsChange,\n pendingDisabledReason,\n onPluginsChanged,\n onSelectedChange,\n renderComputerSection,\n renderPhoneSection,\n renderExternalAccounts,\n renderFooterActions,\n className,\n}: ConnectorPanelProps) {\n const [query, setQuery] = useState(\"\")\n const [selectedConnectors, setSelectedConnectors] = useState<AccountConnector[]>([])\n const [pendingCatalog, setPendingCatalog] = useState<PluginCatalogEntry[] | null>(null)\n const [pendingLoading, setPendingLoading] = useState(false)\n const [pendingError, setPendingError] = useState(false)\n\n const activation = useSessionPluginActivation({\n client,\n sessionId: sessionId ?? \"\",\n onChange: onPluginsChanged,\n })\n const { reload, items: sessionItems } = activation\n\n useEffect(() => {\n if (sessionId) reload()\n }, [reload, sessionId])\n\n const loadPendingCatalog = useCallback(async () => {\n setPendingLoading(true)\n setPendingError(false)\n try {\n const { plugins } = await client.plugins.catalog()\n setPendingCatalog(plugins)\n } catch {\n setPendingError(true)\n } finally {\n setPendingLoading(false)\n }\n }, [client])\n\n useEffect(() => {\n if (sessionId) return\n void loadPendingCatalog()\n }, [loadPendingCatalog, sessionId])\n\n const selected = useMemo(\n () => new Set((pendingPlugins ?? []).map((item) => item.name)),\n [pendingPlugins],\n )\n const items = useMemo(() => {\n if (sessionId) return sessionItems\n return catalogToConnectorItems(pendingCatalog ?? []).map((item) => ({\n ...item,\n active: selected.has(item.name),\n }))\n }, [pendingCatalog, selected, sessionId, sessionItems])\n const visibleItems = useMemo(\n () => (sessionId\n ? filterConnectorItems(items, query)\n : filterConnectorItems(items, query).map((item) => ({ ...item, config: undefined }))),\n [items, query, sessionId],\n )\n\n const togglePending = useCallback((item: PluginConnectorItem, next: boolean) => {\n const kept = (pendingPlugins ?? []).filter((entry) => entry.name !== item.name)\n onPendingPluginsChange?.(next ? [...kept, selectionFromItem(item)] : kept)\n }, [onPendingPluginsChange, pendingPlugins])\n\n const toggle = useCallback((item: PluginConnectorItem, next: boolean) => {\n if (sessionId) activation.toggle(item, next)\n else togglePending(item, next)\n }, [activation, sessionId, togglePending])\n\n const selectedItems = useMemo(\n () => [\n ...items.filter((item) => item.active && !isLocalConnectorName(item.name)),\n ...selectedConnectors.map((item) => ({\n name: item.name, display_name: item.display_name, icon: null,\n iconSource: \"account\" as const, installed: true, active: true,\n status: \"valid\", projected: false, connector: true,\n })),\n ],\n [items, selectedConnectors],\n )\n const onSelectedChangeRef = useRef(onSelectedChange)\n onSelectedChangeRef.current = onSelectedChange\n const latestSelected = useRef(selectedItems)\n latestSelected.current = selectedItems\n const reportSelected = useCallback(() => {\n onSelectedChangeRef.current?.(latestSelected.current)\n }, [])\n const selectedNames = selectedItems.map((item) => item.name).join(\"\\u0000\")\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: selectedNames 是选中集合的稳定指纹\n useEffect(reportSelected, [reportSelected, selectedNames])\n\n const failed = sessionId ? activation.listError : pendingError\n\n return (\n <div className={className}>\n <div className=\"flex items-center gap-2 border-[hsl(var(--border))] border-b px-3 py-2\">\n <Search size={12} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" aria-hidden=\"true\" />\n <input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"搜索连接器\"\n aria-label=\"搜索连接器\"\n className=\"min-w-0 flex-1 bg-transparent text-[11px] outline-none placeholder:text-[hsl(var(--muted-foreground))]\"\n />\n </div>\n\n {renderComputerSection ? (\n <>\n <PanelTitle>电脑</PanelTitle>\n {renderComputerSection(query)}\n </>\n ) : null}\n\n {renderPhoneSection ? renderPhoneSection(query) : null}\n\n <PanelDivider />\n <AccountConnectors\n client={client} query={query} sessionId={sessionId} pending={selected}\n onSelectedChange={setSelectedConnectors} disabledReason={pendingDisabledReason}\n onUse={async (name, label, enabled) => {\n if (sessionId) {\n const result = await client.sessions.setSessionPluginActivation(sessionId, name, enabled)\n onPluginsChanged?.(result.plugin)\n } else {\n const kept = (pendingPlugins ?? []).filter((item) => item.name !== name)\n onPendingPluginsChange?.(enabled ? [...kept, { name, displayName: label, icon: null, iconSource: \"account\" }] : kept)\n }\n }}\n />\n <PanelDivider />\n <PanelTitle>插件</PanelTitle>\n {!sessionId ? (\n <div className=\"px-3 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">\n 先选中,发送这条消息时会一并启用\n </div>\n ) : null}\n {(sessionId ? activation.loading : pendingLoading) && visibleItems.length === 0 ? (\n <div className=\"px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]\">\n <Loader2 size={12} className=\"mr-1 inline animate-spin\" />\n 正在获取插件…\n </div>\n ) : null}\n {failed ? (\n <button\n type=\"button\"\n onClick={() => (sessionId ? reload() : void loadPendingCatalog())}\n className=\"px-3 py-1.5 text-left text-[11px] text-[hsl(var(--muted-foreground))] underline\"\n >\n 插件列表暂不可用,点击重试\n </button>\n ) : null}\n <PluginConnectorList\n client={client}\n sessionId={sessionId}\n items={visibleItems.filter((item) => !isLocalConnectorName(item.name))}\n inFlight={activation.inFlight}\n busy={sessionId ? activation.busy : pendingLoading}\n mutationError={sessionId ? activation.mutationError : false}\n onToggle={toggle}\n onRetry={activation.retry}\n onEditConfig={activation.editConfig}\n configuring={sessionId ? activation.configuring : null}\n onConfigSaved={activation.onConfigSaved}\n onConfigClose={activation.onConfigClose}\n disabledReason={sessionId ? null : pendingDisabledReason}\n unavailableText={\n failed\n ? null\n : query.trim()\n ? \"没有匹配的插件\"\n : null\n }\n emptyText={sessionId ? \"尚未安装插件\" : \"尚未安装插件,去应用市场添加一个\"}\n draft={!sessionId}\n />\n\n {renderExternalAccounts ? (\n <>\n <PanelDivider />\n <PanelTitle>外部账号</PanelTitle>\n {renderExternalAccounts(query)}\n </>\n ) : null}\n\n {renderFooterActions ? (\n <>\n <PanelDivider />\n {renderFooterActions()}\n </>\n ) : null}\n </div>\n )\n}\n","import type { BladeClient } from \"@blade-hq/agent-client\"\nimport { SessionPluginIcon } from \"./SessionPluginIcon\"\nimport type { TriggerSummary } from \"./connector-panel-types\"\n\nexport interface PluginTriggerStackProps {\n client: BladeClient\n /** 会话内图标走会话接口;首页待选传 `null`(走账号级目录图标)。 */\n sessionId: string | null\n /** 折叠结果,来自 `triggerSummary`——折叠规则只有那一处。 */\n summary: TriggerSummary\n className?: string\n}\n\nconst AVATAR_SIZE = 20\n\nfunction hueOf(name: string): number {\n let hash = 0\n for (const char of name) hash = (hash * 31 + char.codePointAt(0)!) % 1000003\n return hash % 360\n}\n\n/**\n * 首字占位的身份色板。\n *\n * 不是自己调的色:直接取 Tailwind 默认调色板里相隔开的 8 个色相(Slack 那类头像\n * 色板也是这个量级、这个思路),深浅主题各一套。用 Tailwind 默认色而不是新造\n * token,是因为仓库里本来就在用(status、图表那批 bg-red-500 / text-sky-400)。\n *\n * 字色取 800 档而不是 700:100 底 + 700 字在浅色下只有 4.5–5.2:1,而这个字只有\n * 11px,够不上「小字看不清」这条线;100 + 800 各色相都在 6.4:1 以上。\n */\nconst AVATAR_PALETTE = [\n \"bg-violet-100 text-violet-800 dark:bg-violet-500/25 dark:text-violet-200\",\n \"bg-sky-100 text-sky-800 dark:bg-sky-500/25 dark:text-sky-200\",\n \"bg-emerald-100 text-emerald-800 dark:bg-emerald-500/25 dark:text-emerald-200\",\n \"bg-amber-100 text-amber-800 dark:bg-amber-500/25 dark:text-amber-200\",\n \"bg-rose-100 text-rose-800 dark:bg-rose-500/25 dark:text-rose-200\",\n \"bg-indigo-100 text-indigo-800 dark:bg-indigo-500/25 dark:text-indigo-200\",\n \"bg-teal-100 text-teal-800 dark:bg-teal-500/25 dark:text-teal-200\",\n \"bg-fuchsia-100 text-fuchsia-800 dark:bg-fuchsia-500/25 dark:text-fuchsia-200\",\n]\n\n/**\n * 触发器上的插件头像堆叠:前三枚圆形头像 + 其余折成 `+N`。\n *\n * 没有图标 token 的插件也用显示名首字占一枚圆——它和别的插件长得不一样,\n * 「我选过它」就看得见;早先把这类项直接剔掉,选中后入口毫无变化。\n *\n * 圆环色取 `--background`(盖住被压住的那枚),与整站头像堆叠同一约定,见\n * `apps/web/src/components/agent-board/ProjectMembers.tsx`:容器没有自己的底色时,\n * 环就等于容器露出来的那层底。图标裁成圆形:插件 logo 多是方的,套在圆按钮里\n * 「方套圆」才是那个视觉冲突的来源。\n */\nexport function PluginTriggerStack({ client, sessionId, summary, className }: PluginTriggerStackProps) {\n if (summary.total === 0) return null\n const ring = \"ring-2 ring-[hsl(var(--background))]\"\n return (\n <span className={`flex items-center -space-x-1 ${className ?? \"\"}`}>\n {summary.visible.map((item) => {\n const label = item.displayName?.trim() || item.name\n const tone = AVATAR_PALETTE[hueOf(item.name) % AVATAR_PALETTE.length]\n return item.icon ? (\n <SessionPluginIcon\n key={item.name}\n client={client}\n sessionId={item.iconSource === \"account\" ? null : sessionId}\n plugin={item}\n size={AVATAR_SIZE}\n shape=\"circle\"\n className={ring}\n />\n ) : (\n <span\n key={item.name}\n title={label}\n className={`flex shrink-0 items-center justify-center rounded-full font-semibold text-[11px] ${tone} ${ring}`}\n style={{ width: AVATAR_SIZE, height: AVATAR_SIZE }}\n >\n {Array.from(label.trim())[0]?.toUpperCase() ?? \"?\"}\n </span>\n )\n })}\n {summary.overflow > 0 ? (\n <span\n className={`flex shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] font-medium text-[hsl(var(--muted-foreground))] text-[10px] ${ring}`}\n style={{ width: AVATAR_SIZE, height: AVATAR_SIZE }}\n >\n +{summary.overflow}\n </span>\n ) : null}\n </span>\n )\n}\n"],"mappings":"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","names":["connected","isLocalConnectorName","useCallback","useEffect","useMemo","useRef","useState","Fragment","jsx","jsxs","useState","useEffect","useCallback","useMemo","isLocalConnectorName","useRef","jsx","jsxs"]}