@agent-native/core 0.84.28 → 0.84.29
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/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/deploy/build.ts +5 -0
- package/corpus/core/src/server/analytics.ts +29 -7
- package/corpus/core/src/server/ssr-handler.ts +161 -25
- package/corpus/core/src/vite/client.ts +3 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +324 -24
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +11 -0
- package/corpus/templates/analytics/app/i18n-data.ts +110 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.js +3 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +4 -4
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/analytics.d.ts +10 -2
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +26 -5
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +103 -21
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
IconReportAnalytics,
|
|
15
15
|
IconSearch,
|
|
16
16
|
IconArchive,
|
|
17
|
+
IconPin,
|
|
18
|
+
IconPlus,
|
|
17
19
|
IconBuilding,
|
|
18
20
|
IconLock,
|
|
19
21
|
IconLink,
|
|
@@ -38,11 +40,13 @@ import {
|
|
|
38
40
|
useRef,
|
|
39
41
|
useMemo,
|
|
40
42
|
Fragment,
|
|
43
|
+
type FormEvent,
|
|
41
44
|
} from "react";
|
|
42
45
|
import { Link, useLocation, useNavigate } from "react-router";
|
|
43
46
|
import { toast } from "sonner";
|
|
44
47
|
|
|
45
48
|
import { getIdToken } from "@/lib/auth";
|
|
49
|
+
import { ANALYTICS_CHAT_STORAGE_KEY } from "@/lib/chat-handoff";
|
|
46
50
|
import { cn, shortcutModifierLabel } from "@/lib/utils";
|
|
47
51
|
import {
|
|
48
52
|
dashboards,
|
|
@@ -70,9 +74,11 @@ import {
|
|
|
70
74
|
callAction,
|
|
71
75
|
appPath,
|
|
72
76
|
navigateWithAgentChatViewTransition,
|
|
77
|
+
useChatThreads,
|
|
73
78
|
useActionMutation,
|
|
74
79
|
useChangeVersions,
|
|
75
80
|
useT,
|
|
81
|
+
type ChatThreadSummary,
|
|
76
82
|
} from "@agent-native/core/client";
|
|
77
83
|
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
78
84
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
@@ -94,6 +100,7 @@ import {
|
|
|
94
100
|
DropdownMenuSeparator,
|
|
95
101
|
DropdownMenuTrigger,
|
|
96
102
|
} from "@/components/ui/dropdown-menu";
|
|
103
|
+
import { Input } from "@/components/ui/input";
|
|
97
104
|
import {
|
|
98
105
|
Popover,
|
|
99
106
|
PopoverTrigger,
|
|
@@ -1175,6 +1182,296 @@ async function fetchAnalysisDetailForPrefetch(id: string): Promise<unknown> {
|
|
|
1175
1182
|
}
|
|
1176
1183
|
}
|
|
1177
1184
|
|
|
1185
|
+
const ANALYTICS_ACTIVE_THREAD_KEY = `agent-chat-active-thread:${ANALYTICS_CHAT_STORAGE_KEY}`;
|
|
1186
|
+
|
|
1187
|
+
function formatThreadAge(updatedAt: number) {
|
|
1188
|
+
const diffMs = Math.max(0, Date.now() - updatedAt);
|
|
1189
|
+
const minutes = Math.floor(diffMs / 60_000);
|
|
1190
|
+
if (minutes < 1) return "now";
|
|
1191
|
+
if (minutes < 60) return `${minutes}m`;
|
|
1192
|
+
const hours = Math.floor(minutes / 60);
|
|
1193
|
+
if (hours < 24) return `${hours}h`;
|
|
1194
|
+
const days = Math.floor(hours / 24);
|
|
1195
|
+
if (days < 7) return `${days}d`;
|
|
1196
|
+
return new Date(updatedAt).toLocaleDateString([], {
|
|
1197
|
+
month: "short",
|
|
1198
|
+
day: "numeric",
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
function threadTitle(thread: ChatThreadSummary, untitledLabel: string) {
|
|
1203
|
+
return thread.title || thread.preview || untitledLabel;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
function threadUpdatedAt(thread: ChatThreadSummary) {
|
|
1207
|
+
return Number.isFinite(thread.updatedAt)
|
|
1208
|
+
? thread.updatedAt
|
|
1209
|
+
: Number.isFinite(thread.createdAt)
|
|
1210
|
+
? thread.createdAt
|
|
1211
|
+
: 0;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
function compareThreads(a: ChatThreadSummary, b: ChatThreadSummary) {
|
|
1215
|
+
const aPinned = a.pinnedAt ?? 0;
|
|
1216
|
+
const bPinned = b.pinnedAt ?? 0;
|
|
1217
|
+
if (aPinned || bPinned) return bPinned - aPinned;
|
|
1218
|
+
return threadUpdatedAt(b) - threadUpdatedAt(a);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function persistedAnalyticsThreadId() {
|
|
1222
|
+
if (typeof window === "undefined") return null;
|
|
1223
|
+
try {
|
|
1224
|
+
return window.localStorage.getItem(ANALYTICS_ACTIVE_THREAD_KEY);
|
|
1225
|
+
} catch {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
function AnalyticsChatsSection() {
|
|
1231
|
+
const navigate = useNavigate();
|
|
1232
|
+
const t = useT();
|
|
1233
|
+
const {
|
|
1234
|
+
threads,
|
|
1235
|
+
activeThreadId,
|
|
1236
|
+
createThread,
|
|
1237
|
+
switchThread,
|
|
1238
|
+
pinThread,
|
|
1239
|
+
archiveThread,
|
|
1240
|
+
renameThread,
|
|
1241
|
+
refreshThreads,
|
|
1242
|
+
} = useChatThreads(undefined, ANALYTICS_CHAT_STORAGE_KEY, undefined, {
|
|
1243
|
+
autoCreate: false,
|
|
1244
|
+
restoreActiveThread: false,
|
|
1245
|
+
});
|
|
1246
|
+
const [renamingThreadId, setRenamingThreadId] = useState<string | null>(null);
|
|
1247
|
+
const [renameDraft, setRenameDraft] = useState("");
|
|
1248
|
+
const renameInputRef = useRef<HTMLInputElement | null>(null);
|
|
1249
|
+
const committingRenameRef = useRef(false);
|
|
1250
|
+
|
|
1251
|
+
const visibleThreads = useMemo(
|
|
1252
|
+
() =>
|
|
1253
|
+
threads
|
|
1254
|
+
.filter((thread) => thread.messageCount > 0 && !thread.archivedAt)
|
|
1255
|
+
.sort(compareThreads)
|
|
1256
|
+
.slice(0, SIDEBAR_PREVIEW_COUNT),
|
|
1257
|
+
[threads],
|
|
1258
|
+
);
|
|
1259
|
+
|
|
1260
|
+
useEffect(() => {
|
|
1261
|
+
const refresh = () => refreshThreads();
|
|
1262
|
+
const handleRunning = (event: Event) => {
|
|
1263
|
+
const detail = (event as CustomEvent).detail as
|
|
1264
|
+
| { isRunning?: unknown }
|
|
1265
|
+
| undefined;
|
|
1266
|
+
if (typeof detail?.isRunning === "boolean") refreshThreads();
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1269
|
+
window.addEventListener("agent-chat:threads-updated", refresh);
|
|
1270
|
+
window.addEventListener("agentNative.chatRunning", handleRunning);
|
|
1271
|
+
window.addEventListener("focus", refresh);
|
|
1272
|
+
return () => {
|
|
1273
|
+
window.removeEventListener("agent-chat:threads-updated", refresh);
|
|
1274
|
+
window.removeEventListener("agentNative.chatRunning", handleRunning);
|
|
1275
|
+
window.removeEventListener("focus", refresh);
|
|
1276
|
+
};
|
|
1277
|
+
}, [refreshThreads]);
|
|
1278
|
+
|
|
1279
|
+
useEffect(() => {
|
|
1280
|
+
if (!renamingThreadId) return;
|
|
1281
|
+
requestAnimationFrame(() => {
|
|
1282
|
+
renameInputRef.current?.focus();
|
|
1283
|
+
renameInputRef.current?.select();
|
|
1284
|
+
});
|
|
1285
|
+
}, [renamingThreadId]);
|
|
1286
|
+
|
|
1287
|
+
function openThread(threadId: string, options?: { isNew?: boolean }) {
|
|
1288
|
+
switchThread(threadId);
|
|
1289
|
+
navigateWithAgentChatViewTransition(navigate, "/ask");
|
|
1290
|
+
window.requestAnimationFrame(() => {
|
|
1291
|
+
window.dispatchEvent(
|
|
1292
|
+
new CustomEvent("agent-chat:open-thread", {
|
|
1293
|
+
detail: { threadId, newThread: options?.isNew === true },
|
|
1294
|
+
}),
|
|
1295
|
+
);
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
async function handleNewChat() {
|
|
1300
|
+
const threadId = await createThread();
|
|
1301
|
+
if (threadId) openThread(threadId, { isNew: true });
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
async function handleArchiveThread(threadId: string) {
|
|
1305
|
+
const wasActive =
|
|
1306
|
+
threadId === activeThreadId || threadId === persistedAnalyticsThreadId();
|
|
1307
|
+
const archived = await archiveThread(threadId);
|
|
1308
|
+
if (!archived) {
|
|
1309
|
+
toast.error(t("chat.archiveFailed"));
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
if (wasActive) {
|
|
1313
|
+
await handleNewChat();
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
function startRenameThread(thread: ChatThreadSummary) {
|
|
1318
|
+
committingRenameRef.current = false;
|
|
1319
|
+
setRenameDraft(threadTitle(thread, t("chat.untitledChat")));
|
|
1320
|
+
setRenamingThreadId(thread.id);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
function cancelRenameThread() {
|
|
1324
|
+
committingRenameRef.current = true;
|
|
1325
|
+
setRenamingThreadId(null);
|
|
1326
|
+
setRenameDraft("");
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
async function commitRenameThread() {
|
|
1330
|
+
if (committingRenameRef.current) return;
|
|
1331
|
+
const threadId = renamingThreadId;
|
|
1332
|
+
const title = renameDraft.trim();
|
|
1333
|
+
if (!threadId) return;
|
|
1334
|
+
committingRenameRef.current = true;
|
|
1335
|
+
setRenamingThreadId(null);
|
|
1336
|
+
setRenameDraft("");
|
|
1337
|
+
if (title) {
|
|
1338
|
+
const renamed = await renameThread(threadId, title);
|
|
1339
|
+
if (!renamed) toast.error(t("chat.renameFailed"));
|
|
1340
|
+
}
|
|
1341
|
+
committingRenameRef.current = false;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function handleRenameSubmit(event: FormEvent<HTMLFormElement>) {
|
|
1345
|
+
event.preventDefault();
|
|
1346
|
+
void commitRenameThread();
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
return (
|
|
1350
|
+
<div className="ms-4 min-w-0 space-y-0.5">
|
|
1351
|
+
<p className="min-w-0 truncate px-3 pb-0.5 pt-1 text-[11px] font-medium text-muted-foreground/70">
|
|
1352
|
+
{t("chat.recentChats")}
|
|
1353
|
+
</p>
|
|
1354
|
+
{visibleThreads.map((thread) => {
|
|
1355
|
+
const title = threadTitle(thread, t("chat.untitledChat"));
|
|
1356
|
+
const isActive =
|
|
1357
|
+
thread.id === activeThreadId ||
|
|
1358
|
+
thread.id === persistedAnalyticsThreadId();
|
|
1359
|
+
const isRenaming = thread.id === renamingThreadId;
|
|
1360
|
+
return (
|
|
1361
|
+
<div
|
|
1362
|
+
key={thread.id}
|
|
1363
|
+
className={cn(
|
|
1364
|
+
"group/item relative flex min-w-0 items-center rounded-lg transition-colors",
|
|
1365
|
+
isActive
|
|
1366
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
1367
|
+
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-primary",
|
|
1368
|
+
)}
|
|
1369
|
+
>
|
|
1370
|
+
{isRenaming ? (
|
|
1371
|
+
<form
|
|
1372
|
+
onSubmit={handleRenameSubmit}
|
|
1373
|
+
className="flex min-w-0 flex-1 items-center px-1"
|
|
1374
|
+
>
|
|
1375
|
+
<Input
|
|
1376
|
+
ref={renameInputRef}
|
|
1377
|
+
value={renameDraft}
|
|
1378
|
+
onChange={(event) => setRenameDraft(event.target.value)}
|
|
1379
|
+
onBlur={() => void commitRenameThread()}
|
|
1380
|
+
onKeyDown={(event) => {
|
|
1381
|
+
if (event.key === "Escape") {
|
|
1382
|
+
event.preventDefault();
|
|
1383
|
+
cancelRenameThread();
|
|
1384
|
+
}
|
|
1385
|
+
}}
|
|
1386
|
+
maxLength={160}
|
|
1387
|
+
aria-label={t("chat.renameThread", { title })}
|
|
1388
|
+
className="h-6 min-w-0 rounded-sm border-sidebar-border bg-background px-1.5 text-xs"
|
|
1389
|
+
/>
|
|
1390
|
+
</form>
|
|
1391
|
+
) : (
|
|
1392
|
+
<>
|
|
1393
|
+
<Tooltip>
|
|
1394
|
+
<TooltipTrigger asChild>
|
|
1395
|
+
<button
|
|
1396
|
+
type="button"
|
|
1397
|
+
onClick={() => openThread(thread.id)}
|
|
1398
|
+
className="min-w-0 flex-1 px-2 py-1.5 pe-12 text-start text-xs outline-none transition-[padding] focus-visible:ring-2 focus-visible:ring-ring md:pe-2 md:group-hover/item:pe-12 md:group-focus-within/item:pe-12"
|
|
1399
|
+
>
|
|
1400
|
+
<span className="block truncate">{title}</span>
|
|
1401
|
+
</button>
|
|
1402
|
+
</TooltipTrigger>
|
|
1403
|
+
<TooltipContent side="right">{title}</TooltipContent>
|
|
1404
|
+
</Tooltip>
|
|
1405
|
+
<div className="pointer-events-none absolute end-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5">
|
|
1406
|
+
<span className="pointer-events-none pe-1 text-[11px] text-muted-foreground/60 transition-opacity group-hover/item:opacity-0 group-focus-within/item:opacity-0">
|
|
1407
|
+
{isActive ? "" : formatThreadAge(threadUpdatedAt(thread))}
|
|
1408
|
+
</span>
|
|
1409
|
+
<DropdownMenu>
|
|
1410
|
+
<Tooltip>
|
|
1411
|
+
<TooltipTrigger asChild>
|
|
1412
|
+
<DropdownMenuTrigger asChild>
|
|
1413
|
+
<button
|
|
1414
|
+
type="button"
|
|
1415
|
+
aria-label={t("chat.optionsFor", { title })}
|
|
1416
|
+
className="pointer-events-auto rounded p-0.5 text-muted-foreground/50 opacity-0 transition-all hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/item:opacity-100 group-focus-within/item:opacity-100 data-[state=open]:opacity-100 data-[state=open]:text-foreground"
|
|
1417
|
+
>
|
|
1418
|
+
<IconDots className="h-3 w-3" />
|
|
1419
|
+
</button>
|
|
1420
|
+
</DropdownMenuTrigger>
|
|
1421
|
+
</TooltipTrigger>
|
|
1422
|
+
<TooltipContent side="right">
|
|
1423
|
+
{t("chat.optionsFor", { title })}
|
|
1424
|
+
</TooltipContent>
|
|
1425
|
+
</Tooltip>
|
|
1426
|
+
<DropdownMenuContent
|
|
1427
|
+
side="right"
|
|
1428
|
+
align="start"
|
|
1429
|
+
className="w-44"
|
|
1430
|
+
>
|
|
1431
|
+
<DropdownMenuItem
|
|
1432
|
+
onSelect={() => startRenameThread(thread)}
|
|
1433
|
+
>
|
|
1434
|
+
<IconPencil className="me-2 h-3.5 w-3.5" />
|
|
1435
|
+
{t("chat.renameChat")}
|
|
1436
|
+
</DropdownMenuItem>
|
|
1437
|
+
<DropdownMenuItem
|
|
1438
|
+
onSelect={() =>
|
|
1439
|
+
void pinThread(thread.id, !thread.pinnedAt)
|
|
1440
|
+
}
|
|
1441
|
+
>
|
|
1442
|
+
<IconPin className="me-2 h-3.5 w-3.5" />
|
|
1443
|
+
{thread.pinnedAt
|
|
1444
|
+
? t("chat.unpinChat")
|
|
1445
|
+
: t("chat.pinChat")}
|
|
1446
|
+
</DropdownMenuItem>
|
|
1447
|
+
<DropdownMenuSeparator />
|
|
1448
|
+
<DropdownMenuItem
|
|
1449
|
+
onSelect={() => void handleArchiveThread(thread.id)}
|
|
1450
|
+
className="text-destructive focus:text-destructive"
|
|
1451
|
+
>
|
|
1452
|
+
<IconArchive className="me-2 h-3.5 w-3.5" />
|
|
1453
|
+
{t("chat.archiveChat")}
|
|
1454
|
+
</DropdownMenuItem>
|
|
1455
|
+
</DropdownMenuContent>
|
|
1456
|
+
</DropdownMenu>
|
|
1457
|
+
</div>
|
|
1458
|
+
</>
|
|
1459
|
+
)}
|
|
1460
|
+
</div>
|
|
1461
|
+
);
|
|
1462
|
+
})}
|
|
1463
|
+
<button
|
|
1464
|
+
type="button"
|
|
1465
|
+
onClick={() => void handleNewChat()}
|
|
1466
|
+
className="flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 text-xs text-muted-foreground/60 hover:bg-sidebar-accent/50 hover:text-primary"
|
|
1467
|
+
>
|
|
1468
|
+
<IconPlus className="h-3 w-3" />
|
|
1469
|
+
{t("chat.newChat")}
|
|
1470
|
+
</button>
|
|
1471
|
+
</div>
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1178
1475
|
function getQuerySnapshots<T>(queryClient: QueryClient, queryKey: QueryKey) {
|
|
1179
1476
|
return queryClient.getQueriesData<T>({ queryKey });
|
|
1180
1477
|
}
|
|
@@ -2102,30 +2399,33 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
|
|
|
2102
2399
|
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto overflow-x-hidden py-2">
|
|
2103
2400
|
<nav className="grid min-w-0 items-start px-2 text-sm font-medium lg:px-4 space-y-1">
|
|
2104
2401
|
{/* Ask link */}
|
|
2105
|
-
<
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2402
|
+
<div className="min-w-0 space-y-1">
|
|
2403
|
+
<Link
|
|
2404
|
+
to="/ask"
|
|
2405
|
+
onClick={(event) => {
|
|
2406
|
+
if (
|
|
2407
|
+
location.pathname !== "/ask" &&
|
|
2408
|
+
!event.metaKey &&
|
|
2409
|
+
!event.ctrlKey &&
|
|
2410
|
+
!event.shiftKey &&
|
|
2411
|
+
!event.altKey
|
|
2412
|
+
) {
|
|
2413
|
+
event.preventDefault();
|
|
2414
|
+
navigateWithAgentChatViewTransition(navigate, "/ask");
|
|
2415
|
+
}
|
|
2416
|
+
}}
|
|
2417
|
+
className={cn(
|
|
2418
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:text-primary",
|
|
2419
|
+
location.pathname === "/ask"
|
|
2420
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
2421
|
+
: "text-muted-foreground hover:bg-sidebar-accent/50",
|
|
2422
|
+
)}
|
|
2423
|
+
>
|
|
2424
|
+
<IconMessageCircle className="h-4 w-4" />
|
|
2425
|
+
{t("navigation.ask")}
|
|
2426
|
+
</Link>
|
|
2427
|
+
{location.pathname === "/ask" && <AnalyticsChatsSection />}
|
|
2428
|
+
</div>
|
|
2129
2429
|
|
|
2130
2430
|
{/* Sessions link */}
|
|
2131
2431
|
<Link
|
|
@@ -150,6 +150,17 @@ const messages = {
|
|
|
150
150
|
},
|
|
151
151
|
chat: {
|
|
152
152
|
emptyState: "讓我分析儀表板、比較趨勢或深入檢視資料...",
|
|
153
|
+
recentChats: "最近聊天",
|
|
154
|
+
newChat: "新聊天",
|
|
155
|
+
untitledChat: "未命名聊天",
|
|
156
|
+
renameChat: "重新命名聊天",
|
|
157
|
+
renameThread: "重新命名 {{title}}",
|
|
158
|
+
renameFailed: "無法重新命名聊天",
|
|
159
|
+
optionsFor: "{{title}} 的選項",
|
|
160
|
+
pinChat: "釘選聊天",
|
|
161
|
+
unpinChat: "取消釘選聊天",
|
|
162
|
+
archiveChat: "封存聊天",
|
|
163
|
+
archiveFailed: "無法封存聊天",
|
|
153
164
|
suggestionArrGrowth: "本季度 ARR 增長的驅動因素是什麼?",
|
|
154
165
|
suggestionChurn: "顯示過去 6 個月的流失趨勢",
|
|
155
166
|
suggestionAnomalies: "分析 HubSpot 銷售儀表板的異常",
|
|
@@ -187,6 +187,17 @@ const enUS = {
|
|
|
187
187
|
chat: {
|
|
188
188
|
emptyState:
|
|
189
189
|
"Ask me to analyze a dashboard, compare trends, or dig into data...",
|
|
190
|
+
recentChats: "Recent chats",
|
|
191
|
+
newChat: "New chat",
|
|
192
|
+
untitledChat: "Untitled chat",
|
|
193
|
+
renameChat: "Rename chat",
|
|
194
|
+
renameThread: "Rename {{title}}",
|
|
195
|
+
renameFailed: "Couldn't rename chat",
|
|
196
|
+
optionsFor: "Options for {{title}}",
|
|
197
|
+
pinChat: "Pin chat",
|
|
198
|
+
unpinChat: "Unpin chat",
|
|
199
|
+
archiveChat: "Archive chat",
|
|
200
|
+
archiveFailed: "Couldn't archive chat",
|
|
190
201
|
suggestionArrGrowth: "What's driving ARR growth this quarter?",
|
|
191
202
|
suggestionChurn: "Show me churn trends over the last 6 months",
|
|
192
203
|
suggestionAnomalies: "Analyze the HubSpot Sales dashboard for anomalies",
|
|
@@ -3562,6 +3573,17 @@ export const messagesByLocale = {
|
|
|
3562
3573
|
},
|
|
3563
3574
|
chat: {
|
|
3564
3575
|
emptyState: "让我分析仪表板、比较趋势或深入查看数据...",
|
|
3576
|
+
recentChats: "最近聊天",
|
|
3577
|
+
newChat: "新聊天",
|
|
3578
|
+
untitledChat: "未命名聊天",
|
|
3579
|
+
renameChat: "重命名聊天",
|
|
3580
|
+
renameThread: "重命名 {{title}}",
|
|
3581
|
+
renameFailed: "无法重命名聊天",
|
|
3582
|
+
optionsFor: "{{title}} 的选项",
|
|
3583
|
+
pinChat: "置顶聊天",
|
|
3584
|
+
unpinChat: "取消置顶聊天",
|
|
3585
|
+
archiveChat: "归档聊天",
|
|
3586
|
+
archiveFailed: "无法归档聊天",
|
|
3565
3587
|
suggestionArrGrowth: "本季度 ARR 增长的驱动因素是什么?",
|
|
3566
3588
|
suggestionChurn: "显示过去 6 个月的流失趋势",
|
|
3567
3589
|
suggestionAnomalies: "分析 HubSpot 销售仪表板的异常",
|
|
@@ -3746,6 +3768,17 @@ export const messagesByLocale = {
|
|
|
3746
3768
|
chat: {
|
|
3747
3769
|
emptyState:
|
|
3748
3770
|
"Pídeme que analice un panel, compare tendencias o investigue datos...",
|
|
3771
|
+
recentChats: "Chats recientes",
|
|
3772
|
+
newChat: "Nuevo chat",
|
|
3773
|
+
untitledChat: "Chat sin título",
|
|
3774
|
+
renameChat: "Cambiar nombre del chat",
|
|
3775
|
+
renameThread: "Cambiar nombre de {{title}}",
|
|
3776
|
+
renameFailed: "No se pudo cambiar el nombre del chat",
|
|
3777
|
+
optionsFor: "Opciones para {{title}}",
|
|
3778
|
+
pinChat: "Fijar chat",
|
|
3779
|
+
unpinChat: "Desfijar chat",
|
|
3780
|
+
archiveChat: "Archivar chat",
|
|
3781
|
+
archiveFailed: "No se pudo archivar el chat",
|
|
3749
3782
|
suggestionArrGrowth: "¿Qué impulsa el crecimiento de ARR este trimestre?",
|
|
3750
3783
|
suggestionChurn: "Muéstrame la tendencia de bajas de los últimos 6 meses",
|
|
3751
3784
|
suggestionAnomalies: "Analiza anomalías en el panel de ventas de HubSpot",
|
|
@@ -3931,6 +3964,17 @@ export const messagesByLocale = {
|
|
|
3931
3964
|
chat: {
|
|
3932
3965
|
emptyState:
|
|
3933
3966
|
"Demandez-moi d'analyser un tableau de bord, de comparer des tendances ou d'explorer les données...",
|
|
3967
|
+
recentChats: "Discussions récentes",
|
|
3968
|
+
newChat: "Nouvelle discussion",
|
|
3969
|
+
untitledChat: "Discussion sans titre",
|
|
3970
|
+
renameChat: "Renommer la discussion",
|
|
3971
|
+
renameThread: "Renommer {{title}}",
|
|
3972
|
+
renameFailed: "Impossible de renommer la discussion",
|
|
3973
|
+
optionsFor: "Options pour {{title}}",
|
|
3974
|
+
pinChat: "Épingler la discussion",
|
|
3975
|
+
unpinChat: "Désépingler la discussion",
|
|
3976
|
+
archiveChat: "Archiver la discussion",
|
|
3977
|
+
archiveFailed: "Impossible d'archiver la discussion",
|
|
3934
3978
|
suggestionArrGrowth:
|
|
3935
3979
|
"Qu'est-ce qui stimule la croissance de l'ARR ce trimestre ?",
|
|
3936
3980
|
suggestionChurn: "Montre-moi les tendances de churn des 6 derniers mois",
|
|
@@ -4125,6 +4169,17 @@ export const messagesByLocale = {
|
|
|
4125
4169
|
chat: {
|
|
4126
4170
|
emptyState:
|
|
4127
4171
|
"Bitte mich, ein Dashboard zu analysieren, Trends zu vergleichen oder Daten zu untersuchen...",
|
|
4172
|
+
recentChats: "Neueste Chats",
|
|
4173
|
+
newChat: "Neuer Chat",
|
|
4174
|
+
untitledChat: "Unbenannter Chat",
|
|
4175
|
+
renameChat: "Chat umbenennen",
|
|
4176
|
+
renameThread: "{{title}} umbenennen",
|
|
4177
|
+
renameFailed: "Chat konnte nicht umbenannt werden",
|
|
4178
|
+
optionsFor: "Optionen für {{title}}",
|
|
4179
|
+
pinChat: "Chat anheften",
|
|
4180
|
+
unpinChat: "Chat lösen",
|
|
4181
|
+
archiveChat: "Chat archivieren",
|
|
4182
|
+
archiveFailed: "Chat konnte nicht archiviert werden",
|
|
4128
4183
|
suggestionArrGrowth: "Was treibt das ARR-Wachstum in diesem Quartal?",
|
|
4129
4184
|
suggestionChurn: "Zeige mir Churn-Trends der letzten 6 Monate",
|
|
4130
4185
|
suggestionAnomalies: "Analysiere Anomalien im HubSpot-Sales-Dashboard",
|
|
@@ -4311,6 +4366,17 @@ export const messagesByLocale = {
|
|
|
4311
4366
|
chat: {
|
|
4312
4367
|
emptyState:
|
|
4313
4368
|
"ダッシュボード分析、トレンド比較、データ調査を依頼できます...",
|
|
4369
|
+
recentChats: "最近のチャット",
|
|
4370
|
+
newChat: "新しいチャット",
|
|
4371
|
+
untitledChat: "無題のチャット",
|
|
4372
|
+
renameChat: "チャット名を変更",
|
|
4373
|
+
renameThread: "{{title}} の名前を変更",
|
|
4374
|
+
renameFailed: "チャット名を変更できませんでした",
|
|
4375
|
+
optionsFor: "{{title}} のオプション",
|
|
4376
|
+
pinChat: "チャットをピン留め",
|
|
4377
|
+
unpinChat: "チャットのピン留めを解除",
|
|
4378
|
+
archiveChat: "チャットをアーカイブ",
|
|
4379
|
+
archiveFailed: "チャットをアーカイブできませんでした",
|
|
4314
4380
|
suggestionArrGrowth: "今四半期の ARR 成長要因は?",
|
|
4315
4381
|
suggestionChurn: "過去 6 か月の解約傾向を表示",
|
|
4316
4382
|
suggestionAnomalies: "HubSpot Sales ダッシュボードの異常を分析",
|
|
@@ -4497,6 +4563,17 @@ export const messagesByLocale = {
|
|
|
4497
4563
|
chat: {
|
|
4498
4564
|
emptyState:
|
|
4499
4565
|
"대시보드를 분석하거나 추세를 비교하거나 데이터를 파고들어 달라고 요청하세요...",
|
|
4566
|
+
recentChats: "최근 채팅",
|
|
4567
|
+
newChat: "새 채팅",
|
|
4568
|
+
untitledChat: "제목 없는 채팅",
|
|
4569
|
+
renameChat: "채팅 이름 바꾸기",
|
|
4570
|
+
renameThread: "{{title}} 이름 바꾸기",
|
|
4571
|
+
renameFailed: "채팅 이름을 바꾸지 못했습니다",
|
|
4572
|
+
optionsFor: "{{title}} 옵션",
|
|
4573
|
+
pinChat: "채팅 고정",
|
|
4574
|
+
unpinChat: "채팅 고정 해제",
|
|
4575
|
+
archiveChat: "채팅 보관",
|
|
4576
|
+
archiveFailed: "채팅을 보관하지 못했습니다",
|
|
4500
4577
|
suggestionArrGrowth: "이번 분기 ARR 성장을 이끄는 요인은?",
|
|
4501
4578
|
suggestionChurn: "지난 6개월의 이탈 추세를 보여줘",
|
|
4502
4579
|
suggestionAnomalies: "HubSpot Sales 대시보드의 이상 징후를 분석해줘",
|
|
@@ -4684,6 +4761,17 @@ export const messagesByLocale = {
|
|
|
4684
4761
|
chat: {
|
|
4685
4762
|
emptyState:
|
|
4686
4763
|
"Peça para eu analisar um dashboard, comparar tendências ou investigar dados...",
|
|
4764
|
+
recentChats: "Chats recentes",
|
|
4765
|
+
newChat: "Novo chat",
|
|
4766
|
+
untitledChat: "Chat sem título",
|
|
4767
|
+
renameChat: "Renomear chat",
|
|
4768
|
+
renameThread: "Renomear {{title}}",
|
|
4769
|
+
renameFailed: "Não foi possível renomear o chat",
|
|
4770
|
+
optionsFor: "Opções para {{title}}",
|
|
4771
|
+
pinChat: "Fixar chat",
|
|
4772
|
+
unpinChat: "Desafixar chat",
|
|
4773
|
+
archiveChat: "Arquivar chat",
|
|
4774
|
+
archiveFailed: "Não foi possível arquivar o chat",
|
|
4687
4775
|
suggestionArrGrowth:
|
|
4688
4776
|
"O que impulsiona o crescimento de ARR neste trimestre?",
|
|
4689
4777
|
suggestionChurn: "Mostre tendências de churn dos últimos 6 meses",
|
|
@@ -4869,6 +4957,17 @@ export const messagesByLocale = {
|
|
|
4869
4957
|
chat: {
|
|
4870
4958
|
emptyState:
|
|
4871
4959
|
"मुझसे डैशबोर्ड का विश्लेषण, ट्रेंड की तुलना या डेटा में गहराई से देखने को कहें...",
|
|
4960
|
+
recentChats: "हाल की चैट",
|
|
4961
|
+
newChat: "नई चैट",
|
|
4962
|
+
untitledChat: "बिना शीर्षक वाली चैट",
|
|
4963
|
+
renameChat: "चैट का नाम बदलें",
|
|
4964
|
+
renameThread: "{{title}} का नाम बदलें",
|
|
4965
|
+
renameFailed: "चैट का नाम नहीं बदला जा सका",
|
|
4966
|
+
optionsFor: "{{title}} के विकल्प",
|
|
4967
|
+
pinChat: "चैट पिन करें",
|
|
4968
|
+
unpinChat: "चैट अनपिन करें",
|
|
4969
|
+
archiveChat: "चैट आर्काइव करें",
|
|
4970
|
+
archiveFailed: "चैट आर्काइव नहीं की जा सकी",
|
|
4872
4971
|
suggestionArrGrowth: "इस तिमाही ARR वृद्धि को क्या चला रहा है?",
|
|
4873
4972
|
suggestionChurn: "पिछले 6 महीनों के churn ट्रेंड दिखाएं",
|
|
4874
4973
|
suggestionAnomalies: "HubSpot Sales डैशबोर्ड में anomalies का विश्लेषण करें",
|
|
@@ -5052,6 +5151,17 @@ export const messagesByLocale = {
|
|
|
5052
5151
|
chat: {
|
|
5053
5152
|
emptyState:
|
|
5054
5153
|
"اطلب مني تحليل لوحة معلومات أو مقارنة الاتجاهات أو التعمق في البيانات...",
|
|
5154
|
+
recentChats: "الدردشات الأخيرة",
|
|
5155
|
+
newChat: "دردشة جديدة",
|
|
5156
|
+
untitledChat: "دردشة بدون عنوان",
|
|
5157
|
+
renameChat: "إعادة تسمية الدردشة",
|
|
5158
|
+
renameThread: "إعادة تسمية {{title}}",
|
|
5159
|
+
renameFailed: "تعذرت إعادة تسمية الدردشة",
|
|
5160
|
+
optionsFor: "خيارات {{title}}",
|
|
5161
|
+
pinChat: "تثبيت الدردشة",
|
|
5162
|
+
unpinChat: "إلغاء تثبيت الدردشة",
|
|
5163
|
+
archiveChat: "أرشفة الدردشة",
|
|
5164
|
+
archiveFailed: "تعذرت أرشفة الدردشة",
|
|
5055
5165
|
suggestionArrGrowth: "ما الذي يدفع نمو ARR هذا الربع؟",
|
|
5056
5166
|
suggestionChurn: "اعرض اتجاهات فقدان العملاء خلال آخر 6 أشهر",
|
|
5057
5167
|
suggestionAnomalies: "حلل الشذوذ في لوحة مبيعات HubSpot",
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -41,8 +41,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
41
41
|
* Body: { text: string, fieldName?: string, requestSource?: string }
|
|
42
42
|
*/
|
|
43
43
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
44
|
-
ok?: undefined;
|
|
45
44
|
text?: undefined;
|
|
45
|
+
ok?: undefined;
|
|
46
46
|
error: string;
|
|
47
47
|
} | {
|
|
48
48
|
error?: undefined;
|
package/dist/deploy/build.js
CHANGED
|
@@ -2392,6 +2392,9 @@ export default bundle;
|
|
|
2392
2392
|
virtual: {
|
|
2393
2393
|
"virtual:agents-bundle": agentsBundleModuleSource,
|
|
2394
2394
|
},
|
|
2395
|
+
replace: {
|
|
2396
|
+
"process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID": JSON.stringify(process.env.GA_MEASUREMENT_ID?.trim() || ""),
|
|
2397
|
+
},
|
|
2395
2398
|
// Replace browser-only renderers (Excalidraw/Mermaid) with an inert proxy in
|
|
2396
2399
|
// the server bundle. Without this, Nitro's Rolldown build pulls the real
|
|
2397
2400
|
// Excalidraw into a shared vendor chunk imported statically by the SSR render
|