neoagent 3.1.1-beta.2 → 3.1.1-beta.4

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 (53) hide show
  1. package/extensions/chrome-browser/manifest.json +1 -1
  2. package/extensions/chrome-browser/protocol.mjs +36 -0
  3. package/flutter_app/lib/main_app_shell.dart +9 -3
  4. package/flutter_app/lib/main_controller.dart +49 -0
  5. package/flutter_app/lib/main_models.dart +55 -0
  6. package/flutter_app/lib/main_operations.dart +530 -2
  7. package/flutter_app/lib/main_settings.dart +301 -1
  8. package/flutter_app/lib/main_shared.dart +7 -2
  9. package/flutter_app/lib/main_timeline.dart +82 -11
  10. package/flutter_app/lib/src/backend_client.dart +50 -0
  11. package/landing/index.html +3 -0
  12. package/landing/status.html +178 -0
  13. package/lib/schema_migrations.js +23 -0
  14. package/package.json +1 -1
  15. package/server/db/database.js +6 -0
  16. package/server/http/routes.js +2 -0
  17. package/server/http/static.js +1 -0
  18. package/server/public/.last_build_id +1 -1
  19. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  20. package/server/public/flutter_bootstrap.js +1 -1
  21. package/server/public/main.dart.js +76806 -75964
  22. package/server/routes/public_status.js +12 -0
  23. package/server/routes/settings.js +14 -0
  24. package/server/routes/social_reach.js +88 -0
  25. package/server/routes/tasks.js +17 -0
  26. package/server/services/ai/tools.js +60 -1
  27. package/server/services/browser/extension/protocol.js +1 -0
  28. package/server/services/manager.js +14 -0
  29. package/server/services/memory/consolidation.js +2 -0
  30. package/server/services/memory/manager.js +70 -8
  31. package/server/services/memory/retention.js +66 -0
  32. package/server/services/memory/routing.js +68 -0
  33. package/server/services/messaging/access_policy.js +39 -2
  34. package/server/services/messaging/manager.js +9 -4
  35. package/server/services/public_status.js +103 -0
  36. package/server/services/runtime/settings.js +6 -0
  37. package/server/services/social_reach/channels/base.js +56 -0
  38. package/server/services/social_reach/channels/github.js +75 -0
  39. package/server/services/social_reach/channels/index.js +34 -0
  40. package/server/services/social_reach/channels/linkedin.js +34 -0
  41. package/server/services/social_reach/channels/rss.js +58 -0
  42. package/server/services/social_reach/channels/unsupported.js +49 -0
  43. package/server/services/social_reach/channels/v2ex.js +85 -0
  44. package/server/services/social_reach/channels/web.js +40 -0
  45. package/server/services/social_reach/channels/xueqiu.js +101 -0
  46. package/server/services/social_reach/channels/youtube.js +42 -0
  47. package/server/services/social_reach/index.js +7 -0
  48. package/server/services/social_reach/platforms.js +162 -0
  49. package/server/services/social_reach/service.js +163 -0
  50. package/server/services/social_reach/store.js +89 -0
  51. package/server/services/social_reach/utils.js +95 -0
  52. package/server/services/tasks/delivery_targets.js +260 -0
  53. package/server/utils/whatsapp.js +33 -1
@@ -5,7 +5,7 @@
5
5
  "version_name": "2.4.1-beta.8",
6
6
  "description": "Connect this Chrome browser to NeoAgent for browser automation.",
7
7
  "minimum_chrome_version": "118",
8
- "permissions": ["alarms", "debugger", "storage", "tabs"],
8
+ "permissions": ["alarms", "cookies", "debugger", "storage", "tabs"],
9
9
  "host_permissions": ["http://*/*", "https://*/*"],
10
10
  "icons": {
11
11
  "16": "icons/icon16.png",
@@ -12,6 +12,7 @@ export const COMMANDS = Object.freeze({
12
12
  SCREENSHOT: 'screenshot',
13
13
  CLOSE: 'close',
14
14
  GET_PAGE_INFO: 'getPageInfo',
15
+ GET_COOKIES: 'getCookies',
15
16
  });
16
17
 
17
18
  function chromeCall(chromeApi, namespace, method, ...args) {
@@ -221,6 +222,41 @@ export function createBrowserProtocol(chromeApi) {
221
222
 
222
223
  async function run(command, payload = {}) {
223
224
  switch (command) {
225
+ case COMMANDS.GET_COOKIES: {
226
+ const domains = Array.isArray(payload.domains)
227
+ ? payload.domains.map((item) => String(item || '').replace(/^\./, '').toLowerCase()).filter(Boolean)
228
+ : [];
229
+ if (domains.length === 0) throw new Error('At least one cookie domain is required.');
230
+ const all = [];
231
+ for (const domain of domains) {
232
+ const cookies = await chromeCall(chromeApi, 'cookies', 'getAll', { domain });
233
+ all.push(...(Array.isArray(cookies) ? cookies : []));
234
+ }
235
+ const seen = new Set();
236
+ const filtered = all.filter((cookie) => {
237
+ const cookieDomain = String(cookie?.domain || '').replace(/^\./, '').toLowerCase();
238
+ const allowed = domains.some((domain) => cookieDomain === domain || cookieDomain.endsWith(`.${domain}`));
239
+ if (!allowed) return false;
240
+ const key = `${cookie.name}\n${cookie.domain}\n${cookie.path}`;
241
+ if (seen.has(key)) return false;
242
+ seen.add(key);
243
+ return true;
244
+ });
245
+ return {
246
+ platform: String(payload.platform || ''),
247
+ domains,
248
+ cookies: filtered.map((cookie) => ({
249
+ name: cookie.name,
250
+ value: cookie.value,
251
+ domain: cookie.domain,
252
+ path: cookie.path,
253
+ secure: cookie.secure === true,
254
+ httpOnly: cookie.httpOnly === true,
255
+ sameSite: cookie.sameSite || null,
256
+ expirationDate: cookie.expirationDate || null,
257
+ })),
258
+ };
259
+ }
224
260
  case COMMANDS.LAUNCH:
225
261
  await attach();
226
262
  return pageSnapshot({ screenshot: false });
@@ -357,8 +357,9 @@ class _LocalInstallWidgetState extends State<_LocalInstallWidget> {
357
357
  if (!mounted) return;
358
358
  setState(() {
359
359
  _phase = exit == 0 ? _LocalInstallPhase.done : _LocalInstallPhase.failed;
360
- if (exit != 0)
360
+ if (exit != 0) {
361
361
  _errorMsg = 'Installation failed (exit $exit). Check the log above.';
362
+ }
362
363
  });
363
364
  }
364
365
 
@@ -471,8 +472,9 @@ class _LocalInstallWidgetState extends State<_LocalInstallWidget> {
471
472
  final proc = _proc;
472
473
  proc?.kill(ProcessSignal.sigterm);
473
474
  await proc?.exitCode;
474
- if (mounted)
475
+ if (mounted) {
475
476
  setState(() => _phase = _LocalInstallPhase.ready);
477
+ }
476
478
  },
477
479
  child: const Text('Cancel'),
478
480
  ),
@@ -1607,7 +1609,11 @@ class _HomeViewState extends State<HomeView> {
1607
1609
  titleSpacing: 0,
1608
1610
  leadingWidth: 44,
1609
1611
  centerTitle: false,
1610
- title: Text(controller.selectedSection.navigationTitle),
1612
+ title: Text(
1613
+ controller.selectedSection.navigationTitle,
1614
+ maxLines: 1,
1615
+ overflow: TextOverflow.ellipsis,
1616
+ ),
1611
1617
  titleTextStyle: Theme.of(
1612
1618
  context,
1613
1619
  ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
@@ -182,6 +182,7 @@ class NeoAgentController extends ChangeNotifier {
182
182
  List<AiWidgetItem> widgets = const <AiWidgetItem>[];
183
183
  List<McpServerItem> mcpServers = const <McpServerItem>[];
184
184
  Map<String, dynamic> browserRuntime = const <String, dynamic>{};
185
+ Map<String, dynamic> socialReachStatus = const <String, dynamic>{};
185
186
  Map<String, dynamic> browserExtensionStatus = const <String, dynamic>{};
186
187
  List<Map<String, dynamic>> browserExtensionTokens =
187
188
  const <Map<String, dynamic>>[];
@@ -2316,6 +2317,9 @@ class NeoAgentController extends ChangeNotifier {
2316
2317
  final browserFuture = _backendClient
2317
2318
  .fetchBrowserStatus(backendUrl)
2318
2319
  .catchError((_) => const <String, dynamic>{});
2320
+ final socialReachFuture = _backendClient
2321
+ .fetchSocialReachStatus(backendUrl)
2322
+ .catchError((_) => const <String, dynamic>{});
2319
2323
  final browserExtensionFuture = _backendClient
2320
2324
  .fetchBrowserExtensionStatus(backendUrl)
2321
2325
  .catchError((_) => const <String, dynamic>{});
@@ -2371,6 +2375,7 @@ class NeoAgentController extends ChangeNotifier {
2371
2375
  final mcpResponse = await mcpFuture;
2372
2376
  final recordingsResponse = await recordingsFuture;
2373
2377
  final browserResponse = await browserFuture;
2378
+ final socialReachResponse = await socialReachFuture;
2374
2379
  final browserExtensionResponse = await browserExtensionFuture;
2375
2380
  final androidResponse = await androidFuture;
2376
2381
  final desktopResponse = await desktopFuture;
@@ -2468,6 +2473,7 @@ class NeoAgentController extends ChangeNotifier {
2468
2473
  RecordingSessionItem.fromJson,
2469
2474
  );
2470
2475
  browserRuntime = Map<String, dynamic>.from(browserResponse);
2476
+ socialReachStatus = Map<String, dynamic>.from(socialReachResponse);
2471
2477
  browserExtensionStatus = Map<String, dynamic>.from(
2472
2478
  browserExtensionResponse,
2473
2479
  );
@@ -2796,6 +2802,23 @@ class NeoAgentController extends ChangeNotifier {
2796
2802
  notifyListeners();
2797
2803
  }
2798
2804
 
2805
+ Future<List<TaskDeliveryTarget>> fetchTaskDeliveryTargets({
2806
+ String? query,
2807
+ String? platform,
2808
+ String? agentId,
2809
+ }) async {
2810
+ final rows = await _backendClient.fetchTaskDeliveryTargets(
2811
+ backendUrl,
2812
+ query: query,
2813
+ platform: platform,
2814
+ agentId: agentId ?? _scopedAgentId,
2815
+ );
2816
+ return rows
2817
+ .map(TaskDeliveryTarget.fromJson)
2818
+ .where((target) => target.platform.isNotEmpty && target.to.isNotEmpty)
2819
+ .toList(growable: false);
2820
+ }
2821
+
2799
2822
  Future<void> refreshWidgets({bool all = false}) async {
2800
2823
  widgets = _decodeModelList(
2801
2824
  'widgets',
@@ -5875,6 +5898,32 @@ class NeoAgentController extends ChangeNotifier {
5875
5898
  }
5876
5899
  }
5877
5900
 
5901
+ Future<Map<String, dynamic>> refreshSocialReachStatus() async {
5902
+ final response = await _backendClient.fetchSocialReachStatus(backendUrl);
5903
+ socialReachStatus = Map<String, dynamic>.from(response);
5904
+ notifyListeners();
5905
+ return socialReachStatus;
5906
+ }
5907
+
5908
+ Future<Map<String, dynamic>> importSocialReachCookies(String platform) async {
5909
+ final response = await _backendClient.importSocialReachCookies(
5910
+ backendUrl,
5911
+ platform,
5912
+ tokenId: selectedBrowserExtensionTokenId,
5913
+ );
5914
+ await refreshSocialReachStatus();
5915
+ return response;
5916
+ }
5917
+
5918
+ Future<Map<String, dynamic>> clearSocialReachCookies(String platform) async {
5919
+ final response = await _backendClient.clearSocialReachCookies(
5920
+ backendUrl,
5921
+ platform,
5922
+ );
5923
+ await refreshSocialReachStatus();
5924
+ return response;
5925
+ }
5926
+
5878
5927
  Future<void> disconnectMessagingPlatform(String platform) async {
5879
5928
  final busyKey = '$platform:disconnect';
5880
5929
  if (_busyMessagingPlatformKeys.contains(busyKey)) {
@@ -643,6 +643,61 @@ class MessagingMessage {
643
643
  }
644
644
  }
645
645
 
646
+ class TaskDeliveryTarget {
647
+ const TaskDeliveryTarget({
648
+ required this.platform,
649
+ required this.platformLabel,
650
+ required this.to,
651
+ required this.label,
652
+ required this.subtitle,
653
+ required this.source,
654
+ required this.connected,
655
+ required this.supportsDelivery,
656
+ });
657
+
658
+ factory TaskDeliveryTarget.fromJson(Map<dynamic, dynamic> json) {
659
+ final platform = json['platform']?.toString() ?? '';
660
+ final to = json['to']?.toString() ?? '';
661
+ return TaskDeliveryTarget(
662
+ platform: platform,
663
+ platformLabel:
664
+ json['platformLabel']?.toString().ifEmpty(platform.toUpperCase()) ??
665
+ platform.toUpperCase(),
666
+ to: to,
667
+ label: json['label']?.toString().ifEmpty(to) ?? to,
668
+ subtitle: json['subtitle']?.toString() ?? '',
669
+ source: json['source']?.toString().ifEmpty('discovered') ?? 'discovered',
670
+ connected: json['connected'] != false,
671
+ supportsDelivery: json['supportsDelivery'] != false,
672
+ );
673
+ }
674
+
675
+ final String platform;
676
+ final String platformLabel;
677
+ final String to;
678
+ final String label;
679
+ final String subtitle;
680
+ final String source;
681
+ final bool connected;
682
+ final bool supportsDelivery;
683
+
684
+ String get id => '$platform:$to';
685
+ bool get selectable => connected && supportsDelivery;
686
+
687
+ String get sourceLabel {
688
+ switch (source) {
689
+ case 'default':
690
+ return 'Default';
691
+ case 'recent':
692
+ return 'Recent';
693
+ case 'manual':
694
+ return 'Manual';
695
+ default:
696
+ return 'Discovered';
697
+ }
698
+ }
699
+ }
700
+
646
701
  class MessagingQrState {
647
702
  const MessagingQrState({required this.platform, required this.qr});
648
703