@elizaos/app-core 2.0.0-alpha.335 → 2.0.0-alpha.337

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.
Files changed (62) hide show
  1. package/apps/app-lifeops/src/routes/lifeops-routes.d.ts.map +1 -1
  2. package/apps/app-lifeops/src/routes/lifeops-routes.js +10 -1
  3. package/i18n/locales/en.json +5 -5
  4. package/package.json +5 -5
  5. package/packages/agent/src/runtime/eliza.d.ts.map +1 -1
  6. package/packages/agent/src/runtime/eliza.js +7 -2
  7. package/packages/app-core/src/api/automations-compat-routes.js +1 -1
  8. package/packages/app-core/src/api/client-n8n.d.ts +4 -1
  9. package/packages/app-core/src/api/client-n8n.d.ts.map +1 -1
  10. package/packages/app-core/src/api/client-n8n.js +18 -0
  11. package/packages/app-core/src/api/client-types-chat.d.ts +37 -0
  12. package/packages/app-core/src/api/client-types-chat.d.ts.map +1 -1
  13. package/packages/app-core/src/api/n8n-routes.d.ts +6 -0
  14. package/packages/app-core/src/api/n8n-routes.d.ts.map +1 -1
  15. package/packages/app-core/src/api/n8n-routes.js +334 -0
  16. package/packages/app-core/src/components/character/CharacterEditorPanels.d.ts.map +1 -1
  17. package/packages/app-core/src/components/character/CharacterEditorPanels.js +192 -85
  18. package/packages/app-core/src/components/character/CharacterExperienceWorkspace.d.ts.map +1 -1
  19. package/packages/app-core/src/components/character/CharacterExperienceWorkspace.js +182 -31
  20. package/packages/app-core/src/components/character/CharacterHubView.d.ts.map +1 -1
  21. package/packages/app-core/src/components/character/CharacterHubView.js +253 -23
  22. package/packages/app-core/src/components/character/CharacterOverviewSection.d.ts +14 -1
  23. package/packages/app-core/src/components/character/CharacterOverviewSection.d.ts.map +1 -1
  24. package/packages/app-core/src/components/character/CharacterOverviewSection.js +35 -8
  25. package/packages/app-core/src/components/character/character-hub-helpers.d.ts.map +1 -1
  26. package/packages/app-core/src/components/character/character-hub-helpers.js +3 -7
  27. package/packages/app-core/src/components/pages/AutomationsView.d.ts.map +1 -1
  28. package/packages/app-core/src/components/pages/AutomationsView.js +523 -274
  29. package/packages/app-core/src/components/pages/HeartbeatForm.d.ts.map +1 -1
  30. package/packages/app-core/src/components/pages/HeartbeatForm.js +11 -13
  31. package/packages/app-core/src/components/pages/KnowledgeView.d.ts.map +1 -1
  32. package/packages/app-core/src/components/pages/KnowledgeView.js +20 -6
  33. package/packages/app-core/src/components/pages/RelationshipsGraphPanel.d.ts +2 -1
  34. package/packages/app-core/src/components/pages/RelationshipsGraphPanel.d.ts.map +1 -1
  35. package/packages/app-core/src/components/pages/RelationshipsGraphPanel.js +3 -3
  36. package/packages/app-core/src/components/pages/WorkflowGraphViewer.d.ts +0 -9
  37. package/packages/app-core/src/components/pages/WorkflowGraphViewer.d.ts.map +1 -1
  38. package/packages/app-core/src/components/pages/WorkflowGraphViewer.js +52 -26
  39. package/packages/app-core/src/components/pages/knowledge-detail.d.ts.map +1 -1
  40. package/packages/app-core/src/components/pages/knowledge-detail.js +28 -2
  41. package/packages/app-core/src/components/pages/page-scoped-conversations.d.ts +1 -1
  42. package/packages/app-core/src/components/pages/page-scoped-conversations.js +4 -4
  43. package/packages/app-core/src/components/pages/relationships/RelationshipsPersonPanels.d.ts +2 -1
  44. package/packages/app-core/src/components/pages/relationships/RelationshipsPersonPanels.d.ts.map +1 -1
  45. package/packages/app-core/src/components/pages/relationships/RelationshipsPersonPanels.js +69 -32
  46. package/packages/app-core/src/components/pages/relationships/RelationshipsSidebar.d.ts +1 -6
  47. package/packages/app-core/src/components/pages/relationships/RelationshipsSidebar.d.ts.map +1 -1
  48. package/packages/app-core/src/components/pages/relationships/RelationshipsSidebar.js +4 -4
  49. package/packages/app-core/src/components/pages/relationships/RelationshipsWorkspaceView.d.ts +2 -1
  50. package/packages/app-core/src/components/pages/relationships/RelationshipsWorkspaceView.d.ts.map +1 -1
  51. package/packages/app-core/src/components/pages/relationships/RelationshipsWorkspaceView.js +25 -15
  52. package/packages/app-core/src/i18n/locales/en.json +5 -5
  53. package/packages/app-core/src/registry/generate-apps.js +2 -2
  54. package/packages/app-core/src/runtime/eliza.d.ts.map +1 -1
  55. package/packages/app-core/src/runtime/eliza.js +6 -1
  56. package/packages/app-core/src/services/n8n-dispatch.d.ts +10 -2
  57. package/packages/app-core/src/services/n8n-dispatch.d.ts.map +1 -1
  58. package/packages/app-core/src/services/n8n-dispatch.js +102 -8
  59. package/packages/shared/src/contracts/lifeops.d.ts +4 -0
  60. package/packages/shared/src/contracts/lifeops.d.ts.map +1 -1
  61. package/packages/typescript/src/features/advanced-capabilities/clipboard/services/clipboardService.d.ts.map +1 -1
  62. package/packages/typescript/src/features/advanced-capabilities/clipboard/services/clipboardService.js +6 -1
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button, PageLayout, SidebarContent, SidebarPanel, SidebarScrollRegion, } from "@elizaos/ui";
3
+ import { BookOpen, Brain, LayoutDashboard, Network, PencilLine, } from "lucide-react";
3
4
  import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
5
  import { client } from "../../api/client";
5
6
  import { useApp } from "../../state/useApp";
@@ -8,10 +9,90 @@ import { RelationshipsWorkspaceView } from "../pages/relationships/Relationships
8
9
  import { AppPageSidebar } from "../shared/AppPageSidebar";
9
10
  import { CharacterExamplesPanel, CharacterIdentityPanel, CharacterStylePanel, } from "./CharacterEditorPanels";
10
11
  import { CharacterExperienceWorkspace } from "./CharacterExperienceWorkspace";
11
- import { CharacterOverviewSection } from "./CharacterOverviewSection";
12
+ import { CharacterOverviewSection, } from "./CharacterOverviewSection";
12
13
  import { CharacterPersonalityTimeline } from "./CharacterPersonalityTimeline";
13
14
  import { CharacterRelationshipsSection } from "./CharacterRelationshipsSection";
14
15
  import { buildCharacterOverviewItems, CHARACTER_HUB_SECTIONS, getCharacterHubSectionLabel, mapExperienceRecordToHubRecord, mapHistoryEntryToTimelineItem, } from "./character-hub-helpers";
16
+ const CHARACTER_SECTION_PATHS = {
17
+ overview: "/character",
18
+ personality: "/character/personality",
19
+ knowledge: "/character/knowledge",
20
+ experience: "/character/experience",
21
+ relationships: "/character/relationships",
22
+ };
23
+ const CHARACTER_SECTION_META = {
24
+ overview: {
25
+ description: "Recent character activity",
26
+ icon: LayoutDashboard,
27
+ },
28
+ personality: {
29
+ description: "Bio, style rules, examples",
30
+ icon: PencilLine,
31
+ },
32
+ knowledge: {
33
+ description: "Documents, chunks, CRUD",
34
+ icon: BookOpen,
35
+ },
36
+ experience: {
37
+ description: "Learnings, confidence, review",
38
+ icon: Brain,
39
+ },
40
+ relationships: {
41
+ description: "People, facts, graph context",
42
+ icon: Network,
43
+ },
44
+ };
45
+ function getSectionFromLocation(tab) {
46
+ if (typeof window === "undefined")
47
+ return "overview";
48
+ const pathname = window.location.pathname.toLowerCase();
49
+ if (pathname.endsWith("/personality"))
50
+ return "personality";
51
+ if (pathname.endsWith("/knowledge"))
52
+ return "knowledge";
53
+ if (pathname.endsWith("/experience"))
54
+ return "experience";
55
+ if (pathname.endsWith("/relationships"))
56
+ return "relationships";
57
+ if (tab === "knowledge")
58
+ return "knowledge";
59
+ return "overview";
60
+ }
61
+ function updateCharacterSectionPath(section, mode = "push") {
62
+ if (typeof window === "undefined")
63
+ return;
64
+ const path = CHARACTER_SECTION_PATHS[section];
65
+ if (!path || window.location.pathname === path)
66
+ return;
67
+ window.history[mode === "replace" ? "replaceState" : "pushState"](null, "", path);
68
+ }
69
+ function countDuplicateValues(values) {
70
+ const seen = new Set();
71
+ const duplicates = new Set();
72
+ for (const value of values) {
73
+ const normalized = value.trim().toLowerCase();
74
+ if (!normalized)
75
+ continue;
76
+ if (seen.has(normalized)) {
77
+ duplicates.add(normalized);
78
+ }
79
+ seen.add(normalized);
80
+ }
81
+ return duplicates.size;
82
+ }
83
+ const DEFAULT_KNOWLEDGE_FILENAMES = new Set([
84
+ "eliza-overview.txt",
85
+ "eliza-history.txt",
86
+ "eliza-cloud-basics.txt",
87
+ ]);
88
+ function isDefaultKnowledgeDocument(document) {
89
+ const normalizedFilename = document.filename.trim().toLowerCase();
90
+ return (document.source === "bundled" ||
91
+ document.source === "character" ||
92
+ document.provenance.kind === "bundled" ||
93
+ document.provenance.kind === "character" ||
94
+ DEFAULT_KNOWLEDGE_FILENAMES.has(normalizedFilename));
95
+ }
15
96
  function mergeCharacterPatch(base, patch) {
16
97
  return {
17
98
  ...base,
@@ -21,7 +102,7 @@ function mergeCharacterPatch(base, patch) {
21
102
  }
22
103
  export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendingStyleEntries, styleEntryDrafts, handleFieldEdit, applyFieldEdit, handlePendingStyleEntryChange, applyStyleEdit, handleStyleEntryDraftChange, characterSaving, characterSaveSuccess, characterSaveError, hasPendingChanges, onSave, onReset, canReset, }) {
23
104
  const { setActionNotice, setTab, tab, t } = useApp();
24
- const [activeSection, setActiveSection] = useState(tab === "knowledge" ? "knowledge" : "overview");
105
+ const [activeSection, setActiveSection] = useState(() => getSectionFromLocation(tab));
25
106
  const [knowledgeDocuments, setKnowledgeDocuments] = useState([]);
26
107
  const [selectedKnowledgeDocumentId, setSelectedKnowledgeDocumentId] = useState(null);
27
108
  const [historyEntries, setHistoryEntries] = useState([]);
@@ -86,13 +167,15 @@ export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendin
86
167
  };
87
168
  }, [flushPendingAutoSave]);
88
169
  useEffect(() => {
89
- if (tab === "knowledge") {
90
- setActiveSection("knowledge");
91
- }
170
+ setActiveSection(getSectionFromLocation(tab));
92
171
  }, [tab]);
93
172
  useEffect(() => {
94
- setTab(activeSection === "knowledge" ? "knowledge" : "character");
95
- }, [activeSection, setTab]);
173
+ const handlePopState = () => {
174
+ setActiveSection(getSectionFromLocation(tab));
175
+ };
176
+ window.addEventListener("popstate", handlePopState);
177
+ return () => window.removeEventListener("popstate", handlePopState);
178
+ }, [tab]);
96
179
  useEffect(() => {
97
180
  let cancelled = false;
98
181
  setHistoryLoading(true);
@@ -185,23 +268,169 @@ export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendin
185
268
  cancelled = true;
186
269
  };
187
270
  }, []);
271
+ const customKnowledgeDocuments = useMemo(() => knowledgeDocuments.filter((document) => !isDefaultKnowledgeDocument(document)), [knowledgeDocuments]);
272
+ const needsKnowledgeUpload = customKnowledgeDocuments.length === 0;
188
273
  const overviewItems = useMemo(() => buildCharacterOverviewItems({
189
274
  history: historyEntries,
190
- documents: knowledgeDocuments,
275
+ documents: customKnowledgeDocuments,
191
276
  experiences: experienceRecords,
192
277
  relationshipActivity,
193
278
  }), [
279
+ customKnowledgeDocuments,
194
280
  experienceRecords,
195
281
  historyEntries,
196
- knowledgeDocuments,
197
282
  relationshipActivity,
198
283
  ]);
284
+ const balancedOverviewItems = useMemo(() => {
285
+ const byKind = new Map();
286
+ for (const item of overviewItems) {
287
+ const bucket = byKind.get(item.kind) ?? [];
288
+ if (bucket.length < 4) {
289
+ bucket.push(item);
290
+ byKind.set(item.kind, bucket);
291
+ }
292
+ }
293
+ return Array.from(byKind.values())
294
+ .flat()
295
+ .sort((left, right) => {
296
+ const leftTime = left.timestamp
297
+ ? new Date(left.timestamp).getTime()
298
+ : 0;
299
+ const rightTime = right.timestamp
300
+ ? new Date(right.timestamp).getTime()
301
+ : 0;
302
+ return rightTime - leftTime;
303
+ });
304
+ }, [overviewItems]);
305
+ const styleRules = d.style?.all ?? [];
306
+ const duplicateStyleRules = countDuplicateValues(styleRules);
307
+ const postExamples = d.postExamples ?? [];
308
+ const duplicatePostExamples = countDuplicateValues(postExamples);
309
+ const lowConfidenceExperiences = experienceRecords.filter((experience) => experience.confidence < 0.55).length;
310
+ const overviewInsights = [
311
+ ...(hasPendingChanges
312
+ ? [
313
+ {
314
+ id: "pending-personality",
315
+ section: "personality",
316
+ title: "Unsaved personality changes",
317
+ detail: "Bio edits still need a manual save.",
318
+ tone: "warn",
319
+ },
320
+ ]
321
+ : []),
322
+ ...(duplicateStyleRules > 0
323
+ ? [
324
+ {
325
+ id: "duplicate-style",
326
+ section: "personality",
327
+ title: "Duplicate style rules",
328
+ detail: `${duplicateStyleRules} repeated style rule ${duplicateStyleRules === 1 ? "entry" : "entries"} should be merged.`,
329
+ tone: "warn",
330
+ },
331
+ ]
332
+ : []),
333
+ ...(duplicatePostExamples > 0
334
+ ? [
335
+ {
336
+ id: "duplicate-posts",
337
+ section: "personality",
338
+ title: "Duplicate post examples",
339
+ detail: `${duplicatePostExamples} repeated post example ${duplicatePostExamples === 1 ? "entry" : "entries"} should be trimmed.`,
340
+ tone: "warn",
341
+ },
342
+ ]
343
+ : []),
344
+ ...(needsKnowledgeUpload
345
+ ? [
346
+ {
347
+ id: knowledgeDocuments.length === 0
348
+ ? "empty-knowledge"
349
+ : "default-knowledge-only",
350
+ section: "knowledge",
351
+ title: knowledgeDocuments.length === 0
352
+ ? "No knowledge uploaded"
353
+ : "Only default knowledge loaded",
354
+ detail: "Upload documents, notes, or links to give this character source material that is specific to your workspace.",
355
+ tone: "warn",
356
+ },
357
+ ]
358
+ : []),
359
+ ...(knowledgeDocuments.some((document) => document.fragmentCount === 0)
360
+ ? [
361
+ {
362
+ id: "empty-fragments",
363
+ section: "knowledge",
364
+ title: "Knowledge without chunks",
365
+ detail: "At least one document has no retrievable chunks.",
366
+ tone: "danger",
367
+ },
368
+ ]
369
+ : []),
370
+ ...(lowConfidenceExperiences > 0
371
+ ? [
372
+ {
373
+ id: "low-confidence-experience",
374
+ section: "experience",
375
+ title: "Experience review needed",
376
+ detail: `${lowConfidenceExperiences} learned ${lowConfidenceExperiences === 1 ? "experience has" : "experiences have"} low confidence.`,
377
+ tone: "warn",
378
+ },
379
+ ]
380
+ : []),
381
+ ...(experienceError
382
+ ? [
383
+ {
384
+ id: "experience-error",
385
+ section: "experience",
386
+ title: "Experience load failed",
387
+ detail: experienceError,
388
+ tone: "danger",
389
+ },
390
+ ]
391
+ : []),
392
+ ...(relationshipActivityError
393
+ ? [
394
+ {
395
+ id: "relationship-error",
396
+ section: "relationships",
397
+ title: "Relationship activity failed",
398
+ detail: relationshipActivityError,
399
+ tone: "danger",
400
+ },
401
+ ]
402
+ : []),
403
+ ...(historyError
404
+ ? [
405
+ {
406
+ id: "history-error",
407
+ section: "personality",
408
+ title: "Personality history failed",
409
+ detail: historyError,
410
+ tone: "danger",
411
+ },
412
+ ]
413
+ : []),
414
+ ];
199
415
  const timelineItems = useMemo(() => historyEntries.map(mapHistoryEntryToTimelineItem), [historyEntries]);
200
416
  const hubExperienceRecords = useMemo(() => experienceRecords.map(mapExperienceRecordToHubRecord), [experienceRecords]);
201
417
  const activeSectionLabel = getCharacterHubSectionLabel(activeSection);
418
+ const navigateToSection = useCallback((section) => {
419
+ setActiveSection(section);
420
+ if (section === "knowledge") {
421
+ if (tab !== "knowledge") {
422
+ setTab("knowledge");
423
+ }
424
+ else {
425
+ updateCharacterSectionPath(section);
426
+ }
427
+ return;
428
+ }
429
+ updateCharacterSectionPath(section);
430
+ }, [setTab, tab]);
202
431
  const scrollPersonalitySectionIntoView = (section) => {
203
432
  if (activeSection !== "personality") {
204
- setActiveSection("personality");
433
+ navigateToSection("personality");
205
434
  requestAnimationFrame(() => {
206
435
  personalitySectionRefs.current[section]?.scrollIntoView({
207
436
  behavior: "smooth",
@@ -218,19 +447,19 @@ export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendin
218
447
  const handleOverviewOpen = (item) => {
219
448
  if (item.kind === "knowledge") {
220
449
  setSelectedKnowledgeDocumentId(item.id.replace("knowledge:", ""));
221
- setActiveSection("knowledge");
450
+ navigateToSection("knowledge");
222
451
  return;
223
452
  }
224
453
  if (item.kind === "experience") {
225
454
  setSelectedExperienceId(item.id.replace("experience:", ""));
226
- setActiveSection("experience");
455
+ navigateToSection("experience");
227
456
  return;
228
457
  }
229
458
  if (item.kind === "relationship") {
230
- setActiveSection("relationships");
459
+ navigateToSection("relationships");
231
460
  return;
232
461
  }
233
- setActiveSection("personality");
462
+ navigateToSection("personality");
234
463
  };
235
464
  const handleSaveExperience = async (experience, draft) => {
236
465
  setSavingExperienceId(experience.id);
@@ -337,22 +566,23 @@ export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendin
337
566
  clearPendingAutoSave();
338
567
  onReset();
339
568
  }, [clearPendingAutoSave, onReset]);
340
- const sectionNav = (_jsx(SidebarPanel, { className: "gap-3 bg-transparent p-0 shadow-none", children: _jsx("nav", { className: "flex flex-col gap-1", "aria-label": "Character hub sections", children: CHARACTER_HUB_SECTIONS.map((section) => (_jsx(SidebarContent.Item, { active: activeSection === section, onClick: () => setActiveSection(section), "aria-current": activeSection === section ? "page" : undefined, className: "items-center gap-2 px-2.5 py-2", children: _jsx(SidebarContent.ItemTitle, { className: activeSection === section ? "font-semibold" : "font-medium", children: getCharacterHubSectionLabel(section) }) }, section))) }) }));
341
- const contextualSidebar = activeSection === "personality" ? (_jsxs(SidebarPanel, { className: "gap-2 bg-transparent p-0 shadow-none", children: [_jsx("div", { className: "px-2.5 text-[0.65rem] font-semibold uppercase tracking-[0.16em] text-muted/70", children: "Personality" }), _jsx("div", { className: "flex flex-col gap-1", children: [
569
+ const sectionNav = (_jsxs(SidebarPanel, { className: "min-h-0 gap-2 bg-transparent p-0 shadow-none", children: [_jsx(SidebarContent.SectionLabel, { className: "px-2", children: "Character" }), _jsx("nav", { className: "flex flex-col gap-1", "aria-label": "Character hub sections", children: CHARACTER_HUB_SECTIONS.map((section) => (() => {
570
+ const meta = CHARACTER_SECTION_META[section];
571
+ const Icon = meta.icon;
572
+ const active = activeSection === section;
573
+ return (_jsxs(SidebarContent.Item, { active: active, onClick: () => navigateToSection(section), "aria-current": active ? "page" : undefined, className: "items-center gap-2 px-2.5 py-2", children: [_jsx(SidebarContent.ItemIcon, { active: active, className: `mt-0 h-8 w-8 bg-transparent p-0 group-hover:bg-transparent ${active ? "text-accent" : "text-muted"}`, children: _jsx(Icon, { className: "h-4 w-4", "aria-hidden": true }) }), _jsx(SidebarContent.ItemBody, { children: _jsx(SidebarContent.ItemTitle, { className: `truncate text-sm leading-5 ${active ? "font-semibold" : "font-medium"}`, children: getCharacterHubSectionLabel(section) }) })] }, section));
574
+ })()) })] }));
575
+ const contextualSidebar = activeSection === "personality" ? (_jsxs(SidebarPanel, { className: "min-h-0 gap-2 bg-transparent p-0 shadow-none", children: [_jsx(SidebarContent.SectionLabel, { children: "Personality" }), _jsx("div", { className: "flex flex-col gap-1", children: [
342
576
  ["bio", "Bio"],
343
577
  ["style", "Style Rules"],
344
578
  ["examples", "Examples"],
345
579
  ["evolution", "Evolution"],
346
- ].map(([id, label]) => (_jsx(SidebarContent.Item, { onClick: () => scrollPersonalitySectionIntoView(id), className: "items-center gap-2 px-2.5 py-2", children: _jsx(SidebarContent.ItemTitle, { className: "font-medium", children: label }) }, id))) })] })) : activeSection === "knowledge" ? (_jsxs(SidebarPanel, { className: "gap-2 bg-transparent p-0 shadow-none", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-2.5", children: [_jsx("div", { className: "text-[0.65rem] font-semibold uppercase tracking-[0.16em] text-muted/70", children: "Documents" }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-7 w-7 rounded-sm text-muted hover:bg-bg-muted/60 hover:text-txt", onClick: () => document.getElementById("character-hub-knowledge-upload")?.click(), title: t("knowledgeview.ChooseFiles", {
347
- defaultValue: "Choose files",
348
- }), "aria-label": t("knowledgeview.ChooseFiles", {
349
- defaultValue: "Choose files",
350
- }), children: "+" })] }), _jsx("div", { className: "ml-2 flex flex-col gap-0.5 border-l border-border/25 pl-2", children: knowledgeDocuments.length > 0 ? (knowledgeDocuments.map((document) => (_jsx(SidebarContent.Item, { active: selectedKnowledgeDocumentId === document.id, onClick: () => setSelectedKnowledgeDocumentId(document.id), "aria-current": selectedKnowledgeDocumentId === document.id
580
+ ].map(([id, label]) => (_jsx(SidebarContent.Item, { onClick: () => scrollPersonalitySectionIntoView(id), className: "items-center gap-2 px-2.5 py-2", children: _jsx(SidebarContent.ItemTitle, { className: "font-medium", children: label }) }, id))) })] })) : activeSection === "knowledge" ? (_jsxs(SidebarPanel, { className: "min-h-0 gap-2 bg-transparent p-0 shadow-none", children: [_jsx(SidebarContent.SectionLabel, { children: "Documents" }), _jsx("div", { className: "ml-2 flex flex-col gap-0.5 border-l border-border/25 pl-2", children: knowledgeDocuments.length > 0 ? (knowledgeDocuments.map((document) => (_jsx(SidebarContent.Item, { active: selectedKnowledgeDocumentId === document.id, onClick: () => setSelectedKnowledgeDocumentId(document.id), "aria-current": selectedKnowledgeDocumentId === document.id
351
581
  ? "page"
352
582
  : undefined, className: "items-center gap-2 py-1.5 pl-2 pr-2", children: _jsx(SidebarContent.ItemTitle, { className: "truncate text-xs-tight font-medium", children: document.filename }) }, document.id)))) : (_jsx("div", { className: "px-2 py-2 text-xs-tight text-muted", children: "No knowledge documents yet." })) })] })) : null;
353
583
  const renderSection = () => {
354
584
  if (activeSection === "overview") {
355
- return (_jsx(CharacterOverviewSection, { items: overviewItems, onOpenItem: handleOverviewOpen }));
585
+ return (_jsx(CharacterOverviewSection, { insights: overviewInsights, items: balancedOverviewItems, needsKnowledgeUpload: needsKnowledgeUpload, onOpenItem: handleOverviewOpen, onOpenIdentitySettings: () => setTab("settings"), onOpenKnowledgeUpload: () => navigateToSection("knowledge"), onOpenSection: navigateToSection }));
356
586
  }
357
587
  if (activeSection === "personality") {
358
588
  return (_jsxs("div", { className: "flex min-w-0 flex-col gap-8", children: [_jsxs("section", { ref: (node) => {
@@ -385,7 +615,7 @@ export function CharacterHubView({ d, bioText, normalizedMessageExamples, pendin
385
615
  void handleDeleteExperience(source);
386
616
  }, savingExperienceId: savingExperienceId, deletingExperienceId: deletingExperienceId }))] }));
387
617
  }
388
- return (_jsxs(CharacterRelationshipsSection, { summary: "See the full relationships viewer, including extracted facts, relevant memories, and user-scoped preferences.", children: [relationshipActivityError ? (_jsx("div", { className: "border-b border-danger/20 bg-danger/10 px-4 py-3 text-sm text-danger", children: relationshipActivityError })) : null, _jsx("div", { className: "min-h-[56rem]", children: _jsx(RelationshipsWorkspaceView, { onViewMemories: () => {
618
+ return (_jsxs(CharacterRelationshipsSection, { summary: "See the full relationships viewer, including extracted facts, relevant memories, and user-scoped preferences.", children: [relationshipActivityError ? (_jsx("div", { className: "border-b border-danger/20 bg-danger/10 px-4 py-3 text-sm text-danger", children: relationshipActivityError })) : null, _jsx("div", { className: "min-h-[40rem]", children: _jsx(RelationshipsWorkspaceView, { embedded: true, onViewMemories: () => {
389
619
  setTab("memories");
390
620
  } }) })] }));
391
621
  };
@@ -1,6 +1,19 @@
1
+ import type { CharacterHubSection } from "./character-hub-helpers";
1
2
  import type { CharacterHubActivityItem } from "./character-hub-types";
2
- export declare function CharacterOverviewSection({ items, onOpenItem, }: {
3
+ export interface CharacterOverviewInsight {
4
+ id: string;
5
+ section: CharacterHubSection;
6
+ title: string;
7
+ detail: string;
8
+ tone?: "default" | "good" | "warn" | "danger";
9
+ }
10
+ export declare function CharacterOverviewSection({ insights, items, onOpenItem, onOpenSection, onOpenKnowledgeUpload, onOpenIdentitySettings, needsKnowledgeUpload, }: {
11
+ insights: CharacterOverviewInsight[];
3
12
  items: CharacterHubActivityItem[];
4
13
  onOpenItem?: (item: CharacterHubActivityItem) => void;
14
+ onOpenSection?: (section: CharacterHubSection) => void;
15
+ onOpenKnowledgeUpload?: () => void;
16
+ onOpenIdentitySettings?: () => void;
17
+ needsKnowledgeUpload?: boolean;
5
18
  }): import("react/jsx-runtime").JSX.Element;
6
19
  //# sourceMappingURL=CharacterOverviewSection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CharacterOverviewSection.d.ts","sourceRoot":"","sources":["../../../../../../src/components/character/CharacterOverviewSection.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AA0CtE,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,UAAU,GACX,EAAE;IACD,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACvD,2CA6EA"}
1
+ {"version":3,"file":"CharacterOverviewSection.d.ts","sourceRoot":"","sources":["../../../../../../src/components/character/CharacterOverviewSection.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,mBAAmB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;CAC/C;AAkKD,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,KAAK,EACL,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,oBAA4B,GAC7B,EAAE;IACD,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACtD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACvD,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,2CAsIA"}
@@ -1,5 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Button } from "@elizaos/ui";
3
+ import { AlertTriangle, BookOpen, Brain, Network, Sparkles, } from "lucide-react";
3
4
  function formatTimestamp(value) {
4
5
  if (!value)
5
6
  return null;
@@ -39,12 +40,38 @@ function activityLabel(kind) {
39
40
  return "Update";
40
41
  }
41
42
  }
42
- export function CharacterOverviewSection({ items, onOpenItem, }) {
43
- if (items.length === 0) {
44
- return (_jsx("section", { className: "rounded-2xl border border-dashed border-border/40 bg-bg-muted/20 px-5 py-8 text-sm text-muted", children: "No updates yet. Personality changes, new knowledge, experiences, and relationship activity will appear here." }));
43
+ function getKindIcon(kind) {
44
+ switch (kind) {
45
+ case "knowledge":
46
+ return BookOpen;
47
+ case "experience":
48
+ return Brain;
49
+ case "relationship":
50
+ return Network;
51
+ default:
52
+ return Sparkles;
45
53
  }
46
- return (_jsxs("section", { className: "flex min-w-0 flex-col gap-3", children: [_jsx("div", { className: "flex items-center justify-between gap-3", children: _jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold text-txt", children: "Overview" }), _jsx("p", { className: "text-sm text-muted", children: "Recent updates across personality, knowledge, experience, and relationships." })] }) }), _jsx("div", { className: "flex min-w-0 flex-col divide-y divide-border/25 rounded-2xl border border-border/40 bg-bg/70", children: items.map((item) => {
47
- const formattedTimestamp = formatTimestamp(item.timestamp);
48
- return (_jsxs("article", { className: "flex min-w-0 items-start gap-3 px-4 py-4 first:rounded-t-2xl last:rounded-b-2xl", children: [_jsx("div", { className: `mt-0.5 inline-flex h-8 min-w-8 items-center justify-center rounded-full px-2 text-[0.65rem] font-bold uppercase tracking-[0.08em] ${activityAccent(item.kind)}`, children: activityLabel(item.kind).slice(0, 1) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-txt", children: item.title }), _jsx("span", { className: "rounded-full border border-border/40 px-2 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.08em] text-muted", children: activityLabel(item.kind) }), item.badge ? (_jsx("span", { className: "rounded-full border border-border/40 px-2 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.08em] text-muted", children: item.badge })) : null, formattedTimestamp ? (_jsx("span", { className: "text-xs text-muted", children: formattedTimestamp })) : null] }), _jsx("p", { className: "mt-1 whitespace-pre-wrap text-sm leading-relaxed text-muted-strong", children: item.description }), item.meta ? (_jsx("p", { className: "mt-2 text-xs text-muted", children: item.meta })) : null] }), onOpenItem ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "shrink-0 rounded-lg", onClick: () => onOpenItem(item), children: "Open" })) : null] }, item.id));
49
- }) })] }));
54
+ }
55
+ function ActivityRow({ item, onOpenItem, }) {
56
+ const formattedTimestamp = formatTimestamp(item.timestamp);
57
+ const Icon = getKindIcon(item.kind);
58
+ return (_jsxs("article", { className: "flex min-w-0 items-start gap-3 py-3 first:pt-0 last:pb-0", children: [_jsx("div", { className: `mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full ${activityAccent(item.kind)}`, children: _jsx(Icon, { className: "h-4 w-4", "aria-hidden": true }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [_jsx("h4", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-txt", children: item.title }), item.badge ? (_jsx("span", { className: "rounded-full border border-border/40 px-2 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.08em] text-muted", children: item.badge })) : null] }), _jsx("p", { className: "mt-1 line-clamp-2 text-sm leading-5 text-muted-strong", children: item.description }), _jsxs("div", { className: "mt-2 flex min-w-0 flex-wrap items-center gap-2 text-xs text-muted", children: [formattedTimestamp ? _jsx("span", { children: formattedTimestamp }) : null, item.meta ? (_jsxs(_Fragment, { children: [formattedTimestamp ? _jsx("span", { "aria-hidden": true, children: "\u00B7" }) : null, _jsx("span", { className: "truncate", children: item.meta })] })) : null] })] }), onOpenItem ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-8 shrink-0 rounded-lg px-2", onClick: () => onOpenItem(item), children: "Open" })) : null] }));
59
+ }
60
+ function ActivityLane({ empty, items, kind, onOpenItem, title, }) {
61
+ const Icon = getKindIcon(kind);
62
+ return (_jsxs("section", { className: "min-w-0 rounded-lg border border-border/35 bg-bg/70 px-4 py-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: `inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full ${activityAccent(kind)}`, children: _jsx(Icon, { className: "h-4 w-4", "aria-hidden": true }) }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-txt", children: title }), _jsx("p", { className: "mt-0.5 text-xs text-muted", children: items.length > 0 ? `${items.length} recent` : empty })] })] }), _jsx("span", { className: "rounded-full border border-border/35 px-2 py-0.5 text-[0.65rem] font-semibold uppercase tracking-[0.08em] text-muted", children: activityLabel(kind) })] }), items.length === 0 ? (_jsx("div", { className: "mt-4 rounded-lg border border-dashed border-border/35 bg-bg-muted/15 px-3 py-5 text-sm text-muted", children: empty })) : (_jsx("div", { className: "mt-4 flex min-w-0 flex-col divide-y divide-border/25", children: items.map((item) => (_jsx(ActivityRow, { item: item, onOpenItem: onOpenItem }, item.id))) }))] }));
63
+ }
64
+ export function CharacterOverviewSection({ insights, items, onOpenItem, onOpenSection, onOpenKnowledgeUpload, onOpenIdentitySettings, needsKnowledgeUpload = false, }) {
65
+ const experienceItems = items
66
+ .filter((item) => item.kind === "experience")
67
+ .slice(0, 4);
68
+ const relationshipItems = items
69
+ .filter((item) => item.kind === "relationship")
70
+ .slice(0, 4);
71
+ const knowledgeItems = items
72
+ .filter((item) => item.kind === "knowledge")
73
+ .slice(0, 4);
74
+ return (_jsxs("section", { className: "flex min-w-0 flex-col gap-4", children: [_jsxs("div", { className: "flex items-end justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-xl font-semibold leading-tight text-txt", children: "Overview" }), _jsx("p", { className: "mt-1 max-w-2xl text-sm leading-5 text-muted", children: "Recent knowledge, learned behavior, and relationship movement." })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [needsKnowledgeUpload ? (_jsx(Button, { type: "button", variant: "default", size: "sm", className: "rounded-lg", onClick: onOpenKnowledgeUpload, children: "Upload knowledge" })) : null, _jsx(Button, { type: "button", variant: "outline", size: "sm", className: "rounded-lg", onClick: onOpenIdentitySettings, children: "Open identity settings" })] })] }), needsKnowledgeUpload ? (_jsx("section", { className: "rounded-lg border border-accent/20 bg-accent/5 px-4 py-3", children: _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-sm font-semibold text-txt", children: "Add source material" }), _jsx("p", { className: "mt-1 max-w-2xl text-sm leading-5 text-muted", children: "Upload docs, notes, or links to make this character specific to your world instead of relying on the default baseline." })] }), _jsx(Button, { type: "button", variant: "outline", size: "sm", className: "rounded-lg", onClick: onOpenKnowledgeUpload, children: "Go to knowledge" })] }) })) : null, insights.length > 0 ? (_jsxs("section", { className: "rounded-lg border border-status-warning/25 bg-status-warning-bg/20 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(AlertTriangle, { className: "h-4 w-4 shrink-0 text-status-warning", "aria-hidden": true }), _jsx("h3", { className: "text-sm font-semibold text-txt", children: "Needs review" })] }), _jsxs("span", { className: "text-xs text-muted", children: [insights.length, " ", insights.length === 1 ? "item" : "items"] })] }), _jsx("div", { className: "mt-3 grid gap-2 md:grid-cols-2", children: insights.slice(0, 4).map((insight) => (_jsxs("button", { type: "button", className: "min-w-0 rounded-lg border border-border/25 bg-bg/45 px-3 py-2 text-left transition-colors hover:border-accent/35 hover:bg-bg-muted/30", onClick: () => onOpenSection?.(insight.section), children: [_jsx("span", { className: "block truncate text-sm font-semibold text-txt", children: insight.title }), _jsx("span", { className: "mt-1 line-clamp-2 text-xs leading-5 text-muted", children: insight.detail })] }, insight.id))) })] })) : null, _jsxs("div", { className: "grid items-start gap-4 xl:grid-cols-3", children: [_jsx(ActivityLane, { empty: "No recent experiences.", items: experienceItems, kind: "experience", onOpenItem: onOpenItem, title: "Recent experiences" }), _jsx(ActivityLane, { empty: "No relationship changes.", items: relationshipItems, kind: "relationship", onOpenItem: onOpenItem, title: "Relationship changes" }), _jsx(ActivityLane, { empty: needsKnowledgeUpload
75
+ ? "Upload source material to build a real knowledge base."
76
+ : "No new knowledge.", items: knowledgeItems, kind: "knowledge", onOpenItem: onOpenItem, title: "New knowledge" })] })] }));
50
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"character-hub-helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/components/character/character-hub-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EACV,yBAAyB,EACzB,wBAAwB,EACxB,+BAA+B,EAChC,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,sBAAsB,kFAMzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAeR;AASD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,qBAAqB,GAC3B,+BAA+B,CA8BjC;AAED,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,gBAAgB,GAC3B,yBAAyB,CAoB3B;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,oBAAoB,EAAE,yBAAyB,EAAE,CAAC;CACnD,GAAG,wBAAwB,EAAE,CAwE7B"}
1
+ {"version":3,"file":"character-hub-helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/components/character/character-hub-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EACV,yBAAyB,EACzB,wBAAwB,EACxB,+BAA+B,EAChC,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,sBAAsB,kFAMzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAeR;AASD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,qBAAqB,GAC3B,+BAA+B,CA8BjC;AAED,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,gBAAgB,GAC3B,yBAAyB,CAoB3B;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,oBAAoB,EAAE,yBAAyB,EAAE,CAAC;CACnD,GAAG,wBAAwB,EAAE,CAoE7B"}
@@ -124,13 +124,9 @@ export function buildCharacterOverviewItems(options) {
124
124
  ...knowledgeItems,
125
125
  ...experienceItems,
126
126
  ...relationshipItems,
127
- ]
128
- .sort((left, right) => {
127
+ ].sort((left, right) => {
129
128
  const leftTime = left.timestamp ? new Date(left.timestamp).getTime() : 0;
130
- const rightTime = right.timestamp
131
- ? new Date(right.timestamp).getTime()
132
- : 0;
129
+ const rightTime = right.timestamp ? new Date(right.timestamp).getTime() : 0;
133
130
  return rightTime - leftTime;
134
- })
135
- .slice(0, 50);
131
+ });
136
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationsView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/AutomationsView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAglJH,wBAAgB,eAAe,4CAO9B;AAED,wBAAgB,uBAAuB,4CAetC"}
1
+ {"version":3,"file":"AutomationsView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/AutomationsView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAi8JH,wBAAgB,eAAe,4CAO9B;AAED,wBAAgB,uBAAuB,4CAmBtC"}