@blade-hq/agent-react 2610.0.1 → 2612.0.0-beta.1
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.
- package/README.md +88 -258
- package/dist/chat/AgentLoopBlock.d.ts +14 -0
- package/dist/{components → chat}/AskUserQuestionBlock.d.ts +3 -7
- package/dist/chat/AssistantTurnBlock.d.ts +50 -0
- package/dist/chat/AttachmentPreviewDialog.d.ts +26 -0
- package/dist/chat/ChatPanel.d.ts +64 -0
- package/dist/chat/CompactionCard.d.ts +6 -0
- package/dist/chat/ConnectionBanner.d.ts +10 -0
- package/dist/chat/CurrentPlanPanel.d.ts +20 -0
- package/dist/chat/FileDeliveryCards.d.ts +26 -0
- package/dist/chat/FinalArtifactCards.d.ts +8 -0
- package/dist/chat/ImageLightbox.d.ts +11 -0
- package/dist/chat/LightComposer.d.ts +7 -0
- package/dist/chat/LiteMessageList.d.ts +82 -0
- package/dist/chat/MessageActions.d.ts +6 -0
- package/dist/chat/MessageContextPills.d.ts +6 -0
- package/dist/chat/MessageFileAttachmentList.d.ts +13 -0
- package/dist/chat/MessageList.d.ts +54 -0
- package/dist/chat/PostChatFollowupBlock.d.ts +11 -0
- package/dist/{components → chat}/RenderErrorBoundary.d.ts +0 -1
- package/dist/chat/ResultFeedback.d.ts +11 -0
- package/dist/chat/SessionReplayBar.d.ts +12 -0
- package/dist/chat/TextAttachmentPills.d.ts +10 -0
- package/dist/chat/ToolCallBlock.d.ts +48 -0
- package/dist/chat/ToolUiCard.d.ts +6 -0
- package/dist/chat/TurnNavRail.d.ts +17 -0
- package/dist/chat/UserMessageBubble.d.ts +20 -0
- package/dist/chat/WorkflowRunBlock.d.ts +13 -0
- package/dist/chat/ai-elements/reasoning.d.ts +32 -0
- package/dist/chat/ai-elements/shimmer.d.ts +15 -0
- package/dist/chat/assistant-turn-questions.d.ts +14 -0
- package/dist/chat/card/CardContext.d.ts +7 -0
- package/dist/chat/chat-theme.d.ts +19 -0
- package/dist/chat/customization.d.ts +214 -0
- package/dist/chat/display-utils.d.ts +48 -0
- package/dist/{components/PostChatFollowupBlock.d.ts → chat/followup-interaction.d.ts} +5 -17
- package/dist/chat/index.d.ts +100 -0
- package/dist/chat/lib/citations.d.ts +30 -0
- package/dist/chat/lib/code-language.d.ts +5 -0
- package/dist/chat/lib/loopback.d.ts +8 -0
- package/dist/chat/lib/markdown-asset-url.d.ts +5 -0
- package/dist/chat/lib/preview-dispatch.d.ts +24 -0
- package/dist/chat/lib/skill-name.d.ts +9 -0
- package/dist/chat/lib/skill-visibility.d.ts +8 -0
- package/dist/chat/lib/ui-meta.d.ts +5 -0
- package/dist/chat/lib/use-async-value.d.ts +8 -0
- package/dist/chat/markdown/ExternalAnchor.d.ts +9 -0
- package/dist/chat/markdown/MarkdownContent.d.ts +40 -0
- package/dist/chat/markdown/text.d.ts +11 -0
- package/dist/chat/message-list-blocks.d.ts +92 -0
- package/dist/chat/plan/PlanSummaryCard.d.ts +10 -0
- package/dist/chat/plan/extract-plan-messages.d.ts +4 -0
- package/dist/chat/plan/parse-plan-messages.d.ts +10 -0
- package/dist/chat/plan/parse-plan-tree.d.ts +16 -0
- package/dist/chat/plan/types.d.ts +56 -0
- package/dist/chat/reasoning-visibility.d.ts +2 -0
- package/dist/chat/runtime/actions.d.ts +22 -0
- package/dist/chat/runtime/background-task-dismissals.d.ts +10 -0
- package/dist/chat/runtime/composer-channels.d.ts +46 -0
- package/dist/chat/runtime/environment.d.ts +152 -0
- package/dist/chat/runtime/input-cache-reset.d.ts +8 -0
- package/dist/chat/runtime/input-services.d.ts +111 -0
- package/dist/chat/runtime/session-source.d.ts +49 -0
- package/dist/chat/runtime/use-chat-actions.d.ts +19 -0
- package/dist/chat/runtime/use-session-replay.d.ts +16 -0
- package/dist/chat/scroll-anchor.d.ts +46 -0
- package/dist/chat/tool-renderers/BashRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/FileEditRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/FileReadRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/KbSearchRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/SearchRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/SubmitResultRenderer.d.ts +2 -0
- package/dist/chat/tool-renderers/kb-search-result.d.ts +19 -0
- package/dist/chat/tool-renderers/registry.d.ts +5 -0
- package/dist/chat/tool-renderers/shared.d.ts +30 -0
- package/dist/chat/tool-renderers/write-preview-scroll.d.ts +5 -0
- package/dist/chat-OCLOVB3H.css +175 -0
- package/dist/chat.css +175 -0
- package/dist/chunk-6ZDOQEWK.js +49365 -0
- package/dist/chunk-6ZDOQEWK.js.map +1 -0
- package/dist/chunk-FQQJP2GJ.js +26986 -0
- package/dist/chunk-FQQJP2GJ.js.map +1 -0
- package/dist/{chunk-G3PMV62Z.js → chunk-PR4QN5HX.js} +9 -2
- package/dist/chunk-WCMGQJLE.js +258 -0
- package/dist/chunk-WCMGQJLE.js.map +1 -0
- package/dist/components/AgentChat.d.ts +3 -3
- package/dist/components/ChatView.d.ts +2 -2
- package/dist/components/ConnectorPanel.d.ts +1 -1
- package/dist/components/ContextCard.d.ts +1 -1
- package/dist/components/LlmChat.d.ts +1 -1
- package/dist/components/McpAppCard.d.ts +1 -1
- package/dist/components/PlanUpdateBlock.d.ts +0 -8
- package/dist/components/PluginConnectorList.d.ts +1 -1
- package/dist/components/ReplayBar.d.ts +1 -1
- package/dist/components/SessionPluginConfigDialog.d.ts +1 -1
- package/dist/components/SessionPluginConfigForm.d.ts +1 -1
- package/dist/components/SessionPluginIcon.d.ts +1 -1
- package/dist/components/SessionPluginSelector.d.ts +1 -1
- package/dist/components/SessionQueuePanel.d.ts +1 -1
- package/dist/components/ToolUiCardView.d.ts +1 -1
- package/dist/components/plugin-config-draft.d.ts +1 -1
- package/dist/components/plugin-config-schema.d.ts +1 -1
- package/dist/components/plugin-connector.d.ts +1 -1
- package/dist/components/use-session-plugin-activation.d.ts +1 -1
- package/dist/context.d.ts +11 -2
- package/dist/embed/blade-chat-element.d.ts +14 -1
- package/dist/embed/entry.d.ts +8 -78
- package/dist/hooks/use-replay.d.ts +1 -1
- package/dist/hooks/use-turn-navigation.d.ts +1 -1
- package/dist/host.d.ts +54 -0
- package/dist/index.d.ts +11 -69
- package/dist/index.js +12 -63525
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +60 -0
- package/dist/internal.js +656 -0
- package/dist/internal.js.map +1 -0
- package/dist/lib/mount-renderers.d.ts +25 -0
- package/dist/lib/use-effect-event.d.ts +3 -0
- package/dist/rich-input/BackgroundTasksPill.d.ts +3 -0
- package/dist/rich-input/ChatInput.d.ts +59 -0
- package/dist/rich-input/ComposerAttachmentViewport.d.ts +3 -0
- package/dist/rich-input/ConnectButton.d.ts +24 -0
- package/dist/rich-input/FileCompletionMenu.d.ts +44 -0
- package/dist/rich-input/FileSizeLimitDialog.d.ts +9 -0
- package/dist/rich-input/ModelSelector.d.ts +10 -0
- package/dist/rich-input/PlanningToggle.d.ts +7 -0
- package/dist/rich-input/ProgressCircle.d.ts +12 -0
- package/dist/rich-input/ReasoningModeSelect.d.ts +9 -0
- package/dist/rich-input/SkillCompletionMenu.d.ts +9 -0
- package/dist/rich-input/SkillStatusBar.d.ts +15 -0
- package/dist/rich-input/extensions/file-mention.d.ts +12 -0
- package/dist/rich-input/extensions/kb-mention.d.ts +18 -0
- package/dist/rich-input/extensions/skill-mention.d.ts +48 -0
- package/dist/rich-input/extensions/workflow-mention.d.ts +10 -0
- package/dist/rich-input/index.d.ts +48 -0
- package/dist/rich-input/input-keyboard.d.ts +13 -0
- package/dist/rich-input/lib/attachment-upload.d.ts +10 -0
- package/dist/rich-input/lib/background-tasks-view.d.ts +31 -0
- package/dist/rich-input/lib/client-query.d.ts +32 -0
- package/dist/rich-input/lib/composer-content.d.ts +42 -0
- package/dist/rich-input/lib/image-input-availability.d.ts +3 -0
- package/dist/rich-input/lib/kb-suggestions.d.ts +37 -0
- package/dist/rich-input/lib/reasoning-levels.d.ts +1 -0
- package/dist/rich-input/lib/session-data.d.ts +20 -0
- package/dist/rich-input/lib/skill-suggestions.d.ts +19 -0
- package/dist/rich-input/lib/token-estimate.d.ts +2 -0
- package/dist/rich-input/lib/token-pressure.d.ts +8 -0
- package/dist/rich-input/lib/upload-results.d.ts +8 -0
- package/dist/rich-input/lib/user-home.d.ts +33 -0
- package/dist/rich-input/model/model-data.d.ts +6 -0
- package/dist/rich-input/model/resolve-model.d.ts +59 -0
- package/dist/rich-input/model/use-composer-model.d.ts +24 -0
- package/dist/rich-input/services.d.ts +22 -0
- package/dist/rich-input/use-dismiss-skill-suggestions-on-mode-change.d.ts +3 -0
- package/dist/rich-input/use-input-history.d.ts +14 -0
- package/dist/rich-input/voice/VoiceWaveform.d.ts +10 -0
- package/dist/rich-input/voice/use-tiptap-voice-input.d.ts +47 -0
- package/dist/rich-input/voice/use-voice-input.d.ts +2 -0
- package/dist/rich-input/voice/voice-input-support.d.ts +5 -0
- package/dist/rich-input.js +29853 -0
- package/dist/rich-input.js.map +1 -0
- package/dist/style.css +30 -64
- package/dist/style.full.css +210 -65
- package/dist/{webapi-W3IB5DO4.js → webapi-E7K2CNM7.js} +2 -2
- package/package.json +12 -3
- package/public-api.md +206 -3603
- package/dist/components/AgentLoopBlock.d.ts +0 -8
- package/dist/components/AgentTaskCard.d.ts +0 -12
- package/dist/components/AssistantTurnBlock.d.ts +0 -36
- package/dist/components/ChatSurface.d.ts +0 -199
- package/dist/components/ConnectionBanner.d.ts +0 -8
- package/dist/components/MarkdownContent.d.ts +0 -30
- package/dist/components/MessageList.d.ts +0 -62
- package/dist/components/Shimmer.d.ts +0 -7
- package/dist/components/ToolCallBlock.d.ts +0 -41
- package/dist/components/TurnNavRail.d.ts +0 -23
- package/dist/components/UserMessageBubble.d.ts +0 -25
- package/dist/components/display-utils.d.ts +0 -4
- /package/dist/{chunk-G3PMV62Z.js.map → chunk-PR4QN5HX.js.map} +0 -0
- /package/dist/{webapi-W3IB5DO4.js.map → webapi-E7K2CNM7.js.map} +0 -0
|
@@ -4,7 +4,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
8
14
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
15
|
};
|
|
10
16
|
var __export = (target, all) => {
|
|
@@ -29,8 +35,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
35
|
));
|
|
30
36
|
|
|
31
37
|
export {
|
|
38
|
+
__require,
|
|
32
39
|
__commonJS,
|
|
33
40
|
__export,
|
|
34
41
|
__toESM
|
|
35
42
|
};
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
43
|
+
//# sourceMappingURL=chunk-PR4QN5HX.js.map
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LoaderCircle,
|
|
3
|
+
PluginConnectorList,
|
|
4
|
+
Search,
|
|
5
|
+
SessionPluginIcon,
|
|
6
|
+
catalogToConnectorItems,
|
|
7
|
+
filterConnectorItems,
|
|
8
|
+
useSessionPluginActivation
|
|
9
|
+
} from "./chunk-FQQJP2GJ.js";
|
|
10
|
+
|
|
11
|
+
// src/components/connector-panel-types.ts
|
|
12
|
+
function selectionFromItem(item) {
|
|
13
|
+
return {
|
|
14
|
+
name: item.name,
|
|
15
|
+
displayName: item.display_name ?? null,
|
|
16
|
+
icon: item.icon,
|
|
17
|
+
iconSource: item.iconSource
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
var TRIGGER_ICON_LIMIT = 3;
|
|
21
|
+
function triggerSummary(items) {
|
|
22
|
+
const visible = items.slice(0, TRIGGER_ICON_LIMIT);
|
|
23
|
+
return {
|
|
24
|
+
visible,
|
|
25
|
+
overflow: items.length - visible.length,
|
|
26
|
+
total: items.length
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/components/ConnectorPanel.tsx
|
|
31
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
32
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
33
|
+
function PanelDivider() {
|
|
34
|
+
return /* @__PURE__ */ jsx("div", { className: "my-1 border-[hsl(var(--border))] border-t" });
|
|
35
|
+
}
|
|
36
|
+
function PanelTitle({ children }) {
|
|
37
|
+
return /* @__PURE__ */ jsx("div", { className: "px-3 pt-1 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children });
|
|
38
|
+
}
|
|
39
|
+
function ConnectorPanel({
|
|
40
|
+
client,
|
|
41
|
+
sessionId,
|
|
42
|
+
pendingPlugins,
|
|
43
|
+
onPendingPluginsChange,
|
|
44
|
+
pendingDisabledReason,
|
|
45
|
+
onPluginsChanged,
|
|
46
|
+
onSelectedChange,
|
|
47
|
+
renderComputerSection,
|
|
48
|
+
renderExternalAccounts,
|
|
49
|
+
renderFooterActions,
|
|
50
|
+
className
|
|
51
|
+
}) {
|
|
52
|
+
const [query, setQuery] = useState("");
|
|
53
|
+
const [pendingCatalog, setPendingCatalog] = useState(null);
|
|
54
|
+
const [pendingLoading, setPendingLoading] = useState(false);
|
|
55
|
+
const [pendingError, setPendingError] = useState(false);
|
|
56
|
+
const activation = useSessionPluginActivation({
|
|
57
|
+
client,
|
|
58
|
+
// 首页不会走这个分支:待选在下面自己处理开关,不碰会话接口。
|
|
59
|
+
sessionId: sessionId ?? "",
|
|
60
|
+
onChange: onPluginsChanged
|
|
61
|
+
});
|
|
62
|
+
const { reload, items: sessionItems } = activation;
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (sessionId) reload();
|
|
65
|
+
}, [reload, sessionId]);
|
|
66
|
+
const loadPendingCatalog = useCallback(async () => {
|
|
67
|
+
setPendingLoading(true);
|
|
68
|
+
setPendingError(false);
|
|
69
|
+
try {
|
|
70
|
+
const { plugins } = await client.plugins.catalog();
|
|
71
|
+
setPendingCatalog(plugins);
|
|
72
|
+
} catch {
|
|
73
|
+
setPendingError(true);
|
|
74
|
+
} finally {
|
|
75
|
+
setPendingLoading(false);
|
|
76
|
+
}
|
|
77
|
+
}, [client]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (sessionId) return;
|
|
80
|
+
void loadPendingCatalog();
|
|
81
|
+
}, [loadPendingCatalog, sessionId]);
|
|
82
|
+
const selected = useMemo(
|
|
83
|
+
() => new Set((pendingPlugins ?? []).map((item) => item.name)),
|
|
84
|
+
[pendingPlugins]
|
|
85
|
+
);
|
|
86
|
+
const items = useMemo(() => {
|
|
87
|
+
if (sessionId) return sessionItems;
|
|
88
|
+
return catalogToConnectorItems(pendingCatalog ?? []).map((item) => ({
|
|
89
|
+
...item,
|
|
90
|
+
active: selected.has(item.name)
|
|
91
|
+
}));
|
|
92
|
+
}, [pendingCatalog, selected, sessionId, sessionItems]);
|
|
93
|
+
const visibleItems = useMemo(
|
|
94
|
+
() => sessionId ? filterConnectorItems(items, query) : filterConnectorItems(items, query).map((item) => ({ ...item, config: void 0 })),
|
|
95
|
+
[items, query, sessionId]
|
|
96
|
+
);
|
|
97
|
+
const togglePending = useCallback((item, next) => {
|
|
98
|
+
const kept = (pendingPlugins ?? []).filter((entry) => entry.name !== item.name);
|
|
99
|
+
onPendingPluginsChange?.(next ? [...kept, selectionFromItem(item)] : kept);
|
|
100
|
+
}, [onPendingPluginsChange, pendingPlugins]);
|
|
101
|
+
const toggle = useCallback((item, next) => {
|
|
102
|
+
if (sessionId) activation.toggle(item, next);
|
|
103
|
+
else togglePending(item, next);
|
|
104
|
+
}, [activation, sessionId, togglePending]);
|
|
105
|
+
const selectedItems = useMemo(
|
|
106
|
+
() => items.filter((item) => item.active),
|
|
107
|
+
[items]
|
|
108
|
+
);
|
|
109
|
+
const onSelectedChangeRef = useRef(onSelectedChange);
|
|
110
|
+
onSelectedChangeRef.current = onSelectedChange;
|
|
111
|
+
const latestSelected = useRef(selectedItems);
|
|
112
|
+
latestSelected.current = selectedItems;
|
|
113
|
+
const reportSelected = useCallback(() => {
|
|
114
|
+
onSelectedChangeRef.current?.(latestSelected.current);
|
|
115
|
+
}, []);
|
|
116
|
+
const selectedNames = selectedItems.map((item) => item.name).join("\0");
|
|
117
|
+
useEffect(reportSelected, [reportSelected, selectedNames]);
|
|
118
|
+
const failed = sessionId ? activation.listError : pendingError;
|
|
119
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
120
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-[hsl(var(--border))] border-b px-3 py-2", children: [
|
|
121
|
+
/* @__PURE__ */ jsx(Search, { size: 12, className: "shrink-0 text-[hsl(var(--muted-foreground))]", "aria-hidden": "true" }),
|
|
122
|
+
/* @__PURE__ */ jsx(
|
|
123
|
+
"input",
|
|
124
|
+
{
|
|
125
|
+
value: query,
|
|
126
|
+
onChange: (event) => setQuery(event.target.value),
|
|
127
|
+
placeholder: "\u641C\u7D22\u8FDE\u63A5\u5668",
|
|
128
|
+
"aria-label": "\u641C\u7D22\u8FDE\u63A5\u5668",
|
|
129
|
+
className: "min-w-0 flex-1 bg-transparent text-[11px] outline-none placeholder:text-[hsl(var(--muted-foreground))]"
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
] }),
|
|
133
|
+
renderComputerSection ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
134
|
+
/* @__PURE__ */ jsx(PanelTitle, { children: "\u7535\u8111" }),
|
|
135
|
+
renderComputerSection(query)
|
|
136
|
+
] }) : null,
|
|
137
|
+
/* @__PURE__ */ jsx(PanelDivider, {}),
|
|
138
|
+
/* @__PURE__ */ jsx(PanelTitle, { children: "\u63D2\u4EF6" }),
|
|
139
|
+
!sessionId ? (
|
|
140
|
+
// 首页没有会话,开关只记下「这条消息要带上谁」:不说清楚,用户会以为已经
|
|
141
|
+
// 生效(issue 明确要求「明确为待选,不宣称已经激活」)。
|
|
142
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 pb-0.5 text-[10px] text-[hsl(var(--muted-foreground))]", children: "\u5148\u9009\u4E2D\uFF0C\u53D1\u9001\u8FD9\u6761\u6D88\u606F\u65F6\u4F1A\u4E00\u5E76\u542F\u7528" })
|
|
143
|
+
) : null,
|
|
144
|
+
(sessionId ? activation.loading : pendingLoading) && visibleItems.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 text-[11px] text-[hsl(var(--muted-foreground))]", children: [
|
|
145
|
+
/* @__PURE__ */ jsx(LoaderCircle, { size: 12, className: "mr-1 inline animate-spin" }),
|
|
146
|
+
"\u6B63\u5728\u83B7\u53D6\u63D2\u4EF6\u2026"
|
|
147
|
+
] }) : null,
|
|
148
|
+
failed ? /* @__PURE__ */ jsx(
|
|
149
|
+
"button",
|
|
150
|
+
{
|
|
151
|
+
type: "button",
|
|
152
|
+
onClick: () => sessionId ? reload() : void loadPendingCatalog(),
|
|
153
|
+
className: "px-3 py-1.5 text-left text-[11px] text-[hsl(var(--muted-foreground))] underline",
|
|
154
|
+
children: "\u63D2\u4EF6\u5217\u8868\u6682\u4E0D\u53EF\u7528\uFF0C\u70B9\u51FB\u91CD\u8BD5"
|
|
155
|
+
}
|
|
156
|
+
) : null,
|
|
157
|
+
/* @__PURE__ */ jsx(
|
|
158
|
+
PluginConnectorList,
|
|
159
|
+
{
|
|
160
|
+
client,
|
|
161
|
+
sessionId,
|
|
162
|
+
items: visibleItems,
|
|
163
|
+
inFlight: activation.inFlight,
|
|
164
|
+
busy: sessionId ? activation.busy : pendingLoading,
|
|
165
|
+
mutationError: sessionId ? activation.mutationError : false,
|
|
166
|
+
onToggle: toggle,
|
|
167
|
+
onRetry: activation.retry,
|
|
168
|
+
onEditConfig: activation.editConfig,
|
|
169
|
+
configuring: sessionId ? activation.configuring : null,
|
|
170
|
+
onConfigSaved: activation.onConfigSaved,
|
|
171
|
+
onConfigClose: activation.onConfigClose,
|
|
172
|
+
disabledReason: sessionId ? null : pendingDisabledReason,
|
|
173
|
+
unavailableText: failed ? null : query.trim() ? "\u6CA1\u6709\u5339\u914D\u7684\u63D2\u4EF6" : null,
|
|
174
|
+
emptyText: sessionId ? "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6" : "\u5C1A\u672A\u5B89\u88C5\u63D2\u4EF6\uFF0C\u53BB\u5E94\u7528\u5E02\u573A\u6DFB\u52A0\u4E00\u4E2A",
|
|
175
|
+
draft: !sessionId
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
renderExternalAccounts ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
179
|
+
/* @__PURE__ */ jsx(PanelDivider, {}),
|
|
180
|
+
/* @__PURE__ */ jsx(PanelTitle, { children: "\u5916\u90E8\u8D26\u53F7" }),
|
|
181
|
+
renderExternalAccounts(query)
|
|
182
|
+
] }) : null,
|
|
183
|
+
renderFooterActions ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
184
|
+
/* @__PURE__ */ jsx(PanelDivider, {}),
|
|
185
|
+
renderFooterActions()
|
|
186
|
+
] }) : null
|
|
187
|
+
] });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/components/PluginTriggerStack.tsx
|
|
191
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
192
|
+
var AVATAR_SIZE = 20;
|
|
193
|
+
function hueOf(name) {
|
|
194
|
+
let hash = 0;
|
|
195
|
+
for (const char of name) hash = (hash * 31 + char.codePointAt(0)) % 1000003;
|
|
196
|
+
return hash % 360;
|
|
197
|
+
}
|
|
198
|
+
var AVATAR_PALETTE = [
|
|
199
|
+
"bg-violet-100 text-violet-800 dark:bg-violet-500/25 dark:text-violet-200",
|
|
200
|
+
"bg-sky-100 text-sky-800 dark:bg-sky-500/25 dark:text-sky-200",
|
|
201
|
+
"bg-emerald-100 text-emerald-800 dark:bg-emerald-500/25 dark:text-emerald-200",
|
|
202
|
+
"bg-amber-100 text-amber-800 dark:bg-amber-500/25 dark:text-amber-200",
|
|
203
|
+
"bg-rose-100 text-rose-800 dark:bg-rose-500/25 dark:text-rose-200",
|
|
204
|
+
"bg-indigo-100 text-indigo-800 dark:bg-indigo-500/25 dark:text-indigo-200",
|
|
205
|
+
"bg-teal-100 text-teal-800 dark:bg-teal-500/25 dark:text-teal-200",
|
|
206
|
+
"bg-fuchsia-100 text-fuchsia-800 dark:bg-fuchsia-500/25 dark:text-fuchsia-200"
|
|
207
|
+
];
|
|
208
|
+
function PluginTriggerStack({ client, sessionId, summary, className }) {
|
|
209
|
+
if (summary.total === 0) return null;
|
|
210
|
+
const ring = "ring-2 ring-[hsl(var(--background))]";
|
|
211
|
+
return /* @__PURE__ */ jsxs2("span", { className: `flex items-center -space-x-1 ${className ?? ""}`, children: [
|
|
212
|
+
summary.visible.map((item) => {
|
|
213
|
+
const label = item.displayName?.trim() || item.name;
|
|
214
|
+
const tone = AVATAR_PALETTE[hueOf(item.name) % AVATAR_PALETTE.length];
|
|
215
|
+
return item.icon ? /* @__PURE__ */ jsx2(
|
|
216
|
+
SessionPluginIcon,
|
|
217
|
+
{
|
|
218
|
+
client,
|
|
219
|
+
sessionId: item.iconSource === "account" ? null : sessionId,
|
|
220
|
+
plugin: item,
|
|
221
|
+
size: AVATAR_SIZE,
|
|
222
|
+
shape: "circle",
|
|
223
|
+
className: ring
|
|
224
|
+
},
|
|
225
|
+
item.name
|
|
226
|
+
) : /* @__PURE__ */ jsx2(
|
|
227
|
+
"span",
|
|
228
|
+
{
|
|
229
|
+
title: label,
|
|
230
|
+
className: `flex shrink-0 items-center justify-center rounded-full font-semibold text-[11px] ${tone} ${ring}`,
|
|
231
|
+
style: { width: AVATAR_SIZE, height: AVATAR_SIZE },
|
|
232
|
+
children: Array.from(label.trim())[0]?.toUpperCase() ?? "?"
|
|
233
|
+
},
|
|
234
|
+
item.name
|
|
235
|
+
);
|
|
236
|
+
}),
|
|
237
|
+
summary.overflow > 0 ? /* @__PURE__ */ jsxs2(
|
|
238
|
+
"span",
|
|
239
|
+
{
|
|
240
|
+
className: `flex shrink-0 items-center justify-center rounded-full bg-[hsl(var(--muted))] font-medium text-[hsl(var(--muted-foreground))] text-[10px] ${ring}`,
|
|
241
|
+
style: { width: AVATAR_SIZE, height: AVATAR_SIZE },
|
|
242
|
+
children: [
|
|
243
|
+
"+",
|
|
244
|
+
summary.overflow
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
) : null
|
|
248
|
+
] });
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export {
|
|
252
|
+
selectionFromItem,
|
|
253
|
+
TRIGGER_ICON_LIMIT,
|
|
254
|
+
triggerSummary,
|
|
255
|
+
ConnectorPanel,
|
|
256
|
+
PluginTriggerStack
|
|
257
|
+
};
|
|
258
|
+
//# sourceMappingURL=chunk-WCMGQJLE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/connector-panel-types.ts","../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 type { 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\"\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 /** 宿主注入:外部账号分区(飞书 / 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 renderExternalAccounts,\n renderFooterActions,\n className,\n}: ConnectorPanelProps) {\n const [query, setQuery] = useState(\"\")\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 // 首页不会走这个分支:待选在下面自己处理开关,不碰会话接口。\n sessionId: sessionId ?? \"\",\n onChange: onPluginsChanged,\n })\n const { reload, items: sessionItems } = activation\n\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 // 首页没有会话:只读账号级目录,不建会话、不激活插件、不启动沙盒。\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 // 首页的「配置」入口没有意义:只有已经启用的会话插件才需要改配置。\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 () => items.filter((item) => item.active),\n [items],\n )\n // 单向汇报给宿主:只在选中的集合真的变化时通知,避免每次渲染都把宿主刷一遍\n // (selectedItems 每次都是新数组,所以用名字串当指纹)。\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 <PanelDivider />\n <PanelTitle>插件</PanelTitle>\n {!sessionId ? (\n // 首页没有会话,开关只记下「这条消息要带上谁」:不说清楚,用户会以为已经\n // 生效(issue 明确要求「明确为待选,不宣称已经激活」)。\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}\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\n/** 头像堆叠里单枚的边长:与面板列表同一档(20),不喧宾夺主。 */\nconst AVATAR_SIZE = 20\n\n/**\n * 插件名 → 稳定色相(0–359)。\n *\n * 没有图标 token 的插件用显示名首字占位,那个字得能区分「这是不同的插件」——所以\n * 按名字散列取色:同一个插件在任何位置、任何会话都是同一个颜色。按下标取调色板\n * 会随选中顺序变色,看着像换了个人。\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 // 身份色按插件名定,不看位置:同一个插件在哪一行、排第几个都是同一个颜色。\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":";;;;;;;;;;;AAmBO,SAAS,kBAAkB,MAAqD;AACrF,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK,gBAAgB;AAAA,IAClC,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,EACnB;AACF;AAGO,IAAM,qBAAqB;AAmB3B,SAAS,eACd,OACgB;AAChB,QAAM,UAAU,MAAM,MAAM,GAAG,kBAAkB;AACjD,SAAO;AAAA,IACL;AAAA,IACA,UAAU,MAAM,SAAS,QAAQ;AAAA,IACjC,OAAO,MAAM;AAAA,EACf;AACF;;;ACvDA,SAAS,aAAa,WAAW,SAAS,QAAQ,gBAAgC;AAqCzE,SAmID,UAnIC,KAuHH,YAvHG;AADT,SAAS,eAAe;AACtB,SAAO,oBAAC,SAAI,WAAU,6CAA4C;AACpE;AAEA,SAAS,WAAW,EAAE,SAAS,GAA4B;AACzD,SACE,oBAAC,SAAI,WAAU,oEACZ,UACH;AAEJ;AASO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAsC,IAAI;AACtF,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,QAAM,aAAa,2BAA2B;AAAA,IAC5C;AAAA;AAAA,IAEA,WAAW,aAAa;AAAA,IACxB,UAAU;AAAA,EACZ,CAAC;AACD,QAAM,EAAE,QAAQ,OAAO,aAAa,IAAI;AAGxC,YAAU,MAAM;AACd,QAAI,UAAW,QAAO;AAAA,EACxB,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,QAAM,qBAAqB,YAAY,YAAY;AACjD,sBAAkB,IAAI;AACtB,oBAAgB,KAAK;AACrB,QAAI;AACF,YAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,QAAQ,QAAQ;AACjD,wBAAkB,OAAO;AAAA,IAC3B,QAAQ;AACN,sBAAgB,IAAI;AAAA,IACtB,UAAE;AACA,wBAAkB,KAAK;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,YAAU,MAAM;AACd,QAAI,UAAW;AAEf,SAAK,mBAAmB;AAAA,EAC1B,GAAG,CAAC,oBAAoB,SAAS,CAAC;AAElC,QAAM,WAAW;AAAA,IACf,MAAM,IAAI,KAAK,kBAAkB,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;AAAA,IAC7D,CAAC,cAAc;AAAA,EACjB;AACA,QAAM,QAAQ,QAAQ,MAAM;AAC1B,QAAI,UAAW,QAAO;AACtB,WAAO,wBAAwB,kBAAkB,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU;AAAA,MAClE,GAAG;AAAA,MACH,QAAQ,SAAS,IAAI,KAAK,IAAI;AAAA,IAChC,EAAE;AAAA,EACJ,GAAG,CAAC,gBAAgB,UAAU,WAAW,YAAY,CAAC;AAEtD,QAAM,eAAe;AAAA,IACnB,MAAO,YACH,qBAAqB,OAAO,KAAK,IACjC,qBAAqB,OAAO,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,QAAQ,OAAU,EAAE;AAAA,IACrF,CAAC,OAAO,OAAO,SAAS;AAAA,EAC1B;AAEA,QAAM,gBAAgB,YAAY,CAAC,MAA2B,SAAkB;AAC9E,UAAM,QAAQ,kBAAkB,CAAC,GAAG,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,IAAI;AAC9E,6BAAyB,OAAO,CAAC,GAAG,MAAM,kBAAkB,IAAI,CAAC,IAAI,IAAI;AAAA,EAC3E,GAAG,CAAC,wBAAwB,cAAc,CAAC;AAE3C,QAAM,SAAS,YAAY,CAAC,MAA2B,SAAkB;AACvE,QAAI,UAAW,YAAW,OAAO,MAAM,IAAI;AAAA,QACtC,eAAc,MAAM,IAAI;AAAA,EAC/B,GAAG,CAAC,YAAY,WAAW,aAAa,CAAC;AAEzC,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,OAAO,CAAC,SAAS,KAAK,MAAM;AAAA,IACxC,CAAC,KAAK;AAAA,EACR;AAGA,QAAM,sBAAsB,OAAO,gBAAgB;AACnD,sBAAoB,UAAU;AAC9B,QAAM,iBAAiB,OAAO,aAAa;AAC3C,iBAAe,UAAU;AACzB,QAAM,iBAAiB,YAAY,MAAM;AACvC,wBAAoB,UAAU,eAAe,OAAO;AAAA,EACtD,GAAG,CAAC,CAAC;AACL,QAAM,gBAAgB,cAAc,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,IAAQ;AAG1E,YAAU,gBAAgB,CAAC,gBAAgB,aAAa,CAAC;AAEzD,QAAM,SAAS,YAAY,WAAW,YAAY;AAElD,SACE,qBAAC,SAAI,WACH;AAAA,yBAAC,SAAI,WAAU,0EACb;AAAA,0BAAC,UAAO,MAAM,IAAI,WAAU,gDAA+C,eAAY,QAAO;AAAA,MAC9F;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,UAChD,aAAY;AAAA,UACZ,cAAW;AAAA,UACX,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IAEC,wBACC,iCACE;AAAA,0BAAC,cAAW,0BAAE;AAAA,MACb,sBAAsB,KAAK;AAAA,OAC9B,IACE;AAAA,IAEJ,oBAAC,gBAAa;AAAA,IACd,oBAAC,cAAW,0BAAE;AAAA,IACb,CAAC;AAAA;AAAA;AAAA,MAGA,oBAAC,SAAI,WAAU,+DAA8D,8GAE7E;AAAA,QACE;AAAA,KACF,YAAY,WAAW,UAAU,mBAAmB,aAAa,WAAW,IAC5E,qBAAC,SAAI,WAAU,+DACb;AAAA,0BAAC,gBAAQ,MAAM,IAAI,WAAU,4BAA2B;AAAA,MAAE;AAAA,OAE5D,IACE;AAAA,IACH,SACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAO,YAAY,OAAO,IAAI,KAAK,mBAAmB;AAAA,QAC/D,WAAU;AAAA,QACX;AAAA;AAAA,IAED,IACE;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,UAAU,WAAW;AAAA,QACrB,MAAM,YAAY,WAAW,OAAO;AAAA,QACpC,eAAe,YAAY,WAAW,gBAAgB;AAAA,QACtD,UAAU;AAAA,QACV,SAAS,WAAW;AAAA,QACpB,cAAc,WAAW;AAAA,QACzB,aAAa,YAAY,WAAW,cAAc;AAAA,QAClD,eAAe,WAAW;AAAA,QAC1B,eAAe,WAAW;AAAA,QAC1B,gBAAgB,YAAY,OAAO;AAAA,QACnC,iBACE,SACI,OACA,MAAM,KAAK,IACT,+CACA;AAAA,QAER,WAAW,YAAY,yCAAW;AAAA,QAClC,OAAO,CAAC;AAAA;AAAA,IACV;AAAA,IAEC,yBACC,iCACE;AAAA,0BAAC,gBAAa;AAAA,MACd,oBAAC,cAAW,sCAAI;AAAA,MACf,uBAAuB,KAAK;AAAA,OAC/B,IACE;AAAA,IAEH,sBACC,iCACE;AAAA,0BAAC,gBAAa;AAAA,MACb,oBAAoB;AAAA,OACvB,IACE;AAAA,KACN;AAEJ;;;AC1KU,gBAAAA,MAqBF,QAAAC,aArBE;AAzDV,IAAM,cAAc;AASpB,SAAS,MAAM,MAAsB;AACnC,MAAI,OAAO;AACX,aAAW,QAAQ,KAAM,SAAQ,OAAO,KAAK,KAAK,YAAY,CAAC,KAAM;AACrE,SAAO,OAAO;AAChB;AAYA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaO,SAAS,mBAAmB,EAAE,QAAQ,WAAW,SAAS,UAAU,GAA4B;AACrG,MAAI,QAAQ,UAAU,EAAG,QAAO;AAChC,QAAM,OAAO;AACb,SACE,gBAAAA,MAAC,UAAK,WAAW,gCAAgC,aAAa,EAAE,IAC7D;AAAA,YAAQ,QAAQ,IAAI,CAAC,SAAS;AAC7B,YAAM,QAAQ,KAAK,aAAa,KAAK,KAAK,KAAK;AAE/C,YAAM,OAAO,eAAe,MAAM,KAAK,IAAI,IAAI,eAAe,MAAM;AACpE,aAAO,KAAK,OACV,gBAAAD;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,WAAW,KAAK,eAAe,YAAY,OAAO;AAAA,UAClD,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAM;AAAA,UACN,WAAW;AAAA;AAAA,QANN,KAAK;AAAA,MAOZ,IAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO;AAAA,UACP,WAAW,oFAAoF,IAAI,IAAI,IAAI;AAAA,UAC3G,OAAO,EAAE,OAAO,aAAa,QAAQ,YAAY;AAAA,UAEhD,gBAAM,KAAK,MAAM,KAAK,CAAC,EAAE,CAAC,GAAG,YAAY,KAAK;AAAA;AAAA,QAL1C,KAAK;AAAA,MAMZ;AAAA,IAEJ,CAAC;AAAA,IACA,QAAQ,WAAW,IAClB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,6IAA6I,IAAI;AAAA,QAC5J,OAAO,EAAE,OAAO,aAAa,QAAQ,YAAY;AAAA,QAClD;AAAA;AAAA,UACG,QAAQ;AAAA;AAAA;AAAA,IACZ,IACE;AAAA,KACN;AAEJ;","names":["jsx","jsxs"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AgentSession, CreateSessionRequest } from "@blade-hq/agent-client";
|
|
1
|
+
import type { AgentSession, CreateSessionRequest } from "@blade-hq/agent-client/internal";
|
|
2
2
|
import { type ReactNode } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import type { FollowupInteractionEvent } from "
|
|
3
|
+
import type { ChatPresentationProps } from "../chat/customization";
|
|
4
|
+
import type { FollowupInteractionEvent } from "../chat/followup-interaction";
|
|
5
5
|
export interface AgentChatProps extends ChatPresentationProps {
|
|
6
6
|
/** follow-up、成果和评分交互;SDK 不绑定任何分析厂商。 */
|
|
7
7
|
onFollowupInteraction?: (event: FollowupInteractionEvent) => void;
|
|
@@ -2,8 +2,8 @@ import { type AgentChatProps } from "./AgentChat";
|
|
|
2
2
|
import { type LlmChatHandle } from "./LlmChat";
|
|
3
3
|
import type { LlmAdvancedSettings, LlmOverride } from "./LlmAdvancedSettings";
|
|
4
4
|
import type { LlmChatOptions } from "../hooks/use-llm-chat";
|
|
5
|
-
export type { AssistantTextRendererProps, AskUserQuestionRendererProps, ChatViewClassNames, ChatViewRenderers, ChatViewSlots, PlanUpdateRendererProps, UserMessageRendererProps, } from "
|
|
6
|
-
export type { FollowupInteractionEvent } from "
|
|
5
|
+
export type { AssistantTextRendererProps, AskUserQuestionRendererProps, ChatViewClassNames, ChatViewRenderers, ChatViewSlots, PlanUpdateRendererProps, UserMessageRendererProps, } from "../chat/customization";
|
|
6
|
+
export type { FollowupInteractionEvent } from "../chat/followup-interaction";
|
|
7
7
|
export interface ChatViewProps extends AgentChatProps {
|
|
8
8
|
/** 挂哪个下层组件。默认 `agent`——不传就是接 Blade 智能体会话的原有行为。 */
|
|
9
9
|
mode?: "agent" | "llm";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BladeClient, SessionPluginActivation } from "@blade-hq/agent-client";
|
|
1
|
+
import type { BladeClient, SessionPluginActivation } from "@blade-hq/agent-client/internal";
|
|
2
2
|
import { type ReactNode } from "react";
|
|
3
3
|
import { type PluginConnectorItem } from "./plugin-connector";
|
|
4
4
|
import { type PluginConnectorSelection } from "./connector-panel-types";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { type ChatPresentationProps } from "../chat/customization";
|
|
1
2
|
import { type LlmChatOptions } from "../hooks/use-llm-chat";
|
|
2
|
-
import { type ChatPresentationProps } from "./ChatSurface";
|
|
3
3
|
import { type LlmAdvancedSettings, type LlmOverride } from "./LlmAdvancedSettings";
|
|
4
4
|
/** 纯 LLM 模式的操作句柄,对应智能体模式的 session.insertText() / send()。 */
|
|
5
5
|
export interface LlmChatHandle {
|
|
@@ -22,11 +22,3 @@ export declare function PlanUpdateBlock({ toolCall, running, autoReveal, classNa
|
|
|
22
22
|
autoReveal?: boolean;
|
|
23
23
|
className?: string;
|
|
24
24
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
25
|
-
export declare function CurrentPlanPanel({ messages, running, revealRevision, sessionId, className, }: {
|
|
26
|
-
messages: ChatMessage[];
|
|
27
|
-
running?: boolean;
|
|
28
|
-
/** 仅实时成功的 update_plan 递增;历史 hydration 不得改变。 */
|
|
29
|
-
revealRevision?: number;
|
|
30
|
-
sessionId?: string;
|
|
31
|
-
className?: string;
|
|
32
|
-
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BladeClient, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { BladeClient, SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
import type { PluginConnectorItem } from "./plugin-connector";
|
|
3
3
|
export interface ConfiguringPlugin {
|
|
4
4
|
name: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BladeClient, SessionPlugin, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { BladeClient, SessionPlugin, SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
export interface SessionPluginConfigDialogProps {
|
|
3
3
|
client: BladeClient;
|
|
4
4
|
sessionId: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionPluginConfigError, SessionPluginConfigSet, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { SessionPluginConfigError, SessionPluginConfigSet, SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
export interface SessionPluginConfigDraft {
|
|
3
3
|
set: SessionPluginConfigSet[];
|
|
4
4
|
remove: string[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type QueuedMessage, type SessionQueueSnapshot } from "@blade-hq/agent-client";
|
|
1
|
+
import { type QueuedMessage, type SessionQueueSnapshot } from "@blade-hq/agent-client/internal";
|
|
2
2
|
import { type JSX } from "react";
|
|
3
3
|
export interface SessionQueuePanelProps {
|
|
4
4
|
snapshot: SessionQueueSnapshot;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionPluginConfigSet, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { SessionPluginConfigSet, SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
export type ConfigPath = (string | number)[];
|
|
3
3
|
export type ConfigValues = Record<string, unknown>;
|
|
4
4
|
export declare function createConfigDraft(config: SessionPluginConfigState): {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
export type JsonSchema = Record<string, unknown>;
|
|
3
3
|
export declare function pointerOf(parts: (string | number)[]): string;
|
|
4
4
|
export declare function pointerParts(pointer: string): string[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BladeClient, SessionPluginActivation, SessionPluginConfigState } from "@blade-hq/agent-client";
|
|
1
|
+
import type { BladeClient, SessionPluginActivation, SessionPluginConfigState } from "@blade-hq/agent-client/internal";
|
|
2
2
|
import type { ConfiguringPlugin } from "./PluginConnectorList";
|
|
3
3
|
import { type PluginConnectorItem } from "./plugin-connector";
|
|
4
4
|
export interface UseSessionPluginActivationResult {
|
package/dist/context.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import type { BladeClient } from "@blade-hq/agent-client";
|
|
2
2
|
import { type ReactNode } from "react";
|
|
3
|
+
import type { BladeHost } from "./host";
|
|
3
4
|
export interface BladeProviderProps {
|
|
4
5
|
client: BladeClient;
|
|
6
|
+
/**
|
|
7
|
+
* 宿主提供的业务动作(打开文件、跳转会话、上传附件……)。全部可选:
|
|
8
|
+
* 没提供的动作,聊天界面里对应的按钮和菜单项不显示。传稳定引用(模块常量或
|
|
9
|
+
* useMemo),每次渲染新建对象会让依赖它的清单反复重新加载。
|
|
10
|
+
*/
|
|
11
|
+
host?: BladeHost;
|
|
5
12
|
children: ReactNode;
|
|
6
13
|
}
|
|
7
14
|
/**
|
|
8
|
-
* 提供 client
|
|
15
|
+
* 提供 client 级共享(一条连接、一份鉴权)与宿主动作。不含任何全局状态:
|
|
9
16
|
* 同一 Provider 下多个 ChatView / useAgentSession 各自独立。
|
|
10
17
|
*/
|
|
11
|
-
export declare function BladeProvider({ client, children }: BladeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare function BladeProvider({ client, host, children }: BladeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
12
19
|
/** 读取当前 BladeProvider 提供的 client。不在 Provider 内使用时抛错。 */
|
|
13
20
|
export declare function useBladeClient(): BladeClient;
|
|
14
21
|
export declare function useOptionalBladeClient(): BladeClient | null;
|
|
22
|
+
/** 读取宿主动作;不在 Provider 内或宿主没传 `host` 时是空对象(所有动作都缺失)。 */
|
|
23
|
+
export declare function useBladeHost(): BladeHost;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentSession } from "@blade-hq/agent-client";
|
|
1
|
+
import { type AgentSession, type BladeChatMountRenderers } from "@blade-hq/agent-client";
|
|
2
2
|
/**
|
|
3
3
|
* `<blade-chat base-url="https://..." session-id="可选" theme="light|dark">`
|
|
4
4
|
*
|
|
@@ -10,11 +10,24 @@ export declare class BladeChatElement extends HTMLElement {
|
|
|
10
10
|
private root;
|
|
11
11
|
private shadow;
|
|
12
12
|
private mountPoint;
|
|
13
|
+
/** 弹层根:Shadow DOM 里 Radix 弹层默认挂的 document.body 够不着内置样式,统一挂到这里。 */
|
|
14
|
+
private overlayRoot;
|
|
13
15
|
/** 当前会话(连接完成后可用);BladeAgent.getChat() 依赖它。 */
|
|
14
16
|
session: AgentSession | null;
|
|
15
17
|
private sessionWaiters;
|
|
16
18
|
/** 自动创建的会话 id:attribute 变化触发的重渲染要继续用它,避免重复建会话。 */
|
|
17
19
|
private autoCreatedSessionId;
|
|
20
|
+
private mountRenderers;
|
|
21
|
+
/** 转换后的 React 渲染器按渲染器对象缓存,避免每次渲染重建挂载内容。 */
|
|
22
|
+
private reactRenderers;
|
|
23
|
+
/**
|
|
24
|
+
* 挂载式渲染器(JS 属性,不是 HTML 属性):为工具卡片、用户消息、助手正文提供
|
|
25
|
+
* DOM 节点与数据,由宿主自己挂载内容(Vue 组件、原生 DOM 都行)。
|
|
26
|
+
* 挂载节点是本元素的 light DOM 子节点,经 `<slot>` 显示在对应位置。
|
|
27
|
+
*/
|
|
28
|
+
get renderers(): BladeChatMountRenderers | null;
|
|
29
|
+
set renderers(value: BladeChatMountRenderers | null);
|
|
30
|
+
private currentReactRenderers;
|
|
18
31
|
connectedCallback(): void;
|
|
19
32
|
/**
|
|
20
33
|
* 自定义样式口子:<blade-chat> 的直接 <style> 子元素会被拷入 Shadow DOM,
|