neoagent 2.4.1-beta.19 → 2.4.1-beta.21

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 (55) hide show
  1. package/README.md +4 -1
  2. package/docs/getting-started.md +9 -3
  3. package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
  4. package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
  5. package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
  6. package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
  7. package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
  8. package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
  9. package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
  10. package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
  11. package/flutter_app/lib/features/location/location_service.dart +3 -0
  12. package/flutter_app/lib/main.dart +1 -0
  13. package/flutter_app/lib/main_account_settings.dart +9 -33
  14. package/flutter_app/lib/main_app_shell.dart +237 -197
  15. package/flutter_app/lib/main_controller.dart +0 -25
  16. package/flutter_app/lib/main_devices.dart +2 -0
  17. package/flutter_app/lib/main_models.dart +144 -0
  18. package/flutter_app/lib/main_operations.dart +150 -19
  19. package/flutter_app/lib/main_shared.dart +642 -195
  20. package/flutter_app/lib/main_theme.dart +2 -0
  21. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +3 -1
  22. package/flutter_app/lib/src/security/password_strength.dart +84 -0
  23. package/flutter_app/lib/src/theme/palette.dart +15 -15
  24. package/flutter_app/pubspec.yaml +3 -0
  25. package/flutter_app/web/favicon_light.svg +3 -0
  26. package/flutter_app/web/icons/Icon-192-light.png +0 -0
  27. package/flutter_app/web/icons/Icon-512-light.png +0 -0
  28. package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
  29. package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
  30. package/lib/manager.js +282 -81
  31. package/package.json +17 -3
  32. package/server/config/origins.js +3 -1
  33. package/server/db/database.js +73 -0
  34. package/server/public/.last_build_id +1 -1
  35. package/server/public/assets/AssetManifest.bin +1 -1
  36. package/server/public/assets/AssetManifest.bin.json +1 -1
  37. package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
  38. package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
  39. package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
  40. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  41. package/server/public/favicon_light.svg +3 -0
  42. package/server/public/flutter_bootstrap.js +1 -1
  43. package/server/public/icons/Icon-192-light.png +0 -0
  44. package/server/public/icons/Icon-512-light.png +0 -0
  45. package/server/public/icons/Icon-maskable-192-light.png +0 -0
  46. package/server/public/icons/Icon-maskable-512-light.png +0 -0
  47. package/server/public/main.dart.js +68769 -68268
  48. package/server/routes/agent_profiles.js +3 -0
  49. package/server/routes/memory.js +22 -1
  50. package/server/services/account/password_policy.js +6 -1
  51. package/server/services/memory/intelligence.js +181 -0
  52. package/server/services/memory/manager.js +475 -25
  53. package/server/utils/security.js +3 -0
  54. package/server/services/memory/openhuman_uplift.test.js +0 -98
  55. package/server/utils/version.test.js +0 -39
@@ -2861,6 +2861,10 @@ class MemoryOverview {
2861
2861
  this.dailyLogs = const <String>[],
2862
2862
  this.apiKeys = const <String, String>{},
2863
2863
  this.coreEntries = const <String, dynamic>{},
2864
+ this.stats = const MemoryStats(),
2865
+ this.entities = const <MemoryEntity>[],
2866
+ this.knowledgeViews = const <KnowledgeViewItem>[],
2867
+ this.recentKnowledgeChanges = const <KnowledgeChangeItem>[],
2864
2868
  });
2865
2869
 
2866
2870
  factory MemoryOverview.fromJson(Map<dynamic, dynamic> json) {
@@ -2880,6 +2884,16 @@ class MemoryOverview {
2880
2884
  coreEntries: coreRaw is Map
2881
2885
  ? Map<String, dynamic>.from(coreRaw)
2882
2886
  : const <String, dynamic>{},
2887
+ stats: MemoryStats.fromJson(_jsonMap(json['stats'])),
2888
+ entities: _jsonMapList(
2889
+ json['entities'],
2890
+ ).map(MemoryEntity.fromJson).toList(),
2891
+ knowledgeViews: _jsonMapList(
2892
+ json['knowledgeViews'],
2893
+ ).map(KnowledgeViewItem.fromJson).toList(),
2894
+ recentKnowledgeChanges: _jsonMapList(
2895
+ json['recentKnowledgeChanges'],
2896
+ ).map(KnowledgeChangeItem.fromJson).toList(),
2883
2897
  );
2884
2898
  }
2885
2899
 
@@ -2887,6 +2901,10 @@ class MemoryOverview {
2887
2901
  final List<String> dailyLogs;
2888
2902
  final Map<String, String> apiKeys;
2889
2903
  final Map<String, dynamic> coreEntries;
2904
+ final MemoryStats stats;
2905
+ final List<MemoryEntity> entities;
2906
+ final List<KnowledgeViewItem> knowledgeViews;
2907
+ final List<KnowledgeChangeItem> recentKnowledgeChanges;
2890
2908
 
2891
2909
  int get behaviorNotesLength => assistantBehaviorNotes.length;
2892
2910
  int get dailyLogCount => dailyLogs.length;
@@ -2894,6 +2912,112 @@ class MemoryOverview {
2894
2912
  int get coreCount => coreEntries.length;
2895
2913
  }
2896
2914
 
2915
+ class MemoryStats {
2916
+ const MemoryStats({
2917
+ this.total = 0,
2918
+ this.active = 0,
2919
+ this.archived = 0,
2920
+ this.facts = 0,
2921
+ this.entities = 0,
2922
+ this.knowledgeViews = 0,
2923
+ this.ingestionDocuments = 0,
2924
+ this.averageImportance = 0,
2925
+ this.averageConfidence = 0,
2926
+ });
2927
+
2928
+ factory MemoryStats.fromJson(Map<dynamic, dynamic> json) {
2929
+ return MemoryStats(
2930
+ total: _asInt(json['total']),
2931
+ active: _asInt(json['active']),
2932
+ archived: _asInt(json['archived']),
2933
+ facts: _asInt(json['facts']),
2934
+ entities: _asInt(json['entities']),
2935
+ knowledgeViews: _asInt(json['knowledgeViews']),
2936
+ ingestionDocuments: _asInt(json['ingestionDocuments']),
2937
+ averageImportance: _asDouble(json['averageImportance']),
2938
+ averageConfidence: _asDouble(json['averageConfidence']),
2939
+ );
2940
+ }
2941
+
2942
+ final int total;
2943
+ final int active;
2944
+ final int archived;
2945
+ final int facts;
2946
+ final int entities;
2947
+ final int knowledgeViews;
2948
+ final int ingestionDocuments;
2949
+ final double averageImportance;
2950
+ final double averageConfidence;
2951
+ }
2952
+
2953
+ class MemoryEntity {
2954
+ const MemoryEntity({
2955
+ required this.id,
2956
+ required this.key,
2957
+ required this.name,
2958
+ required this.kind,
2959
+ required this.mentionCount,
2960
+ });
2961
+
2962
+ factory MemoryEntity.fromJson(Map<dynamic, dynamic> json) {
2963
+ return MemoryEntity(
2964
+ id: json['id']?.toString() ?? '',
2965
+ key: json['key']?.toString() ?? '',
2966
+ name: json['name']?.toString() ?? '',
2967
+ kind: json['kind']?.toString().ifEmpty('concept') ?? 'concept',
2968
+ mentionCount: _asInt(json['mentionCount']),
2969
+ );
2970
+ }
2971
+
2972
+ final String id;
2973
+ final String key;
2974
+ final String name;
2975
+ final String kind;
2976
+ final int mentionCount;
2977
+ }
2978
+
2979
+ class KnowledgeViewItem {
2980
+ const KnowledgeViewItem({
2981
+ required this.title,
2982
+ required this.viewType,
2983
+ required this.summary,
2984
+ });
2985
+
2986
+ factory KnowledgeViewItem.fromJson(Map<dynamic, dynamic> json) {
2987
+ return KnowledgeViewItem(
2988
+ title:
2989
+ json['title']?.toString().ifEmpty('Knowledge view') ??
2990
+ 'Knowledge view',
2991
+ viewType: json['viewType']?.toString().ifEmpty('view') ?? 'view',
2992
+ summary: json['summary']?.toString() ?? '',
2993
+ );
2994
+ }
2995
+
2996
+ final String title;
2997
+ final String viewType;
2998
+ final String summary;
2999
+ }
3000
+
3001
+ class KnowledgeChangeItem {
3002
+ const KnowledgeChangeItem({
3003
+ required this.title,
3004
+ required this.kind,
3005
+ required this.summary,
3006
+ });
3007
+
3008
+ factory KnowledgeChangeItem.fromJson(Map<dynamic, dynamic> json) {
3009
+ return KnowledgeChangeItem(
3010
+ title: json['title']?.toString().ifEmpty('Change') ?? 'Change',
3011
+ kind: json['kind']?.toString().ifEmpty('change') ?? 'change',
3012
+ summary: json['summary']?.toString() ?? '',
3013
+ );
3014
+ }
3015
+
3016
+ final String title;
3017
+ final String kind;
3018
+ final String summary;
3019
+ }
3020
+
2897
3021
  class MemoryItem {
2898
3022
  const MemoryItem({
2899
3023
  required this.id,
@@ -2901,25 +3025,45 @@ class MemoryItem {
2901
3025
  required this.category,
2902
3026
  required this.importance,
2903
3027
  required this.createdAt,
3028
+ this.summary = '',
3029
+ this.confidence = 0.7,
3030
+ this.entities = const <MemoryEntity>[],
3031
+ this.score,
2904
3032
  });
2905
3033
 
2906
3034
  factory MemoryItem.fromJson(Map<dynamic, dynamic> json) {
2907
3035
  return MemoryItem(
2908
3036
  id: json['id']?.toString() ?? '',
2909
3037
  content: json['content']?.toString() ?? '',
3038
+ summary: json['summary']?.toString() ?? '',
2910
3039
  category: json['category']?.toString().ifEmpty('memory') ?? 'memory',
2911
3040
  importance: _asInt(json['importance']),
3041
+ confidence: _asDouble(json['confidence'], fallback: 0.7),
2912
3042
  createdAt: _parseTimestamp(json['created_at']?.toString()),
3043
+ entities: _jsonMapList(
3044
+ json['entities'],
3045
+ ).map(MemoryEntity.fromJson).toList(),
3046
+ score: (() {
3047
+ final raw = json['score'];
3048
+ if (raw == null) return null;
3049
+ if (raw is num) return raw.toDouble();
3050
+ return double.tryParse(raw.toString());
3051
+ })(),
2913
3052
  );
2914
3053
  }
2915
3054
 
2916
3055
  final String id;
2917
3056
  final String content;
3057
+ final String summary;
2918
3058
  final String category;
2919
3059
  final int importance;
3060
+ final double confidence;
2920
3061
  final DateTime createdAt;
3062
+ final List<MemoryEntity> entities;
3063
+ final double? score;
2921
3064
 
2922
3065
  String get createdAtLabel => _formatTimestamp(createdAt);
3066
+ int get confidencePercent => (confidence * 100).round().clamp(0, 100);
2923
3067
  }
2924
3068
 
2925
3069
  class ConversationItem {
@@ -1332,9 +1332,7 @@ class _MemoryPanelState extends State<MemoryPanel> {
1332
1332
  return AlertDialog(
1333
1333
  backgroundColor: _bgCard,
1334
1334
  title: Text('Import memory transfer?'),
1335
- content: Text(
1336
- 'This will import the response into $targetLabel.',
1337
- ),
1335
+ content: Text('This will import the response into $targetLabel.'),
1338
1336
  actions: <Widget>[
1339
1337
  TextButton(
1340
1338
  onPressed: () => Navigator.of(context).pop(false),
@@ -1381,9 +1379,9 @@ class _MemoryPanelState extends State<MemoryPanel> {
1381
1379
  if (!mounted) {
1382
1380
  return;
1383
1381
  }
1384
- ScaffoldMessenger.of(context).showSnackBar(
1385
- SnackBar(content: Text('Import failed: $error')),
1386
- );
1382
+ ScaffoldMessenger.of(
1383
+ context,
1384
+ ).showSnackBar(SnackBar(content: Text('Import failed: $error')));
1387
1385
  } finally {
1388
1386
  if (mounted) {
1389
1387
  setState(() {
@@ -1519,7 +1517,7 @@ class _MemoryPanelState extends State<MemoryPanel> {
1519
1517
  _PageTitle(
1520
1518
  title: 'Memory',
1521
1519
  subtitle:
1522
- 'Core memory, thread context, long-term recall, daily logs, and behavior notes.',
1520
+ 'Structured facts, entities, reflections, long-term recall, and behavior notes.',
1523
1521
  trailing: Wrap(
1524
1522
  spacing: 10,
1525
1523
  runSpacing: 10,
@@ -1541,33 +1539,33 @@ class _MemoryPanelState extends State<MemoryPanel> {
1541
1539
  children: <Widget>[
1542
1540
  Expanded(
1543
1541
  child: _OverviewCard(
1544
- title: 'Behavior Notes',
1545
- value: '${controller.memoryOverview.behaviorNotesLength} chars',
1546
- helper: 'Durable assistant style guidance',
1542
+ title: 'Active Memories',
1543
+ value: '${controller.memoryOverview.stats.active}',
1544
+ helper: 'Recallable long-term entries',
1547
1545
  ),
1548
1546
  ),
1549
1547
  const SizedBox(width: 12),
1550
1548
  Expanded(
1551
1549
  child: _OverviewCard(
1552
- title: 'Core Memory',
1553
- value: '${controller.memoryOverview.coreCount}',
1554
- helper: 'Pinned key/value entries',
1550
+ title: 'Extracted Facts',
1551
+ value: '${controller.memoryOverview.stats.facts}',
1552
+ helper: 'Structured statements for recall',
1555
1553
  ),
1556
1554
  ),
1557
1555
  const SizedBox(width: 12),
1558
1556
  Expanded(
1559
1557
  child: _OverviewCard(
1560
- title: 'Daily Logs',
1561
- value: '${controller.memoryOverview.dailyLogCount}',
1562
- helper: 'Recent captured log files',
1558
+ title: 'Entities',
1559
+ value: '${controller.memoryOverview.stats.entities}',
1560
+ helper: 'People, projects, files, and concepts',
1563
1561
  ),
1564
1562
  ),
1565
1563
  const SizedBox(width: 12),
1566
1564
  Expanded(
1567
1565
  child: _OverviewCard(
1568
- title: 'API Keys',
1569
- value: '${controller.memoryOverview.apiKeyCount}',
1570
- helper: 'Masked agent-managed credentials',
1566
+ title: 'Reflections',
1567
+ value: '${controller.memoryOverview.stats.knowledgeViews}',
1568
+ helper: 'Materialized knowledge views',
1571
1569
  ),
1572
1570
  ),
1573
1571
  ],
@@ -1609,6 +1607,117 @@ class _MemoryPanelState extends State<MemoryPanel> {
1609
1607
  ),
1610
1608
  ),
1611
1609
  const SizedBox(height: 16),
1610
+ Card(
1611
+ child: Padding(
1612
+ padding: const EdgeInsets.all(18),
1613
+ child: Column(
1614
+ crossAxisAlignment: CrossAxisAlignment.start,
1615
+ children: <Widget>[
1616
+ const _SectionTitle('Memory Intelligence'),
1617
+ const SizedBox(height: 12),
1618
+ Wrap(
1619
+ spacing: 10,
1620
+ runSpacing: 10,
1621
+ children: <Widget>[
1622
+ _MetaPill(
1623
+ label:
1624
+ 'Confidence ${(controller.memoryOverview.stats.averageConfidence * 100).round()}%',
1625
+ icon: Icons.verified_outlined,
1626
+ ),
1627
+ _MetaPill(
1628
+ label:
1629
+ 'Avg importance ${controller.memoryOverview.stats.averageImportance.toStringAsFixed(1)}',
1630
+ icon: Icons.priority_high_outlined,
1631
+ ),
1632
+ _MetaPill(
1633
+ label:
1634
+ '${controller.memoryOverview.stats.ingestionDocuments} ingested docs',
1635
+ icon: Icons.source_outlined,
1636
+ ),
1637
+ ],
1638
+ ),
1639
+ const SizedBox(height: 16),
1640
+ if (controller.memoryOverview.entities.isNotEmpty) ...<Widget>[
1641
+ Text(
1642
+ 'Top entities',
1643
+ style: TextStyle(fontWeight: FontWeight.w700),
1644
+ ),
1645
+ const SizedBox(height: 8),
1646
+ Wrap(
1647
+ spacing: 8,
1648
+ runSpacing: 8,
1649
+ children: controller.memoryOverview.entities.map((entity) {
1650
+ return _MetaPill(
1651
+ label: entity.name,
1652
+ icon: Icons.hub_outlined,
1653
+ );
1654
+ }).toList(),
1655
+ ),
1656
+ const SizedBox(height: 16),
1657
+ ],
1658
+ if (controller
1659
+ .memoryOverview
1660
+ .knowledgeViews
1661
+ .isNotEmpty) ...<Widget>[
1662
+ Text(
1663
+ 'Reflections',
1664
+ style: TextStyle(fontWeight: FontWeight.w700),
1665
+ ),
1666
+ const SizedBox(height: 8),
1667
+ ...controller.memoryOverview.knowledgeViews.take(5).map((
1668
+ view,
1669
+ ) {
1670
+ return Container(
1671
+ width: double.infinity,
1672
+ margin: const EdgeInsets.only(bottom: 10),
1673
+ padding: const EdgeInsets.all(12),
1674
+ decoration: BoxDecoration(
1675
+ color: _bgSecondary,
1676
+ borderRadius: BorderRadius.circular(8),
1677
+ border: Border.all(color: _border),
1678
+ ),
1679
+ child: Column(
1680
+ crossAxisAlignment: CrossAxisAlignment.start,
1681
+ children: <Widget>[
1682
+ Row(
1683
+ children: <Widget>[
1684
+ Expanded(
1685
+ child: Text(
1686
+ view.title,
1687
+ style: TextStyle(fontWeight: FontWeight.w700),
1688
+ ),
1689
+ ),
1690
+ _MetaPill(
1691
+ label: view.viewType,
1692
+ icon: Icons.auto_stories_outlined,
1693
+ ),
1694
+ ],
1695
+ ),
1696
+ if (view.summary.trim().isNotEmpty) ...<Widget>[
1697
+ const SizedBox(height: 8),
1698
+ Text(
1699
+ view.summary,
1700
+ maxLines: 4,
1701
+ overflow: TextOverflow.ellipsis,
1702
+ style: TextStyle(color: _textSecondary),
1703
+ ),
1704
+ ],
1705
+ ],
1706
+ ),
1707
+ );
1708
+ }),
1709
+ ],
1710
+ if (controller.memoryOverview.entities.isEmpty &&
1711
+ controller.memoryOverview.knowledgeViews.isEmpty)
1712
+ Text(
1713
+ 'No structured entities or reflections yet.',
1714
+ style: TextStyle(color: _textSecondary),
1715
+ ),
1716
+ ],
1717
+ ),
1718
+ ),
1719
+ ),
1720
+ const SizedBox(height: 16),
1612
1721
  Card(
1613
1722
  child: Theme(
1614
1723
  data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
@@ -1938,6 +2047,11 @@ class _MemoryPanelState extends State<MemoryPanel> {
1938
2047
  icon: Icons
1939
2048
  .priority_high_outlined,
1940
2049
  ),
2050
+ _MetaPill(
2051
+ label:
2052
+ 'Confidence ${memory.confidencePercent}%',
2053
+ icon: Icons.verified_outlined,
2054
+ ),
1941
2055
  ],
1942
2056
  ),
1943
2057
  ),
@@ -1961,6 +2075,23 @@ class _MemoryPanelState extends State<MemoryPanel> {
1961
2075
  ),
1962
2076
  const SizedBox(height: 10),
1963
2077
  Text(memory.content),
2078
+ if (memory
2079
+ .entities
2080
+ .isNotEmpty) ...<Widget>[
2081
+ const SizedBox(height: 8),
2082
+ Wrap(
2083
+ spacing: 8,
2084
+ runSpacing: 8,
2085
+ children: memory.entities.take(6).map(
2086
+ (entity) {
2087
+ return _MetaPill(
2088
+ label: entity.name,
2089
+ icon: Icons.hub_outlined,
2090
+ );
2091
+ },
2092
+ ).toList(),
2093
+ ),
2094
+ ],
1964
2095
  const SizedBox(height: 8),
1965
2096
  Text(
1966
2097
  memory.createdAtLabel,