@cntyclub/agent-react 0.2.0 → 0.4.0
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/api/schema.d.ts +347 -0
- package/dist/api/schema.d.ts.map +1 -0
- package/dist/api-client.d.ts +30 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/components/agent-panel.d.ts +20 -0
- package/dist/components/agent-panel.d.ts.map +1 -0
- package/dist/components/agent-widget.d.ts +23 -0
- package/dist/components/agent-widget.d.ts.map +1 -0
- package/dist/components/message-item.d.ts +7 -0
- package/dist/components/message-item.d.ts.map +1 -0
- package/dist/components/tool-approval-card.d.ts +14 -0
- package/dist/components/tool-approval-card.d.ts.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/index.d.ts +10 -547
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +229 -96
- package/dist/index.js.map +1 -1
- package/dist/table-format.d.ts +29 -0
- package/dist/table-format.d.ts.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/use-agent-chat.d.ts +26 -0
- package/dist/use-agent-chat.d.ts.map +1 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ChatMessage, ChatMessageBubble, Markdown, DataTablePaged, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Button, Spinner, Tooltip, TooltipTrigger, TooltipContent, Chat, ChatMessages, ChatTypingIndicator, cn, ChatInput, useMediaQuery, TooltipProvider, Fab } from '@cntyclub/ui-react';
|
|
2
|
-
import { WrenchIcon,
|
|
1
|
+
import { ChatMessage, ChatMessageBubble, Markdown, ChatToolChip, DataTablePaged, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Button, Spinner, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Tooltip, TooltipTrigger, TooltipContent, Chat, ChatMessages, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, ChatTypingIndicator, cn, ChatInput, useMediaQuery, TooltipProvider, Fab } from '@cntyclub/ui-react';
|
|
2
|
+
import { WrenchIcon, CheckIcon, ShieldAlertIcon, HistoryIcon, SquarePenIcon, Minimize2Icon, Maximize2Icon, XIcon, Trash2Icon, SparklesIcon } from 'lucide-react';
|
|
3
3
|
import * as React2 from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -77,6 +77,144 @@ var AgentApiClient = class {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
|
+
var NOISE_KEYS = /* @__PURE__ */ new Set([
|
|
81
|
+
"id",
|
|
82
|
+
"pk",
|
|
83
|
+
"uuid",
|
|
84
|
+
"slug",
|
|
85
|
+
"object_id",
|
|
86
|
+
"external_id",
|
|
87
|
+
"client_id",
|
|
88
|
+
"content_type",
|
|
89
|
+
"provider_call_id",
|
|
90
|
+
"tool_call_id"
|
|
91
|
+
]);
|
|
92
|
+
var NOISE_PATTERNS = [
|
|
93
|
+
/_id$/i,
|
|
94
|
+
/_ids$/i,
|
|
95
|
+
/_key$/i,
|
|
96
|
+
/_hash$/i,
|
|
97
|
+
/embedding/i,
|
|
98
|
+
/vector/i,
|
|
99
|
+
/password/i,
|
|
100
|
+
/secret/i,
|
|
101
|
+
/(^|_)token(_|$)/i
|
|
102
|
+
];
|
|
103
|
+
var IMAGE_KEY = /(image|logo|avatar|photo|picture|icon|thumbnail|banner|cover|headshot)/i;
|
|
104
|
+
var IMAGE_EXT = /\.(png|jpe?g|gif|webp|svg|avif)(\?|$)/i;
|
|
105
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
106
|
+
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(T|$)/;
|
|
107
|
+
var URL_RE = /^https?:\/\//i;
|
|
108
|
+
var PRIORITY_KEYS = ["name", "title", "label", "full_name", "email"];
|
|
109
|
+
var LABEL_KEYS = ["name", "title", "label", "full_name", "email", "code"];
|
|
110
|
+
function isUuid(value) {
|
|
111
|
+
return typeof value === "string" && UUID_RE.test(value);
|
|
112
|
+
}
|
|
113
|
+
function humanize(key) {
|
|
114
|
+
const text = key.replace(/_/g, " ").trim();
|
|
115
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
116
|
+
}
|
|
117
|
+
function isNoiseColumn(key, rows) {
|
|
118
|
+
if (NOISE_KEYS.has(key.toLowerCase())) return true;
|
|
119
|
+
if (NOISE_PATTERNS.some((pattern) => pattern.test(key))) return true;
|
|
120
|
+
const values = rows.map((row) => row[key]).filter((value) => value !== null && value !== void 0 && value !== "");
|
|
121
|
+
return values.length > 0 && values.every(isUuid);
|
|
122
|
+
}
|
|
123
|
+
function pickLabel(obj) {
|
|
124
|
+
for (const key of LABEL_KEYS) {
|
|
125
|
+
const value = obj[key];
|
|
126
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
127
|
+
if (typeof value === "number") return String(value);
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
function formatObject(obj) {
|
|
132
|
+
const label = pickLabel(obj);
|
|
133
|
+
if (label) return label;
|
|
134
|
+
const parts = [];
|
|
135
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
136
|
+
if (value === null || value === void 0 || value === "") continue;
|
|
137
|
+
if (typeof value === "object") continue;
|
|
138
|
+
parts.push(`${humanize(key)} ${value}`);
|
|
139
|
+
if (parts.length >= 6) break;
|
|
140
|
+
}
|
|
141
|
+
return parts.join(" \xB7 ") || "\u2014";
|
|
142
|
+
}
|
|
143
|
+
function formatArray(arr) {
|
|
144
|
+
const items = arr.map((item) => {
|
|
145
|
+
if (item === null || item === void 0) return "";
|
|
146
|
+
if (Array.isArray(item)) return "";
|
|
147
|
+
if (typeof item === "object") return pickLabel(item) ?? "";
|
|
148
|
+
return String(item);
|
|
149
|
+
}).filter(Boolean);
|
|
150
|
+
if (items.length === 0) return "\u2014";
|
|
151
|
+
const shown = items.slice(0, 8);
|
|
152
|
+
const extra = items.length - shown.length;
|
|
153
|
+
return shown.join(", ") + (extra > 0 ? ` +${extra} more` : "");
|
|
154
|
+
}
|
|
155
|
+
function renderScalar(key, value) {
|
|
156
|
+
if (typeof value !== "string") return value;
|
|
157
|
+
const text = value.trim();
|
|
158
|
+
if (URL_RE.test(text) && (IMAGE_EXT.test(text) || IMAGE_KEY.test(key))) {
|
|
159
|
+
return /* @__PURE__ */ jsx(
|
|
160
|
+
"img",
|
|
161
|
+
{
|
|
162
|
+
alt: humanize(key),
|
|
163
|
+
className: "h-9 w-9 rounded-md border border-border object-cover",
|
|
164
|
+
loading: "lazy",
|
|
165
|
+
src: text
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (URL_RE.test(text)) {
|
|
170
|
+
let label = text;
|
|
171
|
+
try {
|
|
172
|
+
label = new URL(text).hostname.replace(/^www\./, "");
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
return /* @__PURE__ */ jsx(
|
|
176
|
+
"a",
|
|
177
|
+
{
|
|
178
|
+
className: "text-primary underline underline-offset-2",
|
|
179
|
+
href: text,
|
|
180
|
+
rel: "noreferrer",
|
|
181
|
+
target: "_blank",
|
|
182
|
+
children: label
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (ISO_DATE_RE.test(text)) {
|
|
187
|
+
const date = new Date(text);
|
|
188
|
+
if (!Number.isNaN(date.getTime())) return date.toLocaleDateString();
|
|
189
|
+
}
|
|
190
|
+
return text;
|
|
191
|
+
}
|
|
192
|
+
function formatCellValue(key, value) {
|
|
193
|
+
if (value === null || value === void 0 || value === "") return value;
|
|
194
|
+
if (Array.isArray(value)) return formatArray(value);
|
|
195
|
+
if (typeof value === "object") return formatObject(value);
|
|
196
|
+
return renderScalar(key, value);
|
|
197
|
+
}
|
|
198
|
+
function toDisplayTable(block) {
|
|
199
|
+
const rows = block.rows ?? [];
|
|
200
|
+
const kept = (block.columns ?? []).filter((key) => !isNoiseColumn(key, rows));
|
|
201
|
+
const columnKeys = kept.length > 0 ? kept : block.columns ?? [];
|
|
202
|
+
const ordered = [...columnKeys].sort((a, b) => {
|
|
203
|
+
const ra = PRIORITY_KEYS.indexOf(a.toLowerCase());
|
|
204
|
+
const rb = PRIORITY_KEYS.indexOf(b.toLowerCase());
|
|
205
|
+
const pa = ra === -1 ? PRIORITY_KEYS.length : ra;
|
|
206
|
+
const pb = rb === -1 ? PRIORITY_KEYS.length : rb;
|
|
207
|
+
if (pa !== pb) return pa - pb;
|
|
208
|
+
return columnKeys.indexOf(a) - columnKeys.indexOf(b);
|
|
209
|
+
});
|
|
210
|
+
const columns = ordered.map((key) => ({ key, label: humanize(key) }));
|
|
211
|
+
const displayRows = rows.map((row) => {
|
|
212
|
+
const out = {};
|
|
213
|
+
for (const key of ordered) out[key] = formatCellValue(key, row[key]);
|
|
214
|
+
return out;
|
|
215
|
+
});
|
|
216
|
+
return { columns, rows: displayRows };
|
|
217
|
+
}
|
|
80
218
|
function humanizeToolName(toolName) {
|
|
81
219
|
return toolName.replace(/^[a-z]+_/, "").replaceAll("_", " ");
|
|
82
220
|
}
|
|
@@ -89,32 +227,26 @@ function MessageItem({ message }) {
|
|
|
89
227
|
if (!message.content && requestedTools.length === 0) return null;
|
|
90
228
|
return /* @__PURE__ */ jsxs(ChatMessage, { from: "assistant", children: [
|
|
91
229
|
message.content ? /* @__PURE__ */ jsx(ChatMessageBubble, { from: "assistant", children: /* @__PURE__ */ jsx(Markdown, { children: message.content }) }) : null,
|
|
92
|
-
requestedTools.map((toolCall) => /* @__PURE__ */ jsxs(
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
/* @__PURE__ */ jsx(WrenchIcon, { className: "size-3" }),
|
|
98
|
-
"Using ",
|
|
99
|
-
humanizeToolName(toolCall.name ?? "tool"),
|
|
100
|
-
"\u2026"
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
toolCall.id ?? toolCall.name
|
|
104
|
-
))
|
|
230
|
+
requestedTools.map((toolCall) => /* @__PURE__ */ jsxs(ChatToolChip, { icon: /* @__PURE__ */ jsx(WrenchIcon, {}), children: [
|
|
231
|
+
"Using ",
|
|
232
|
+
humanizeToolName(toolCall.name ?? "tool"),
|
|
233
|
+
"\u2026"
|
|
234
|
+
] }, toolCall.id ?? toolCall.name))
|
|
105
235
|
] });
|
|
106
236
|
}
|
|
107
237
|
const tableBlocks = (message.blocks ?? []).filter((block) => block.type === "table");
|
|
108
|
-
return /* @__PURE__ */ jsx(ChatMessage, { from: "assistant", children: tableBlocks.length > 0 ? tableBlocks.map((block, index) =>
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
238
|
+
return /* @__PURE__ */ jsx(ChatMessage, { from: "assistant", children: tableBlocks.length > 0 ? tableBlocks.map((block, index) => {
|
|
239
|
+
const { columns, rows } = toDisplayTable(block);
|
|
240
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full max-w-full", children: /* @__PURE__ */ jsx(
|
|
241
|
+
DataTablePaged,
|
|
242
|
+
{
|
|
243
|
+
columns,
|
|
244
|
+
pageSize: 8,
|
|
245
|
+
rows,
|
|
246
|
+
totalCount: typeof block.pagination?.count === "number" ? block.pagination.count : block.row_count
|
|
247
|
+
}
|
|
248
|
+
) }, `${message.id}-${index}`);
|
|
249
|
+
}) : /* @__PURE__ */ jsxs(ChatToolChip, { icon: /* @__PURE__ */ jsx(CheckIcon, {}), children: [
|
|
118
250
|
humanizeToolName(message.tool_name ?? "tool"),
|
|
119
251
|
" finished"
|
|
120
252
|
] }) });
|
|
@@ -205,72 +337,74 @@ function AgentPanel({
|
|
|
205
337
|
),
|
|
206
338
|
"data-slot": "agent-panel",
|
|
207
339
|
children: [
|
|
208
|
-
/* @__PURE__ */ jsxs(
|
|
209
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
210
|
-
/* @__PURE__ */ jsx(
|
|
211
|
-
/* @__PURE__ */ jsxs(
|
|
340
|
+
/* @__PURE__ */ jsxs(ChatHeader, { children: [
|
|
341
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
|
|
342
|
+
/* @__PURE__ */ jsx(ChatHeaderAvatar, {}),
|
|
343
|
+
/* @__PURE__ */ jsxs(ChatHeaderTitle, { children: [
|
|
212
344
|
/* @__PURE__ */ jsx("div", { className: "truncate font-medium text-sm", children: agentName }),
|
|
213
345
|
config.tagline ? /* @__PURE__ */ jsx("div", { className: "truncate text-muted-foreground text-xs", children: config.tagline }) : null
|
|
214
346
|
] })
|
|
215
347
|
] }),
|
|
216
|
-
/* @__PURE__ */ jsxs(
|
|
217
|
-
/* @__PURE__ */
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
/* @__PURE__ */
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
348
|
+
/* @__PURE__ */ jsxs(ChatHeaderActions, { children: [
|
|
349
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
350
|
+
/* @__PURE__ */ jsx(
|
|
351
|
+
TooltipTrigger,
|
|
352
|
+
{
|
|
353
|
+
render: /* @__PURE__ */ jsx(
|
|
354
|
+
Button,
|
|
355
|
+
{
|
|
356
|
+
"aria-label": "Conversation history",
|
|
357
|
+
onClick: view === "history" ? () => setView("chat") : openHistory,
|
|
358
|
+
size: "icon-sm",
|
|
359
|
+
variant: "ghost",
|
|
360
|
+
children: /* @__PURE__ */ jsx(HistoryIcon, {})
|
|
361
|
+
}
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
),
|
|
365
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: "History" })
|
|
366
|
+
] }),
|
|
367
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
368
|
+
/* @__PURE__ */ jsx(
|
|
369
|
+
TooltipTrigger,
|
|
370
|
+
{
|
|
371
|
+
render: /* @__PURE__ */ jsx(
|
|
372
|
+
Button,
|
|
373
|
+
{
|
|
374
|
+
"aria-label": "New chat",
|
|
375
|
+
onClick: () => {
|
|
376
|
+
chat.newChat();
|
|
377
|
+
setView("chat");
|
|
378
|
+
},
|
|
379
|
+
size: "icon-sm",
|
|
380
|
+
variant: "ghost",
|
|
381
|
+
children: /* @__PURE__ */ jsx(SquarePenIcon, {})
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
),
|
|
386
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: "New chat" })
|
|
387
|
+
] }),
|
|
388
|
+
canToggleAgentMode ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
389
|
+
/* @__PURE__ */ jsx(
|
|
390
|
+
TooltipTrigger,
|
|
391
|
+
{
|
|
392
|
+
render: /* @__PURE__ */ jsx(
|
|
393
|
+
Button,
|
|
394
|
+
{
|
|
395
|
+
"aria-label": agentMode ? "Exit Agent Mode" : "Enter Agent Mode",
|
|
396
|
+
onClick: onToggleAgentMode,
|
|
397
|
+
size: "icon-sm",
|
|
398
|
+
variant: "ghost",
|
|
399
|
+
children: agentMode ? /* @__PURE__ */ jsx(Minimize2Icon, {}) : /* @__PURE__ */ jsx(Maximize2Icon, {})
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
),
|
|
404
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: agentMode ? "Exit Agent Mode" : "Agent Mode" })
|
|
405
|
+
] }) : null,
|
|
406
|
+
/* @__PURE__ */ jsx(Button, { "aria-label": "Close", onClick: onClose, size: "icon-sm", variant: "ghost", children: /* @__PURE__ */ jsx(XIcon, {}) })
|
|
407
|
+
] })
|
|
274
408
|
] }),
|
|
275
409
|
view === "history" ? /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-1 overflow-y-auto p-2", children: chat.conversations.length === 0 ? /* @__PURE__ */ jsx("p", { className: "p-4 text-center text-muted-foreground text-sm", children: "No conversations yet." }) : chat.conversations.map((conversation) => /* @__PURE__ */ jsxs(
|
|
276
410
|
"div",
|
|
@@ -307,22 +441,21 @@ function AgentPanel({
|
|
|
307
441
|
},
|
|
308
442
|
conversation.id
|
|
309
443
|
)) }) : /* @__PURE__ */ jsxs(Chat, { children: [
|
|
310
|
-
/* @__PURE__ */ jsx(ChatMessages, { className: cn(agentMode && "mx-auto w-full max-w-3xl"), children: chat.messages.length === 0 && !chat.sending ? /* @__PURE__ */ jsxs(
|
|
311
|
-
/* @__PURE__ */ jsx(
|
|
444
|
+
/* @__PURE__ */ jsx(ChatMessages, { className: cn(agentMode && "mx-auto w-full max-w-3xl"), children: chat.messages.length === 0 && !chat.sending ? /* @__PURE__ */ jsxs(ChatEmptyState, { children: [
|
|
445
|
+
/* @__PURE__ */ jsx(ChatEmptyStateIcon, {}),
|
|
312
446
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
313
|
-
/* @__PURE__ */ jsxs(
|
|
447
|
+
/* @__PURE__ */ jsxs(ChatEmptyStateTitle, { children: [
|
|
314
448
|
"Hi! I'm ",
|
|
315
449
|
agentName,
|
|
316
450
|
"."
|
|
317
451
|
] }),
|
|
318
|
-
/* @__PURE__ */ jsx(
|
|
452
|
+
/* @__PURE__ */ jsx(ChatEmptyStateDescription, { className: "mt-1", children: "Ask me anything about your data \u2014 I can look things up and take actions (with your approval)." })
|
|
319
453
|
] }),
|
|
320
|
-
/* @__PURE__ */ jsx(
|
|
321
|
-
|
|
454
|
+
/* @__PURE__ */ jsx(ChatSuggestions, { children: suggestions.slice(0, 4).map((suggestion, index) => /* @__PURE__ */ jsx(
|
|
455
|
+
ChatSuggestion,
|
|
322
456
|
{
|
|
457
|
+
index,
|
|
323
458
|
onClick: () => handleSubmit(suggestion),
|
|
324
|
-
size: "sm",
|
|
325
|
-
variant: "outline",
|
|
326
459
|
children: suggestion
|
|
327
460
|
},
|
|
328
461
|
suggestion
|
|
@@ -347,7 +480,7 @@ function AgentPanel({
|
|
|
347
480
|
/* @__PURE__ */ jsx(
|
|
348
481
|
ChatInput,
|
|
349
482
|
{
|
|
350
|
-
className: cn(agentMode && "mx-auto w-full max-w-3xl
|
|
483
|
+
className: cn(agentMode && "mx-auto w-full max-w-3xl"),
|
|
351
484
|
disabled: busy || chat.pendingApprovals.length > 0,
|
|
352
485
|
onSubmit: handleSubmit,
|
|
353
486
|
onValueChange: setDraft,
|