@ash-cloud/ash-ui 0.2.4 → 0.2.6
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/dist/index.cjs +209 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -5
- package/dist/index.d.ts +72 -5
- package/dist/index.js +206 -14
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.cjs +5 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +26 -2
- package/dist/types.d.ts +26 -2
- package/dist/types.js +5 -2
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1269,6 +1269,128 @@ function JsonDisplay({ value, maxHeight, className }) {
|
|
|
1269
1269
|
const formatted = JSON.stringify(value, null, 2);
|
|
1270
1270
|
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { maxHeight, className, children: formatted });
|
|
1271
1271
|
}
|
|
1272
|
+
var ChatDisplayModeContext = react.createContext(null);
|
|
1273
|
+
function useChatDisplayMode() {
|
|
1274
|
+
const ctx = react.useContext(ChatDisplayModeContext);
|
|
1275
|
+
if (!ctx) {
|
|
1276
|
+
return {
|
|
1277
|
+
mode: "debug",
|
|
1278
|
+
toggleMode: () => {
|
|
1279
|
+
},
|
|
1280
|
+
setMode: () => {
|
|
1281
|
+
},
|
|
1282
|
+
toolDescriptions: {},
|
|
1283
|
+
getUserDescription: () => null
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
return ctx;
|
|
1287
|
+
}
|
|
1288
|
+
function ChatDisplayModeProvider({
|
|
1289
|
+
children,
|
|
1290
|
+
defaultMode = "user",
|
|
1291
|
+
storageKey = "ash-display-mode",
|
|
1292
|
+
toolDescriptions = {}
|
|
1293
|
+
}) {
|
|
1294
|
+
const [mode, setModeState] = react.useState(() => {
|
|
1295
|
+
if (typeof window !== "undefined") {
|
|
1296
|
+
const stored = localStorage.getItem(storageKey);
|
|
1297
|
+
if (stored === "user" || stored === "debug") return stored;
|
|
1298
|
+
}
|
|
1299
|
+
return defaultMode;
|
|
1300
|
+
});
|
|
1301
|
+
react.useEffect(() => {
|
|
1302
|
+
if (typeof window !== "undefined") {
|
|
1303
|
+
localStorage.setItem(storageKey, mode);
|
|
1304
|
+
}
|
|
1305
|
+
}, [mode, storageKey]);
|
|
1306
|
+
const toggleMode = () => setModeState((m) => m === "user" ? "debug" : "user");
|
|
1307
|
+
const setMode = (m) => setModeState(m);
|
|
1308
|
+
const getUserDescription = (toolName, input) => {
|
|
1309
|
+
if (toolDescriptions[toolName]) {
|
|
1310
|
+
const desc = toolDescriptions[toolName];
|
|
1311
|
+
return typeof desc === "function" ? desc(input) : desc;
|
|
1312
|
+
}
|
|
1313
|
+
for (const [pattern, desc] of Object.entries(toolDescriptions)) {
|
|
1314
|
+
if (toolName.includes(pattern)) {
|
|
1315
|
+
return typeof desc === "function" ? desc(input) : desc;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
return null;
|
|
1319
|
+
};
|
|
1320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1321
|
+
ChatDisplayModeContext.Provider,
|
|
1322
|
+
{
|
|
1323
|
+
value: {
|
|
1324
|
+
mode,
|
|
1325
|
+
toggleMode,
|
|
1326
|
+
setMode,
|
|
1327
|
+
toolDescriptions,
|
|
1328
|
+
getUserDescription
|
|
1329
|
+
},
|
|
1330
|
+
children
|
|
1331
|
+
}
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
function DisplayModeToggle({ className }) {
|
|
1335
|
+
const { mode, toggleMode } = useChatDisplayMode();
|
|
1336
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1337
|
+
"button",
|
|
1338
|
+
{
|
|
1339
|
+
onClick: toggleMode,
|
|
1340
|
+
className: cn("ash-display-mode-toggle", className),
|
|
1341
|
+
title: mode === "user" ? "Switch to debug mode" : "Switch to user mode",
|
|
1342
|
+
children: [
|
|
1343
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ash-display-mode-icon", children: mode === "user" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1344
|
+
"svg",
|
|
1345
|
+
{
|
|
1346
|
+
className: "w-4 h-4",
|
|
1347
|
+
fill: "none",
|
|
1348
|
+
stroke: "currentColor",
|
|
1349
|
+
viewBox: "0 0 24 24",
|
|
1350
|
+
children: [
|
|
1351
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1352
|
+
"path",
|
|
1353
|
+
{
|
|
1354
|
+
strokeLinecap: "round",
|
|
1355
|
+
strokeLinejoin: "round",
|
|
1356
|
+
strokeWidth: 2,
|
|
1357
|
+
d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
|
1358
|
+
}
|
|
1359
|
+
),
|
|
1360
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1361
|
+
"path",
|
|
1362
|
+
{
|
|
1363
|
+
strokeLinecap: "round",
|
|
1364
|
+
strokeLinejoin: "round",
|
|
1365
|
+
strokeWidth: 2,
|
|
1366
|
+
d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
|
|
1367
|
+
}
|
|
1368
|
+
)
|
|
1369
|
+
]
|
|
1370
|
+
}
|
|
1371
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1372
|
+
"svg",
|
|
1373
|
+
{
|
|
1374
|
+
className: "w-4 h-4",
|
|
1375
|
+
fill: "none",
|
|
1376
|
+
stroke: "currentColor",
|
|
1377
|
+
viewBox: "0 0 24 24",
|
|
1378
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1379
|
+
"path",
|
|
1380
|
+
{
|
|
1381
|
+
strokeLinecap: "round",
|
|
1382
|
+
strokeLinejoin: "round",
|
|
1383
|
+
strokeWidth: 2,
|
|
1384
|
+
d: "M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
|
|
1385
|
+
}
|
|
1386
|
+
)
|
|
1387
|
+
}
|
|
1388
|
+
) }),
|
|
1389
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ash-display-mode-label", children: mode === "user" ? "User" : "Debug" })
|
|
1390
|
+
]
|
|
1391
|
+
}
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1272
1394
|
var ToolContext = react.createContext(null);
|
|
1273
1395
|
function useTool() {
|
|
1274
1396
|
const context = react.useContext(ToolContext);
|
|
@@ -1285,6 +1407,7 @@ function Tool({
|
|
|
1285
1407
|
variant = "default"
|
|
1286
1408
|
}) {
|
|
1287
1409
|
const [isExpanded, setIsExpanded] = react.useState(defaultExpanded);
|
|
1410
|
+
const { mode, getUserDescription } = useChatDisplayMode();
|
|
1288
1411
|
const toggleExpanded = () => setIsExpanded((prev) => !prev);
|
|
1289
1412
|
const contextValue = {
|
|
1290
1413
|
toolInvocation,
|
|
@@ -1296,6 +1419,27 @@ function Tool({
|
|
|
1296
1419
|
const isErrorResult = Boolean(
|
|
1297
1420
|
toolInvocation.result && typeof toolInvocation.result === "object" && "error" in toolInvocation.result
|
|
1298
1421
|
);
|
|
1422
|
+
if (mode === "user") {
|
|
1423
|
+
const userDesc = getUserDescription(toolInvocation.toolName, toolInvocation.args) || formatToolName(toolInvocation.toolName);
|
|
1424
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1425
|
+
"div",
|
|
1426
|
+
{
|
|
1427
|
+
className: cn(
|
|
1428
|
+
"ash-tool ash-tool-user-mode",
|
|
1429
|
+
"flex items-center gap-2 px-3 py-1.5",
|
|
1430
|
+
"text-[var(--ash-font-size-xs,11px)]",
|
|
1431
|
+
"text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
|
|
1432
|
+
className
|
|
1433
|
+
),
|
|
1434
|
+
"data-tool-name": toolInvocation.toolName,
|
|
1435
|
+
"data-tool-state": toolInvocation.state,
|
|
1436
|
+
children: [
|
|
1437
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIndicator, { status, size: "xs" }),
|
|
1438
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: userDesc })
|
|
1439
|
+
]
|
|
1440
|
+
}
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1299
1443
|
return /* @__PURE__ */ jsxRuntime.jsx(ToolContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1300
1444
|
"div",
|
|
1301
1445
|
{
|
|
@@ -3130,6 +3274,9 @@ function isErrorEntry(entry) {
|
|
|
3130
3274
|
function isWidgetEntry(entry) {
|
|
3131
3275
|
return entry.type === "widget";
|
|
3132
3276
|
}
|
|
3277
|
+
function isSystemMessage(entry) {
|
|
3278
|
+
return entry.type === "system_message";
|
|
3279
|
+
}
|
|
3133
3280
|
var DEFAULT_STYLE_CONFIG = {
|
|
3134
3281
|
userVariant: "bubble",
|
|
3135
3282
|
assistantVariant: "bubble",
|
|
@@ -3263,7 +3410,7 @@ function messageToNormalizedEntry(message) {
|
|
|
3263
3410
|
return {
|
|
3264
3411
|
id,
|
|
3265
3412
|
timestamp,
|
|
3266
|
-
entryType: { type: "
|
|
3413
|
+
entryType: { type: "system_message" },
|
|
3267
3414
|
content
|
|
3268
3415
|
};
|
|
3269
3416
|
}
|
|
@@ -3666,6 +3813,8 @@ function useAgentChat(options) {
|
|
|
3666
3813
|
onSessionEnd,
|
|
3667
3814
|
onError,
|
|
3668
3815
|
onSandboxLog,
|
|
3816
|
+
canUseTool,
|
|
3817
|
+
resolveToolPermission,
|
|
3669
3818
|
onReconnect,
|
|
3670
3819
|
maxReconnectAttempts = 3,
|
|
3671
3820
|
reconnectBaseDelay = 1e3,
|
|
@@ -3699,6 +3848,23 @@ function useAgentChat(options) {
|
|
|
3699
3848
|
const emitStreamingEntries = react.useCallback((newEntries) => {
|
|
3700
3849
|
setStreamingEntries([...newEntries]);
|
|
3701
3850
|
}, []);
|
|
3851
|
+
const handleToolPermission = react.useCallback(async (event) => {
|
|
3852
|
+
if (event.type !== "tool_permission") return;
|
|
3853
|
+
if (!canUseTool) return;
|
|
3854
|
+
if (!event.requestId || !event.sessionId || !event.toolName) return;
|
|
3855
|
+
const request = {
|
|
3856
|
+
requestId: event.requestId,
|
|
3857
|
+
sessionId: event.sessionId,
|
|
3858
|
+
toolName: event.toolName,
|
|
3859
|
+
input: event.input
|
|
3860
|
+
};
|
|
3861
|
+
const allow = await canUseTool(request);
|
|
3862
|
+
if (!resolveToolPermission) {
|
|
3863
|
+
console.warn("[useAgentChat] resolveToolPermission not provided for tool permission response");
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
await resolveToolPermission(request, allow);
|
|
3867
|
+
}, [canUseTool, resolveToolPermission]);
|
|
3702
3868
|
const createTextEntry = react.useCallback((id, content) => ({
|
|
3703
3869
|
id,
|
|
3704
3870
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3857,6 +4023,7 @@ function useAgentChat(options) {
|
|
|
3857
4023
|
for await (const event of stream) {
|
|
3858
4024
|
if (controller.signal.aborted) break;
|
|
3859
4025
|
eventCountRef.current++;
|
|
4026
|
+
await handleToolPermission(event);
|
|
3860
4027
|
localStreamingEntries = processEvent(event, localStreamingEntries);
|
|
3861
4028
|
emitStreamingEntries(localStreamingEntries);
|
|
3862
4029
|
if (event.type === "complete" || event.type === "session_end" || event.type === "error") {
|
|
@@ -3890,9 +4057,10 @@ function useAgentChat(options) {
|
|
|
3890
4057
|
}
|
|
3891
4058
|
return false;
|
|
3892
4059
|
}
|
|
3893
|
-
}, [subscribeToSession, maxReconnectAttempts, reconnectBaseDelay, onReconnect, processEvent, emitStreamingEntries]);
|
|
3894
|
-
const send = react.useCallback(async (prompt) => {
|
|
4060
|
+
}, [subscribeToSession, maxReconnectAttempts, reconnectBaseDelay, onReconnect, processEvent, emitStreamingEntries, handleToolPermission]);
|
|
4061
|
+
const send = react.useCallback(async (prompt, sendOptions) => {
|
|
3895
4062
|
if (isStreaming) return;
|
|
4063
|
+
const role = sendOptions?.role ?? "user";
|
|
3896
4064
|
let finalPrompt = prompt;
|
|
3897
4065
|
let additionalMetadata = {};
|
|
3898
4066
|
let additionalContext;
|
|
@@ -3938,13 +4106,15 @@ function useAgentChat(options) {
|
|
|
3938
4106
|
setError(null);
|
|
3939
4107
|
reconnectAttemptsRef.current = 0;
|
|
3940
4108
|
eventCountRef.current = 0;
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
4109
|
+
if (role !== "system") {
|
|
4110
|
+
const userEntry = {
|
|
4111
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
4112
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4113
|
+
entryType: { type: "user_message" },
|
|
4114
|
+
content: prompt
|
|
4115
|
+
};
|
|
4116
|
+
setHistoryEntries((prev) => [...prev, userEntry]);
|
|
4117
|
+
}
|
|
3948
4118
|
resetStreamingState();
|
|
3949
4119
|
const controller = new AbortController();
|
|
3950
4120
|
abortControllerRef.current = controller;
|
|
@@ -3954,7 +4124,8 @@ function useAgentChat(options) {
|
|
|
3954
4124
|
const stream = createStream(finalPrompt, sessionId || void 0, {
|
|
3955
4125
|
signal: controller.signal,
|
|
3956
4126
|
metadata: Object.keys(additionalMetadata).length > 0 ? additionalMetadata : void 0,
|
|
3957
|
-
sessionContext: additionalContext
|
|
4127
|
+
sessionContext: additionalContext,
|
|
4128
|
+
role: role !== "user" ? role : void 0
|
|
3958
4129
|
});
|
|
3959
4130
|
for await (const event of stream) {
|
|
3960
4131
|
if (controller.signal.aborted) break;
|
|
@@ -3969,6 +4140,7 @@ function useAgentChat(options) {
|
|
|
3969
4140
|
console.error("[useAgentChat] onEvent error:", err);
|
|
3970
4141
|
}
|
|
3971
4142
|
}
|
|
4143
|
+
await handleToolPermission(event);
|
|
3972
4144
|
let processedEvent = event;
|
|
3973
4145
|
if (middleware?.length) {
|
|
3974
4146
|
processedEvent = await applyEventMiddleware(middleware, event);
|
|
@@ -4018,7 +4190,7 @@ function useAgentChat(options) {
|
|
|
4018
4190
|
abortControllerRef.current = null;
|
|
4019
4191
|
resetStreamingState();
|
|
4020
4192
|
}
|
|
4021
|
-
}, [isStreaming, sessionId, historyEntries, streamingEntries, createStream, subscribeToSession, processEvent, emitStreamingEntries, resetStreamingState, onError, attemptReconnect, onBeforeSend, onEvent, middleware]);
|
|
4193
|
+
}, [isStreaming, sessionId, historyEntries, streamingEntries, createStream, subscribeToSession, processEvent, emitStreamingEntries, resetStreamingState, onError, attemptReconnect, onBeforeSend, onEvent, middleware, handleToolPermission]);
|
|
4022
4194
|
const stop = react.useCallback(() => {
|
|
4023
4195
|
reconnectAttemptsRef.current = maxReconnectAttempts + 1;
|
|
4024
4196
|
setIsReconnecting(false);
|
|
@@ -4069,6 +4241,8 @@ function useChat(options) {
|
|
|
4069
4241
|
initialSessionId,
|
|
4070
4242
|
initialMessages = [],
|
|
4071
4243
|
onToolCall,
|
|
4244
|
+
canUseTool,
|
|
4245
|
+
resolveToolPermission,
|
|
4072
4246
|
onFinish,
|
|
4073
4247
|
onError,
|
|
4074
4248
|
onSessionStart,
|
|
@@ -4103,6 +4277,23 @@ function useChat(options) {
|
|
|
4103
4277
|
return prev;
|
|
4104
4278
|
});
|
|
4105
4279
|
}, []);
|
|
4280
|
+
const handleToolPermission = react.useCallback(async (event) => {
|
|
4281
|
+
if (event.type !== "tool_permission") return;
|
|
4282
|
+
if (!canUseTool) return;
|
|
4283
|
+
if (!event.requestId || !event.sessionId || !event.toolName) return;
|
|
4284
|
+
const request = {
|
|
4285
|
+
requestId: event.requestId,
|
|
4286
|
+
sessionId: event.sessionId,
|
|
4287
|
+
toolName: event.toolName,
|
|
4288
|
+
input: event.input
|
|
4289
|
+
};
|
|
4290
|
+
const allow = await canUseTool(request);
|
|
4291
|
+
if (!resolveToolPermission) {
|
|
4292
|
+
console.warn("[useChat] resolveToolPermission not provided for tool permission response");
|
|
4293
|
+
return;
|
|
4294
|
+
}
|
|
4295
|
+
await resolveToolPermission(request, allow);
|
|
4296
|
+
}, [canUseTool, resolveToolPermission]);
|
|
4106
4297
|
const processEvent = react.useCallback((event) => {
|
|
4107
4298
|
switch (event.type) {
|
|
4108
4299
|
case "session_start":
|
|
@@ -4222,6 +4413,7 @@ function useChat(options) {
|
|
|
4222
4413
|
const stream = createStream(finalPrompt, sessionIdRef.current || void 0, streamOptions);
|
|
4223
4414
|
for await (const event of stream) {
|
|
4224
4415
|
if (controller.signal.aborted) break;
|
|
4416
|
+
await handleToolPermission(event);
|
|
4225
4417
|
let processedEvent = event;
|
|
4226
4418
|
if (middleware?.length) {
|
|
4227
4419
|
processedEvent = await applyEventMiddleware(middleware, event);
|
|
@@ -4251,7 +4443,7 @@ function useChat(options) {
|
|
|
4251
4443
|
abortControllerRef.current = null;
|
|
4252
4444
|
currentAssistantMessageRef.current = null;
|
|
4253
4445
|
}
|
|
4254
|
-
}, [isLoading, createStream, processEvent, middleware, onError]);
|
|
4446
|
+
}, [isLoading, createStream, processEvent, middleware, onError, handleToolPermission]);
|
|
4255
4447
|
const stop = react.useCallback(() => {
|
|
4256
4448
|
reconnectAttemptsRef.current = maxReconnectAttempts + 1;
|
|
4257
4449
|
setIsReconnecting(false);
|
|
@@ -4392,6 +4584,7 @@ exports.Attachments = Attachments;
|
|
|
4392
4584
|
exports.BotIcon = BotIcon;
|
|
4393
4585
|
exports.BrainIcon = BrainIcon;
|
|
4394
4586
|
exports.BugIcon = BugIcon;
|
|
4587
|
+
exports.ChatDisplayModeProvider = ChatDisplayModeProvider;
|
|
4395
4588
|
exports.CheckCircleIcon = CheckCircleIcon;
|
|
4396
4589
|
exports.CheckIcon = CheckIcon;
|
|
4397
4590
|
exports.ChevronDownIcon = ChevronDownIcon;
|
|
@@ -4410,6 +4603,7 @@ exports.ConversationLoadMore = ConversationLoadMore;
|
|
|
4410
4603
|
exports.ConversationScrollButton = ConversationScrollButton;
|
|
4411
4604
|
exports.CopyIcon = CopyIcon;
|
|
4412
4605
|
exports.DEFAULT_STYLE_CONFIG = DEFAULT_STYLE_CONFIG;
|
|
4606
|
+
exports.DisplayModeToggle = DisplayModeToggle;
|
|
4413
4607
|
exports.EditIcon = EditIcon;
|
|
4414
4608
|
exports.EnvVarsPanel = EnvVarsPanel;
|
|
4415
4609
|
exports.ErrorIcon = ErrorIcon;
|
|
@@ -4503,6 +4697,7 @@ exports.isGenericToolAction = isGenericToolAction;
|
|
|
4503
4697
|
exports.isGlobAction = isGlobAction;
|
|
4504
4698
|
exports.isMcpToolAction = isMcpToolAction;
|
|
4505
4699
|
exports.isSearchAction = isSearchAction;
|
|
4700
|
+
exports.isSystemMessage = isSystemMessage;
|
|
4506
4701
|
exports.isTodoWriteAction = isTodoWriteAction;
|
|
4507
4702
|
exports.isToolCallEntry = isToolCallEntry;
|
|
4508
4703
|
exports.isWebFetchAction = isWebFetchAction;
|
|
@@ -4529,6 +4724,7 @@ exports.updateToolCallWithResult = updateToolCallWithResult;
|
|
|
4529
4724
|
exports.useAgentChat = useAgentChat;
|
|
4530
4725
|
exports.useAttachment = useAttachment;
|
|
4531
4726
|
exports.useChat = useChat;
|
|
4727
|
+
exports.useChatDisplayMode = useChatDisplayMode;
|
|
4532
4728
|
exports.useConversation = useConversation;
|
|
4533
4729
|
exports.useFileUpload = useFileUpload;
|
|
4534
4730
|
exports.useLongTextConversion = useLongTextConversion;
|