@blade-hq/agent-react 2610.0.0-beta.32 → 2610.0.0-beta.33
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 +20 -0
- package/dist/components/SessionMemoryToggle.d.ts +19 -0
- package/dist/context.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +114 -2
- package/dist/index.js.map +1 -1
- package/dist/style.css +4 -1
- package/dist/style.full.css +4 -1
- package/package.json +2 -2
- package/public-api.md +22 -1
package/README.md
CHANGED
|
@@ -74,6 +74,26 @@ await session?.send("你好")
|
|
|
74
74
|
- 必须覆盖连接窗口内事件时,用 `onSessionConnected` 在历史加载和房间订阅开始前完成订阅,并返回取消订阅函数。
|
|
75
75
|
- 同一 `sessionId` 的多次调用复用同一 `AgentSession` 实例(引用计数);卸载后延迟释放,路由抖动不会断连。
|
|
76
76
|
|
|
77
|
+
## SessionMemoryToggle
|
|
78
|
+
|
|
79
|
+
把当前会话是否使用记忆放进宿主自己的会话设置面板:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
const [memoryEnabled, setMemoryEnabled] = useState(session.memory_enabled !== false)
|
|
83
|
+
|
|
84
|
+
<SessionMemoryToggle
|
|
85
|
+
sessionId={session.id}
|
|
86
|
+
enabled={memoryEnabled}
|
|
87
|
+
onSaved={(_sessionId, enabled) => setMemoryEnabled(enabled)}
|
|
88
|
+
onError={(error) => toast.error(String(error))}
|
|
89
|
+
/>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
组件默认使用 `BladeProvider` 的 client;已有独立 client 装配层的宿主也可以显式传
|
|
93
|
+
`client={client}`。同一 client、同一会话的多个开关共享保存锁,即使切换会话或同时存在多个
|
|
94
|
+
设置入口,也不会并发提交相互覆盖。服务端确认后的权威值通过 `onSaved` 返回。
|
|
95
|
+
全部属性见 `SessionMemoryToggleProps`。
|
|
96
|
+
|
|
77
97
|
## useReplay
|
|
78
98
|
|
|
79
99
|
会话回放(演示 / 彩排):拿一个已经聊完的会话当素材,重现当时的回复和工具调用,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BladeClient } from "@blade-hq/agent-client";
|
|
2
|
+
export interface SessionMemoryToggleProps {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** 不在 BladeProvider 内使用时显式传入,与宿主现有 BladeClient 复用连接和鉴权。 */
|
|
6
|
+
client?: BladeClient;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
label?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
labelClassName?: string;
|
|
11
|
+
inputClassName?: string;
|
|
12
|
+
onSaved?: (sessionId: string, enabled: boolean) => void;
|
|
13
|
+
onError?: (error: unknown) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 当前会话记忆开关。同一 client + sessionId 的所有实例共享保存锁,避免多个聊天入口
|
|
17
|
+
* 或会话切换时发出乱序更新;服务端成功后才通过 onSaved 交还权威值。
|
|
18
|
+
*/
|
|
19
|
+
export declare function SessionMemoryToggle({ sessionId, enabled, client: clientProp, disabled, label, className, labelClassName, inputClassName, onSaved, onError, }: SessionMemoryToggleProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/context.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ export interface BladeProviderProps {
|
|
|
11
11
|
export declare function BladeProvider({ client, children }: BladeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
12
12
|
/** 读取当前 BladeProvider 提供的 client。不在 Provider 内使用时抛错。 */
|
|
13
13
|
export declare function useBladeClient(): BladeClient;
|
|
14
|
+
export declare function useOptionalBladeClient(): BladeClient | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export type { PlanStepStatus, PlanUpdateData, PlanUpdateDisplayState, } from "./
|
|
|
32
32
|
export { ContextCard, ContextGroupCard } from "./components/ContextCard";
|
|
33
33
|
export type { ContextCardProps, ContextGroupCardProps } from "./components/ContextCard";
|
|
34
34
|
export { collectMemoryRefs, MemoryRefsHint } from "./components/AssistantTurnBlock";
|
|
35
|
+
export { SessionMemoryToggle } from "./components/SessionMemoryToggle";
|
|
36
|
+
export type { SessionMemoryToggleProps } from "./components/SessionMemoryToggle";
|
|
35
37
|
export { isAgentComputerCommand, isAgentComputerToolCall, classifyAgentComputerLaunchOutcome, } from "./lib/agent-computer-command";
|
|
36
38
|
export type { AgentComputerLaunchOutcome } from "./lib/agent-computer-command";
|
|
37
39
|
export * from "@blade-hq/agent-client";
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,9 @@ function useBladeClient() {
|
|
|
17
17
|
}
|
|
18
18
|
return client;
|
|
19
19
|
}
|
|
20
|
+
function useOptionalBladeClient() {
|
|
21
|
+
return useContext(BladeClientContext);
|
|
22
|
+
}
|
|
20
23
|
|
|
21
24
|
// src/hooks/use-agent-session.ts
|
|
22
25
|
import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -2248,8 +2251,9 @@ function AgentLoopBlock({ toolCall }) {
|
|
|
2248
2251
|
ChevronRight,
|
|
2249
2252
|
{
|
|
2250
2253
|
size: 14,
|
|
2254
|
+
style: { transitionDuration: "260ms", transitionTimingFunction: "cubic-bezier(0.25, 0.1, 0.25, 1)" },
|
|
2251
2255
|
className: cn(
|
|
2252
|
-
"shrink-0 transition-transform
|
|
2256
|
+
"shrink-0 transition-transform",
|
|
2253
2257
|
expanded && "rotate-90"
|
|
2254
2258
|
),
|
|
2255
2259
|
"aria-hidden": "true"
|
|
@@ -3294,8 +3298,9 @@ function AssistantTurnBlock({
|
|
|
3294
3298
|
ChevronRight,
|
|
3295
3299
|
{
|
|
3296
3300
|
size: 14,
|
|
3301
|
+
style: { transitionDuration: "260ms", transitionTimingFunction: "cubic-bezier(0.25, 0.1, 0.25, 1)" },
|
|
3297
3302
|
className: cn(
|
|
3298
|
-
"shrink-0 transition-transform
|
|
3303
|
+
"shrink-0 transition-transform",
|
|
3299
3304
|
effectiveMode === "detail" && "rotate-90"
|
|
3300
3305
|
),
|
|
3301
3306
|
"aria-hidden": "true"
|
|
@@ -5007,6 +5012,112 @@ function ContextGroupCard({ contexts, className }) {
|
|
|
5007
5012
|
] });
|
|
5008
5013
|
}
|
|
5009
5014
|
|
|
5015
|
+
// src/components/SessionMemoryToggle.tsx
|
|
5016
|
+
import { useCallback as useCallback9, useEffect as useEffect14, useRef as useRef13, useState as useState17, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
5017
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5018
|
+
var saveStates = /* @__PURE__ */ new WeakMap();
|
|
5019
|
+
function getSaveState(client, sessionId) {
|
|
5020
|
+
let clientStates = saveStates.get(client);
|
|
5021
|
+
if (!clientStates) {
|
|
5022
|
+
clientStates = /* @__PURE__ */ new Map();
|
|
5023
|
+
saveStates.set(client, clientStates);
|
|
5024
|
+
}
|
|
5025
|
+
let state = clientStates.get(sessionId);
|
|
5026
|
+
if (!state) {
|
|
5027
|
+
state = { saving: false, listeners: /* @__PURE__ */ new Set() };
|
|
5028
|
+
clientStates.set(sessionId, state);
|
|
5029
|
+
}
|
|
5030
|
+
return state;
|
|
5031
|
+
}
|
|
5032
|
+
function notify(state) {
|
|
5033
|
+
for (const listener of state.listeners) listener();
|
|
5034
|
+
}
|
|
5035
|
+
function cleanupSaveState(client, sessionId, state) {
|
|
5036
|
+
if (state.saving || state.listeners.size > 0) return;
|
|
5037
|
+
const clientStates = saveStates.get(client);
|
|
5038
|
+
if (clientStates?.get(sessionId) === state) clientStates.delete(sessionId);
|
|
5039
|
+
}
|
|
5040
|
+
function SessionMemoryToggle({
|
|
5041
|
+
sessionId,
|
|
5042
|
+
enabled,
|
|
5043
|
+
client: clientProp,
|
|
5044
|
+
disabled = false,
|
|
5045
|
+
label = "\u5F53\u524D\u4F1A\u8BDD\u4F7F\u7528\u8BB0\u5FC6",
|
|
5046
|
+
className,
|
|
5047
|
+
labelClassName,
|
|
5048
|
+
inputClassName,
|
|
5049
|
+
onSaved,
|
|
5050
|
+
onError
|
|
5051
|
+
}) {
|
|
5052
|
+
const contextClient = useOptionalBladeClient();
|
|
5053
|
+
const client = clientProp ?? contextClient;
|
|
5054
|
+
if (!client) {
|
|
5055
|
+
throw new Error("SessionMemoryToggle \u5FC5\u987B\u5728 <BladeProvider> \u5185\u4F7F\u7528\u6216\u663E\u5F0F\u4F20\u5165 client");
|
|
5056
|
+
}
|
|
5057
|
+
const saveState = getSaveState(client, sessionId);
|
|
5058
|
+
const subscribe = useCallback9(
|
|
5059
|
+
(listener) => {
|
|
5060
|
+
saveState.listeners.add(listener);
|
|
5061
|
+
return () => {
|
|
5062
|
+
saveState.listeners.delete(listener);
|
|
5063
|
+
cleanupSaveState(client, sessionId, saveState);
|
|
5064
|
+
};
|
|
5065
|
+
},
|
|
5066
|
+
[client, saveState, sessionId]
|
|
5067
|
+
);
|
|
5068
|
+
const getSaving = useCallback9(() => saveState.saving, [saveState]);
|
|
5069
|
+
const saving = useSyncExternalStore2(
|
|
5070
|
+
subscribe,
|
|
5071
|
+
getSaving,
|
|
5072
|
+
getSaving
|
|
5073
|
+
);
|
|
5074
|
+
const [draftEnabled, setDraftEnabled] = useState17(enabled);
|
|
5075
|
+
const activeSessionIdRef = useRef13(sessionId);
|
|
5076
|
+
activeSessionIdRef.current = sessionId;
|
|
5077
|
+
useEffect14(() => {
|
|
5078
|
+
setDraftEnabled(enabled);
|
|
5079
|
+
}, [enabled, sessionId]);
|
|
5080
|
+
const update = useCallback9(
|
|
5081
|
+
(nextEnabled) => {
|
|
5082
|
+
const currentSaveState = getSaveState(client, sessionId);
|
|
5083
|
+
if (currentSaveState.saving) return;
|
|
5084
|
+
currentSaveState.saving = true;
|
|
5085
|
+
notify(currentSaveState);
|
|
5086
|
+
setDraftEnabled(nextEnabled);
|
|
5087
|
+
void client.sessions.updateSessionMemory(sessionId, nextEnabled).then(
|
|
5088
|
+
(updated) => {
|
|
5089
|
+
if (activeSessionIdRef.current === sessionId) {
|
|
5090
|
+
setDraftEnabled(updated.memory_enabled);
|
|
5091
|
+
}
|
|
5092
|
+
onSaved?.(sessionId, updated.memory_enabled);
|
|
5093
|
+
},
|
|
5094
|
+
(error) => {
|
|
5095
|
+
if (activeSessionIdRef.current === sessionId) setDraftEnabled(enabled);
|
|
5096
|
+
onError?.(error);
|
|
5097
|
+
}
|
|
5098
|
+
).finally(() => {
|
|
5099
|
+
currentSaveState.saving = false;
|
|
5100
|
+
notify(currentSaveState);
|
|
5101
|
+
cleanupSaveState(client, sessionId, currentSaveState);
|
|
5102
|
+
});
|
|
5103
|
+
},
|
|
5104
|
+
[client, enabled, onError, onSaved, sessionId]
|
|
5105
|
+
);
|
|
5106
|
+
return /* @__PURE__ */ jsxs20("label", { className: cn("flex items-center justify-between", className), children: [
|
|
5107
|
+
/* @__PURE__ */ jsx24("span", { className: labelClassName, children: label }),
|
|
5108
|
+
/* @__PURE__ */ jsx24(
|
|
5109
|
+
"input",
|
|
5110
|
+
{
|
|
5111
|
+
type: "checkbox",
|
|
5112
|
+
checked: draftEnabled,
|
|
5113
|
+
onChange: (event) => update(event.target.checked),
|
|
5114
|
+
disabled: disabled || saving,
|
|
5115
|
+
className: inputClassName
|
|
5116
|
+
}
|
|
5117
|
+
)
|
|
5118
|
+
] });
|
|
5119
|
+
}
|
|
5120
|
+
|
|
5010
5121
|
// src/lib/agent-computer-command.ts
|
|
5011
5122
|
var COMPUTER_LAUNCH_COMMAND_PATTERN = /(?:^|[\n;&|(]\s*)computer\s+launch(?:\s|$)/;
|
|
5012
5123
|
function isAgentComputerCommand(command) {
|
|
@@ -5065,6 +5176,7 @@ export {
|
|
|
5065
5176
|
PlanUpdateBlock,
|
|
5066
5177
|
ReplayBar,
|
|
5067
5178
|
ReplayMismatchPrompt,
|
|
5179
|
+
SessionMemoryToggle,
|
|
5068
5180
|
WhatIfUserBubble,
|
|
5069
5181
|
classifyAgentComputerLaunchOutcome,
|
|
5070
5182
|
collectMemoryRefs,
|