neoagent 2.4.1-beta.9 → 2.4.1

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 (234) hide show
  1. package/.env.example +33 -3
  2. package/LICENSE +111 -56
  3. package/README.md +8 -3
  4. package/docs/configuration.md +8 -0
  5. package/docs/getting-started.md +9 -3
  6. package/docs/index.md +4 -0
  7. package/extensions/chrome-browser/background.mjs +36 -4
  8. package/extensions/chrome-browser/icons/icon128.png +0 -0
  9. package/extensions/chrome-browser/icons/icon16.png +0 -0
  10. package/extensions/chrome-browser/icons/icon48.png +0 -0
  11. package/extensions/chrome-browser/icons/logo.svg +39 -8
  12. package/extensions/chrome-browser/manifest.json +3 -3
  13. package/extensions/chrome-browser/popup.html +5 -1
  14. package/extensions/chrome-browser/popup.js +13 -0
  15. package/flutter_app/android/app/src/main/AndroidManifest.xml +2 -1
  16. package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  17. package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  18. package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  19. package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  20. package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  21. package/flutter_app/assets/branding/app_icon_1024.png +0 -0
  22. package/flutter_app/assets/branding/app_icon_128.png +0 -0
  23. package/flutter_app/assets/branding/app_icon_192.png +0 -0
  24. package/flutter_app/assets/branding/app_icon_256.png +0 -0
  25. package/flutter_app/assets/branding/app_icon_32.png +0 -0
  26. package/flutter_app/assets/branding/app_icon_512.png +0 -0
  27. package/flutter_app/assets/branding/app_icon_64.png +0 -0
  28. package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
  29. package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
  30. package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
  31. package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
  32. package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
  33. package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
  34. package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
  35. package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
  36. package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
  37. package/flutter_app/assets/branding/tray_icon_template.png +0 -0
  38. package/flutter_app/lib/features/location/location_service.dart +3 -0
  39. package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +391 -382
  40. package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +743 -0
  41. package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +18 -16
  42. package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +19 -18
  43. package/flutter_app/lib/features/onboarding/onboarding_shell.dart +8 -1
  44. package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +16 -13
  45. package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +17 -13
  46. package/flutter_app/lib/main.dart +2 -0
  47. package/flutter_app/lib/main_account_settings.dart +10 -34
  48. package/flutter_app/lib/main_admin.dart +14 -1
  49. package/flutter_app/lib/main_app_shell.dart +377 -340
  50. package/flutter_app/lib/main_chat.dart +707 -227
  51. package/flutter_app/lib/main_controller.dart +197 -42
  52. package/flutter_app/lib/main_devices.dart +436 -4
  53. package/flutter_app/lib/main_integrations.dart +255 -6
  54. package/flutter_app/lib/main_launcher.dart +1 -1
  55. package/flutter_app/lib/main_model_picker.dart +685 -0
  56. package/flutter_app/lib/main_models.dart +212 -0
  57. package/flutter_app/lib/main_navigation.dart +1 -9
  58. package/flutter_app/lib/main_operations.dart +1417 -614
  59. package/flutter_app/lib/main_settings.dart +673 -871
  60. package/flutter_app/lib/main_shared.dart +971 -443
  61. package/flutter_app/lib/main_spacing.dart +4 -4
  62. package/flutter_app/lib/main_theme.dart +22 -14
  63. package/flutter_app/lib/main_unified.dart +5 -72
  64. package/flutter_app/lib/src/android_apk_drop_zone.dart +24 -0
  65. package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +13 -0
  66. package/flutter_app/lib/src/android_apk_drop_zone_web.dart +219 -0
  67. package/flutter_app/lib/src/backend_client.dart +46 -0
  68. package/flutter_app/lib/src/desktop_companion_actions.dart +30 -7
  69. package/flutter_app/lib/src/desktop_companion_io.dart +71 -1
  70. package/flutter_app/lib/src/security/password_strength.dart +84 -0
  71. package/flutter_app/lib/src/stream_renderer.dart +42 -3
  72. package/flutter_app/lib/src/theme/palette.dart +76 -34
  73. package/flutter_app/linux/runner/resources/app_icon.png +0 -0
  74. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  75. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  76. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  77. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  78. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  79. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  80. package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  81. package/flutter_app/pubspec.lock +2 -2
  82. package/flutter_app/pubspec.yaml +7 -1
  83. package/flutter_app/tool/branding_source/neoagent-icon-1024.png +0 -0
  84. package/flutter_app/tool/branding_source/neoagent-icon-128.png +0 -0
  85. package/flutter_app/tool/branding_source/neoagent-icon-16.png +0 -0
  86. package/flutter_app/tool/branding_source/neoagent-icon-180.png +0 -0
  87. package/flutter_app/tool/branding_source/neoagent-icon-192.png +0 -0
  88. package/flutter_app/tool/branding_source/neoagent-icon-256.png +0 -0
  89. package/flutter_app/tool/branding_source/neoagent-icon-32.png +0 -0
  90. package/flutter_app/tool/branding_source/neoagent-icon-48.png +0 -0
  91. package/flutter_app/tool/branding_source/neoagent-icon-512.png +0 -0
  92. package/flutter_app/tool/branding_source/neoagent-icon-64.png +0 -0
  93. package/flutter_app/tool/branding_source/neoagent-icon.svg +43 -0
  94. package/flutter_app/tool/generate_desktop_branding.py +154 -152
  95. package/flutter_app/web/favicon.png +0 -0
  96. package/flutter_app/web/favicon.svg +40 -9
  97. package/flutter_app/web/favicon_light.svg +43 -0
  98. package/flutter_app/web/icons/Icon-192-light.png +0 -0
  99. package/flutter_app/web/icons/Icon-192.png +0 -0
  100. package/flutter_app/web/icons/Icon-512-light.png +0 -0
  101. package/flutter_app/web/icons/Icon-512.png +0 -0
  102. package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
  103. package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
  104. package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
  105. package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
  106. package/flutter_app/windows/runner/main.cpp +7 -1
  107. package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
  108. package/lib/manager.js +445 -83
  109. package/package.json +17 -3
  110. package/runtime/paths.js +3 -1
  111. package/server/admin/access.js +198 -0
  112. package/server/admin/admin.css +268 -0
  113. package/server/admin/admin.js +348 -0
  114. package/server/admin/analytics.js +128 -0
  115. package/server/admin/index.html +1015 -0
  116. package/server/admin/login.html +290 -0
  117. package/server/admin/logo.svg +43 -0
  118. package/server/admin/sql.js +134 -0
  119. package/server/admin/users.js +147 -0
  120. package/server/config/origins.js +3 -1
  121. package/server/db/database.js +92 -0
  122. package/server/db/ftsQuery.js +27 -0
  123. package/server/http/routes.js +1 -0
  124. package/server/http/static.js +23 -6
  125. package/server/index.js +1 -1
  126. package/server/middleware/adminAuth.js +48 -0
  127. package/server/middleware/auth.js +1 -40
  128. package/server/public/.last_build_id +1 -1
  129. package/server/public/app_icon.png +0 -0
  130. package/server/public/assets/AssetManifest.bin +1 -1
  131. package/server/public/assets/AssetManifest.bin.json +1 -1
  132. package/server/public/assets/assets/branding/app_icon_1024.png +0 -0
  133. package/server/public/assets/assets/branding/app_icon_256.png +0 -0
  134. package/server/public/assets/assets/branding/app_icon_512.png +0 -0
  135. package/server/public/assets/assets/branding/app_icon_light_1024.png +0 -0
  136. package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
  137. package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
  138. package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
  139. package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
  140. package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
  141. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  142. package/server/public/assets/web/icons/Icon-192.png +0 -0
  143. package/server/public/favicon.png +0 -0
  144. package/server/public/favicon.svg +40 -9
  145. package/server/public/favicon_light.svg +43 -0
  146. package/server/public/flutter_bootstrap.js +2 -2
  147. package/server/public/icons/Icon-192-light.png +0 -0
  148. package/server/public/icons/Icon-192.png +0 -0
  149. package/server/public/icons/Icon-512-light.png +0 -0
  150. package/server/public/icons/Icon-512.png +0 -0
  151. package/server/public/icons/Icon-maskable-192-light.png +0 -0
  152. package/server/public/icons/Icon-maskable-192.png +0 -0
  153. package/server/public/icons/Icon-maskable-512-light.png +0 -0
  154. package/server/public/icons/Icon-maskable-512.png +0 -0
  155. package/server/public/main.dart.js +88537 -85936
  156. package/server/routes/admin.js +632 -0
  157. package/server/routes/agent_profiles.js +3 -0
  158. package/server/routes/agents.js +1 -1
  159. package/server/routes/auth.js +3 -1
  160. package/server/routes/mcp.js +29 -13
  161. package/server/routes/memory.js +23 -1
  162. package/server/routes/messaging.js +2 -0
  163. package/server/routes/screenHistory.js +14 -8
  164. package/server/routes/settings.js +10 -2
  165. package/server/routes/stream.js +1 -1
  166. package/server/routes/triggers.js +4 -4
  167. package/server/routes/voice_assistant.js +36 -1
  168. package/server/routes/workspace.js +86 -0
  169. package/server/services/account/admin_two_factor.js +132 -0
  170. package/server/services/account/password_policy.js +6 -1
  171. package/server/services/ai/completion.js +44 -0
  172. package/server/services/ai/engine.js +321 -500
  173. package/server/services/ai/imageAnalysis.js +9 -5
  174. package/server/services/ai/logFormat.js +46 -0
  175. package/server/services/ai/loopPolicy.js +11 -0
  176. package/server/services/ai/messagingFallback.js +228 -0
  177. package/server/services/ai/models.js +194 -55
  178. package/server/services/ai/providerRetry.js +169 -0
  179. package/server/services/ai/providers/anthropic.js +15 -4
  180. package/server/services/ai/providers/google.js +38 -11
  181. package/server/services/ai/providers/grok.js +19 -68
  182. package/server/services/ai/providers/grokOauth.js +141 -0
  183. package/server/services/ai/providers/nvidia.js +154 -0
  184. package/server/services/ai/providers/ollama.js +76 -39
  185. package/server/services/ai/providers/openai.js +20 -31
  186. package/server/services/ai/providers/openaiCodex.js +6 -2
  187. package/server/services/ai/providers/openaiCompatible.js +70 -0
  188. package/server/services/ai/providers/openrouter.js +162 -0
  189. package/server/services/ai/settings.js +30 -0
  190. package/server/services/ai/systemPrompt.js +51 -29
  191. package/server/services/ai/taskAnalysis.js +60 -1
  192. package/server/services/ai/toolEvidence.js +207 -0
  193. package/server/services/ai/toolSelector.js +8 -1
  194. package/server/services/ai/tools.js +78 -13
  195. package/server/services/browser/extension/registry.js +94 -9
  196. package/server/services/desktop/registry.js +104 -1
  197. package/server/services/desktop/screenRecorder.js +208 -98
  198. package/server/services/desktop/screen_recorder_support.js +46 -0
  199. package/server/services/integrations/google/provider.js +13 -0
  200. package/server/services/integrations/home_assistant/constants.js +88 -0
  201. package/server/services/integrations/home_assistant/network.js +207 -0
  202. package/server/services/integrations/home_assistant/provider.js +249 -0
  203. package/server/services/integrations/home_assistant/snapshot.js +98 -0
  204. package/server/services/integrations/home_assistant/tools.js +101 -0
  205. package/server/services/integrations/manager.js +5 -0
  206. package/server/services/integrations/registry.js +2 -0
  207. package/server/services/integrations/trello/provider.js +8 -2
  208. package/server/services/manager.js +51 -53
  209. package/server/services/mcp/client.js +208 -268
  210. package/server/services/mcp/client_support.js +172 -0
  211. package/server/services/mcp/recovery.js +116 -0
  212. package/server/services/mcp/tool_operations.js +123 -0
  213. package/server/services/memory/ingestion.js +185 -370
  214. package/server/services/memory/ingestion_coverage.js +129 -0
  215. package/server/services/memory/ingestion_documents.js +123 -0
  216. package/server/services/memory/ingestion_support.js +171 -0
  217. package/server/services/memory/intelligence.js +181 -0
  218. package/server/services/memory/manager.js +476 -32
  219. package/server/services/messaging/automation.js +71 -134
  220. package/server/services/messaging/formatting_guides.js +26 -1
  221. package/server/services/messaging/inbound_queue.js +111 -0
  222. package/server/services/messaging/manager.js +25 -8
  223. package/server/services/messaging/typing_keepalive.js +110 -0
  224. package/server/services/streaming/android-stream.js +293 -40
  225. package/server/services/tasks/integration_runtime.js +4 -1
  226. package/server/services/tasks/runtime.js +415 -56
  227. package/server/services/tasks/task_repository.js +48 -6
  228. package/server/services/websocket.js +8 -2
  229. package/server/services/widgets/service.js +17 -1
  230. package/server/services/workspace/manager.js +116 -0
  231. package/server/utils/logger.js +44 -6
  232. package/server/utils/security.js +3 -0
  233. package/server/utils/version.js +29 -19
  234. package/server/services/memory/openhuman_uplift.test.js +0 -98
@@ -1888,6 +1888,27 @@ class ChatEntry {
1888
1888
  }
1889
1889
  return null;
1890
1890
  }
1891
+
1892
+ ChatRichPayload? get richPayload {
1893
+ final schema = metadata['schema'];
1894
+ if (schema is! Map) return null;
1895
+ final type = schema['type']?.toString() ?? '';
1896
+ if (type != 'quick_reply' && type != 'list_picker') return null;
1897
+ final optList = schema['options'];
1898
+ if (optList is! List) return null;
1899
+ final options = optList
1900
+ .whereType<Map>()
1901
+ .map(
1902
+ (item) => ChatPayloadOption(
1903
+ label: item['label']?.toString() ?? '',
1904
+ value: item['value']?.toString() ?? '',
1905
+ ),
1906
+ )
1907
+ .where((o) => o.label.isNotEmpty)
1908
+ .toList(growable: false);
1909
+ if (options.isEmpty) return null;
1910
+ return ChatRichPayload(type: type, options: options);
1911
+ }
1891
1912
  }
1892
1913
 
1893
1914
  class SharedChatAttachment {
@@ -2015,6 +2036,7 @@ class ModelMeta {
2015
2036
  this.available = true,
2016
2037
  this.providerStatus = '',
2017
2038
  this.providerStatusLabel = '',
2039
+ this.priceTier,
2018
2040
  });
2019
2041
 
2020
2042
  factory ModelMeta.fromJson(Map<dynamic, dynamic> json) {
@@ -2026,6 +2048,7 @@ class ModelMeta {
2026
2048
  available: json['available'] != false,
2027
2049
  providerStatus: json['providerStatus']?.toString() ?? '',
2028
2050
  providerStatusLabel: json['providerStatusLabel']?.toString() ?? '',
2051
+ priceTier: json['priceTier']?.toString(),
2029
2052
  );
2030
2053
  }
2031
2054
 
@@ -2036,6 +2059,8 @@ class ModelMeta {
2036
2059
  final bool available;
2037
2060
  final String providerStatus;
2038
2061
  final String providerStatusLabel;
2062
+ /// Pricing tier: 'free' | 'cheap' | 'medium' | 'expensive' | null (unknown)
2063
+ final String? priceTier;
2039
2064
  }
2040
2065
 
2041
2066
  class AiProviderConfig {
@@ -2861,6 +2886,10 @@ class MemoryOverview {
2861
2886
  this.dailyLogs = const <String>[],
2862
2887
  this.apiKeys = const <String, String>{},
2863
2888
  this.coreEntries = const <String, dynamic>{},
2889
+ this.stats = const MemoryStats(),
2890
+ this.entities = const <MemoryEntity>[],
2891
+ this.knowledgeViews = const <KnowledgeViewItem>[],
2892
+ this.recentKnowledgeChanges = const <KnowledgeChangeItem>[],
2864
2893
  });
2865
2894
 
2866
2895
  factory MemoryOverview.fromJson(Map<dynamic, dynamic> json) {
@@ -2880,6 +2909,16 @@ class MemoryOverview {
2880
2909
  coreEntries: coreRaw is Map
2881
2910
  ? Map<String, dynamic>.from(coreRaw)
2882
2911
  : const <String, dynamic>{},
2912
+ stats: MemoryStats.fromJson(_jsonMap(json['stats'])),
2913
+ entities: _jsonMapList(
2914
+ json['entities'],
2915
+ ).map(MemoryEntity.fromJson).toList(),
2916
+ knowledgeViews: _jsonMapList(
2917
+ json['knowledgeViews'],
2918
+ ).map(KnowledgeViewItem.fromJson).toList(),
2919
+ recentKnowledgeChanges: _jsonMapList(
2920
+ json['recentKnowledgeChanges'],
2921
+ ).map(KnowledgeChangeItem.fromJson).toList(),
2883
2922
  );
2884
2923
  }
2885
2924
 
@@ -2887,6 +2926,10 @@ class MemoryOverview {
2887
2926
  final List<String> dailyLogs;
2888
2927
  final Map<String, String> apiKeys;
2889
2928
  final Map<String, dynamic> coreEntries;
2929
+ final MemoryStats stats;
2930
+ final List<MemoryEntity> entities;
2931
+ final List<KnowledgeViewItem> knowledgeViews;
2932
+ final List<KnowledgeChangeItem> recentKnowledgeChanges;
2890
2933
 
2891
2934
  int get behaviorNotesLength => assistantBehaviorNotes.length;
2892
2935
  int get dailyLogCount => dailyLogs.length;
@@ -2894,6 +2937,112 @@ class MemoryOverview {
2894
2937
  int get coreCount => coreEntries.length;
2895
2938
  }
2896
2939
 
2940
+ class MemoryStats {
2941
+ const MemoryStats({
2942
+ this.total = 0,
2943
+ this.active = 0,
2944
+ this.archived = 0,
2945
+ this.facts = 0,
2946
+ this.entities = 0,
2947
+ this.knowledgeViews = 0,
2948
+ this.ingestionDocuments = 0,
2949
+ this.averageImportance = 0,
2950
+ this.averageConfidence = 0,
2951
+ });
2952
+
2953
+ factory MemoryStats.fromJson(Map<dynamic, dynamic> json) {
2954
+ return MemoryStats(
2955
+ total: _asInt(json['total']),
2956
+ active: _asInt(json['active']),
2957
+ archived: _asInt(json['archived']),
2958
+ facts: _asInt(json['facts']),
2959
+ entities: _asInt(json['entities']),
2960
+ knowledgeViews: _asInt(json['knowledgeViews']),
2961
+ ingestionDocuments: _asInt(json['ingestionDocuments']),
2962
+ averageImportance: _asDouble(json['averageImportance']),
2963
+ averageConfidence: _asDouble(json['averageConfidence']),
2964
+ );
2965
+ }
2966
+
2967
+ final int total;
2968
+ final int active;
2969
+ final int archived;
2970
+ final int facts;
2971
+ final int entities;
2972
+ final int knowledgeViews;
2973
+ final int ingestionDocuments;
2974
+ final double averageImportance;
2975
+ final double averageConfidence;
2976
+ }
2977
+
2978
+ class MemoryEntity {
2979
+ const MemoryEntity({
2980
+ required this.id,
2981
+ required this.key,
2982
+ required this.name,
2983
+ required this.kind,
2984
+ required this.mentionCount,
2985
+ });
2986
+
2987
+ factory MemoryEntity.fromJson(Map<dynamic, dynamic> json) {
2988
+ return MemoryEntity(
2989
+ id: json['id']?.toString() ?? '',
2990
+ key: json['key']?.toString() ?? '',
2991
+ name: json['name']?.toString() ?? '',
2992
+ kind: json['kind']?.toString().ifEmpty('concept') ?? 'concept',
2993
+ mentionCount: _asInt(json['mentionCount']),
2994
+ );
2995
+ }
2996
+
2997
+ final String id;
2998
+ final String key;
2999
+ final String name;
3000
+ final String kind;
3001
+ final int mentionCount;
3002
+ }
3003
+
3004
+ class KnowledgeViewItem {
3005
+ const KnowledgeViewItem({
3006
+ required this.title,
3007
+ required this.viewType,
3008
+ required this.summary,
3009
+ });
3010
+
3011
+ factory KnowledgeViewItem.fromJson(Map<dynamic, dynamic> json) {
3012
+ return KnowledgeViewItem(
3013
+ title:
3014
+ json['title']?.toString().ifEmpty('Knowledge view') ??
3015
+ 'Knowledge view',
3016
+ viewType: json['viewType']?.toString().ifEmpty('view') ?? 'view',
3017
+ summary: json['summary']?.toString() ?? '',
3018
+ );
3019
+ }
3020
+
3021
+ final String title;
3022
+ final String viewType;
3023
+ final String summary;
3024
+ }
3025
+
3026
+ class KnowledgeChangeItem {
3027
+ const KnowledgeChangeItem({
3028
+ required this.title,
3029
+ required this.kind,
3030
+ required this.summary,
3031
+ });
3032
+
3033
+ factory KnowledgeChangeItem.fromJson(Map<dynamic, dynamic> json) {
3034
+ return KnowledgeChangeItem(
3035
+ title: json['title']?.toString().ifEmpty('Change') ?? 'Change',
3036
+ kind: json['kind']?.toString().ifEmpty('change') ?? 'change',
3037
+ summary: json['summary']?.toString() ?? '',
3038
+ );
3039
+ }
3040
+
3041
+ final String title;
3042
+ final String kind;
3043
+ final String summary;
3044
+ }
3045
+
2897
3046
  class MemoryItem {
2898
3047
  const MemoryItem({
2899
3048
  required this.id,
@@ -2901,25 +3050,45 @@ class MemoryItem {
2901
3050
  required this.category,
2902
3051
  required this.importance,
2903
3052
  required this.createdAt,
3053
+ this.summary = '',
3054
+ this.confidence = 0.7,
3055
+ this.entities = const <MemoryEntity>[],
3056
+ this.score,
2904
3057
  });
2905
3058
 
2906
3059
  factory MemoryItem.fromJson(Map<dynamic, dynamic> json) {
2907
3060
  return MemoryItem(
2908
3061
  id: json['id']?.toString() ?? '',
2909
3062
  content: json['content']?.toString() ?? '',
3063
+ summary: json['summary']?.toString() ?? '',
2910
3064
  category: json['category']?.toString().ifEmpty('memory') ?? 'memory',
2911
3065
  importance: _asInt(json['importance']),
3066
+ confidence: _asDouble(json['confidence'], fallback: 0.7),
2912
3067
  createdAt: _parseTimestamp(json['created_at']?.toString()),
3068
+ entities: _jsonMapList(
3069
+ json['entities'],
3070
+ ).map(MemoryEntity.fromJson).toList(),
3071
+ score: (() {
3072
+ final raw = json['score'];
3073
+ if (raw == null) return null;
3074
+ if (raw is num) return raw.toDouble();
3075
+ return double.tryParse(raw.toString());
3076
+ })(),
2913
3077
  );
2914
3078
  }
2915
3079
 
2916
3080
  final String id;
2917
3081
  final String content;
3082
+ final String summary;
2918
3083
  final String category;
2919
3084
  final int importance;
3085
+ final double confidence;
2920
3086
  final DateTime createdAt;
3087
+ final List<MemoryEntity> entities;
3088
+ final double? score;
2921
3089
 
2922
3090
  String get createdAtLabel => _formatTimestamp(createdAt);
3091
+ int get confidencePercent => (confidence * 100).round().clamp(0, 100);
2923
3092
  }
2924
3093
 
2925
3094
  class ConversationItem {
@@ -2955,6 +3124,9 @@ class TaskItem {
2955
3124
  required this.model,
2956
3125
  required this.enabled,
2957
3126
  required this.lastRun,
3127
+ required this.lastRunId,
3128
+ required this.lastRunStatus,
3129
+ required this.lastRunError,
2958
3130
  required this.taskType,
2959
3131
  required this.widgetId,
2960
3132
  });
@@ -3000,6 +3172,9 @@ class TaskItem {
3000
3172
  '',
3001
3173
  enabled: json['enabled'] != false,
3002
3174
  lastRun: _parseOptionalTimestamp(json['lastRun']?.toString()),
3175
+ lastRunId: json['lastRunId']?.toString() ?? '',
3176
+ lastRunStatus: json['lastRunStatus']?.toString() ?? '',
3177
+ lastRunError: json['lastRunError']?.toString() ?? '',
3003
3178
  taskType:
3004
3179
  json['taskType']?.toString().ifEmpty(
3005
3180
  json['task_type']?.toString() ?? 'agent_prompt',
@@ -3024,12 +3199,20 @@ class TaskItem {
3024
3199
  final String model;
3025
3200
  final bool enabled;
3026
3201
  final DateTime? lastRun;
3202
+ final String lastRunId;
3203
+ final String lastRunStatus;
3204
+ final String lastRunError;
3027
3205
  final String taskType;
3028
3206
  final String widgetId;
3029
3207
 
3030
3208
  String get scheduleLabel =>
3031
3209
  triggerSummary.trim().isEmpty ? 'Task trigger' : triggerSummary;
3032
3210
  String get lastRunLabel => lastRun == null ? '' : _formatTimestamp(lastRun!);
3211
+ String get lastRunStatusLabel =>
3212
+ _titleCase(lastRunStatus.replaceAll('_', ' '));
3213
+ bool get hasLastRunStatus => lastRunStatus.trim().isNotEmpty;
3214
+ bool get lastRunFailed =>
3215
+ lastRunStatus == 'failed' || lastRunStatus == 'error';
3033
3216
  bool get hasModelOverride => model.trim().isNotEmpty;
3034
3217
  bool get isWidgetRefresh => taskType == 'widget_refresh';
3035
3218
  }
@@ -3239,6 +3422,9 @@ class McpServerItem {
3239
3422
  required this.enabled,
3240
3423
  required this.status,
3241
3424
  required this.toolCount,
3425
+ required this.error,
3426
+ required this.consecutiveFails,
3427
+ required this.nextRetryAt,
3242
3428
  });
3243
3429
 
3244
3430
  factory McpServerItem.fromJson(Map<dynamic, dynamic> json) {
@@ -3253,6 +3439,9 @@ class McpServerItem {
3253
3439
  enabled: json['enabled'] == true,
3254
3440
  status: json['status']?.toString().ifEmpty('stopped') ?? 'stopped',
3255
3441
  toolCount: _asInt(json['toolCount']),
3442
+ error: json['error']?.toString(),
3443
+ consecutiveFails: _asInt(json['consecutiveFails']),
3444
+ nextRetryAt: _parseOptionalTimestamp(json['nextRetryAt']?.toString()),
3256
3445
  );
3257
3446
  }
3258
3447
 
@@ -3264,6 +3453,14 @@ class McpServerItem {
3264
3453
  final bool enabled;
3265
3454
  final String status;
3266
3455
  final int toolCount;
3456
+ final String? error;
3457
+ final int consecutiveFails;
3458
+ final DateTime? nextRetryAt;
3459
+
3460
+ bool get hasError => (error ?? '').trim().isNotEmpty;
3461
+ String get retryLabel => nextRetryAt == null
3462
+ ? ''
3463
+ : 'Next retry: ${_formatTimestamp(nextRetryAt!)}';
3267
3464
 
3268
3465
  String get authMethodLabel {
3269
3466
  final auth = _jsonMap(config['auth']);
@@ -3865,3 +4062,18 @@ class ToolEventItem {
3865
4062
 
3866
4063
  String get compactSummary => _condenseRunText(summary, maxLength: 120);
3867
4064
  }
4065
+
4066
+ class ChatPayloadOption {
4067
+ const ChatPayloadOption({required this.label, required this.value});
4068
+
4069
+ final String label;
4070
+ final String value;
4071
+ }
4072
+
4073
+ class ChatRichPayload {
4074
+ const ChatRichPayload({required this.type, required this.options});
4075
+
4076
+ final String type;
4077
+ final List<ChatPayloadOption> options;
4078
+ }
4079
+
@@ -21,7 +21,6 @@ enum AppSection {
21
21
  runs,
22
22
  settings,
23
23
  accountSettings,
24
- logs,
25
24
  skills,
26
25
  agents,
27
26
  integrations,
@@ -76,13 +75,11 @@ extension AppSectionX on AppSection {
76
75
  case AppSection.messaging:
77
76
  return 'Messaging';
78
77
  case AppSection.runs:
79
- return 'Runs & Logs';
78
+ return 'Runs';
80
79
  case AppSection.settings:
81
80
  return 'Settings';
82
81
  case AppSection.accountSettings:
83
82
  return 'Account settings';
84
- case AppSection.logs:
85
- return 'Logs';
86
83
  case AppSection.skills:
87
84
  return 'Skills';
88
85
  case AppSection.agents:
@@ -120,8 +117,6 @@ extension AppSectionX on AppSection {
120
117
  return Icons.tune;
121
118
  case AppSection.accountSettings:
122
119
  return Icons.manage_accounts_outlined;
123
- case AppSection.logs:
124
- return Icons.article_outlined;
125
120
  case AppSection.skills:
126
121
  return Icons.extension_outlined;
127
122
  case AppSection.agents:
@@ -158,7 +153,6 @@ extension AppSectionX on AppSection {
158
153
  case AppSection.health:
159
154
  return SidebarGroup.automation;
160
155
  case AppSection.runs:
161
- case AppSection.logs:
162
156
  case AppSection.settings:
163
157
  case AppSection.accountSettings:
164
158
  case AppSection.messaging:
@@ -169,8 +163,6 @@ extension AppSectionX on AppSection {
169
163
 
170
164
  AppSection get canonicalSection {
171
165
  switch (this) {
172
- case AppSection.logs:
173
- return AppSection.runs;
174
166
  case AppSection.skills:
175
167
  case AppSection.mcp:
176
168
  return AppSection.integrations;