neoagent 2.3.1-beta.85 → 2.3.1-beta.87

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/docs/capabilities.md +2 -0
  2. package/flutter_app/android/app/src/main/AndroidManifest.xml +14 -0
  3. package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +84 -0
  4. package/flutter_app/lib/main_chat.dart +156 -2
  5. package/flutter_app/lib/main_controller.dart +137 -10
  6. package/flutter_app/lib/main_models.dart +69 -0
  7. package/flutter_app/lib/main_operations.dart +248 -0
  8. package/flutter_app/lib/main_runtime.dart +11 -2
  9. package/flutter_app/lib/main_settings.dart +173 -176
  10. package/flutter_app/lib/main_shared.dart +78 -0
  11. package/flutter_app/lib/src/app_launch_bridge.dart +39 -10
  12. package/flutter_app/lib/src/backend_client.dart +28 -0
  13. package/package.json +1 -1
  14. package/server/guest-agent.android.package.json +13 -0
  15. package/server/guest-agent.browser.package.json +14 -0
  16. package/server/guest_agent.js +61 -44
  17. package/server/http/routes.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 +69936 -69277
  22. package/server/routes/android.js +2 -11
  23. package/server/routes/browser.js +2 -2
  24. package/server/routes/memory.js +90 -0
  25. package/server/routes/social_video.js +62 -0
  26. package/server/services/ai/capabilityHealth.js +6 -14
  27. package/server/services/ai/systemPrompt.js +1 -0
  28. package/server/services/ai/toolResult.js +20 -0
  29. package/server/services/ai/tools.js +29 -0
  30. package/server/services/android/android_bootstrap_worker.js +2 -2
  31. package/server/services/android/controller.js +528 -132
  32. package/server/services/browser/controller.js +51 -68
  33. package/server/services/manager.js +15 -0
  34. package/server/services/memory/llm_transfer.js +217 -0
  35. package/server/services/runtime/backends/local-vm.js +16 -3
  36. package/server/services/runtime/guest_bootstrap.js +224 -56
  37. package/server/services/runtime/manager.js +53 -15
  38. package/server/services/runtime/qemu.js +149 -24
  39. package/server/services/runtime/settings.js +9 -14
  40. package/server/services/runtime/validation.js +10 -11
  41. package/server/services/social_video/adapters/base.js +26 -0
  42. package/server/services/social_video/adapters/index.js +27 -0
  43. package/server/services/social_video/adapters/instagram.js +17 -0
  44. package/server/services/social_video/adapters/tiktok.js +17 -0
  45. package/server/services/social_video/adapters/x.js +17 -0
  46. package/server/services/social_video/adapters/youtube.js +17 -0
  47. package/server/services/social_video/captions.js +187 -0
  48. package/server/services/social_video/frame.js +42 -0
  49. package/server/services/social_video/index.js +7 -0
  50. package/server/services/social_video/metadata.js +63 -0
  51. package/server/services/social_video/result.js +63 -0
  52. package/server/services/social_video/service.js +576 -0
  53. package/server/services/social_video/url.js +83 -0
  54. package/server/utils/deployment.js +4 -4
  55. package/server/guest-agent.package.json +0 -15
@@ -1242,21 +1242,157 @@ class MemoryPanel extends StatefulWidget {
1242
1242
 
1243
1243
  class _MemoryPanelState extends State<MemoryPanel> {
1244
1244
  late final TextEditingController _searchController;
1245
+ late final TextEditingController _llmPromptController;
1246
+ late final TextEditingController _llmImportController;
1245
1247
  final Set<String> _selectedMemoryIds = <String>{};
1246
1248
  bool _bulkActionInFlight = false;
1249
+ bool _llmPromptLoading = false;
1250
+ bool _llmImporting = false;
1251
+ bool _llmApplyBehaviorNotes = true;
1252
+ bool _llmApplyCoreMemory = true;
1247
1253
 
1248
1254
  @override
1249
1255
  void initState() {
1250
1256
  super.initState();
1251
1257
  _searchController = TextEditingController();
1258
+ _llmPromptController = TextEditingController();
1259
+ _llmImportController = TextEditingController();
1252
1260
  }
1253
1261
 
1254
1262
  @override
1255
1263
  void dispose() {
1256
1264
  _searchController.dispose();
1265
+ _llmPromptController.dispose();
1266
+ _llmImportController.dispose();
1257
1267
  super.dispose();
1258
1268
  }
1259
1269
 
1270
+ Future<void> _loadLlmPrompt(NeoAgentController controller) async {
1271
+ if (_llmPromptLoading) {
1272
+ return;
1273
+ }
1274
+ setState(() {
1275
+ _llmPromptLoading = true;
1276
+ });
1277
+ try {
1278
+ final prompt = await controller.fetchMemoryTransferPrompt();
1279
+ if (!mounted) {
1280
+ return;
1281
+ }
1282
+ setState(() {
1283
+ _llmPromptController.text = prompt;
1284
+ });
1285
+ } catch (error) {
1286
+ if (!mounted) {
1287
+ return;
1288
+ }
1289
+ ScaffoldMessenger.of(context).showSnackBar(
1290
+ SnackBar(content: Text('Failed to generate prompt: $error')),
1291
+ );
1292
+ } finally {
1293
+ if (mounted) {
1294
+ setState(() {
1295
+ _llmPromptLoading = false;
1296
+ });
1297
+ }
1298
+ }
1299
+ }
1300
+
1301
+ Future<void> _copyLlmPrompt() async {
1302
+ final prompt = _llmPromptController.text.trim();
1303
+ if (prompt.isEmpty) {
1304
+ return;
1305
+ }
1306
+ await Clipboard.setData(ClipboardData(text: prompt));
1307
+ if (!mounted) {
1308
+ return;
1309
+ }
1310
+ ScaffoldMessenger.of(
1311
+ context,
1312
+ ).showSnackBar(const SnackBar(content: Text('Prompt copied.')));
1313
+ }
1314
+
1315
+ Future<void> _importLlmMemories(NeoAgentController controller) async {
1316
+ if (_llmImporting) {
1317
+ return;
1318
+ }
1319
+ final text = _llmImportController.text.trim();
1320
+ if (text.isEmpty) {
1321
+ return;
1322
+ }
1323
+ final confirmImport = await showDialog<bool>(
1324
+ context: context,
1325
+ builder: (context) {
1326
+ final applyTargets = <String>[
1327
+ if (_llmApplyBehaviorNotes) 'behavior notes',
1328
+ if (_llmApplyCoreMemory) 'core memory',
1329
+ 'memories',
1330
+ ];
1331
+ final targetLabel = applyTargets.join(', ');
1332
+ return AlertDialog(
1333
+ backgroundColor: _bgCard,
1334
+ title: Text('Import memory transfer?'),
1335
+ content: Text(
1336
+ 'This will import the response into $targetLabel.',
1337
+ ),
1338
+ actions: <Widget>[
1339
+ TextButton(
1340
+ onPressed: () => Navigator.of(context).pop(false),
1341
+ child: Text('Cancel'),
1342
+ ),
1343
+ FilledButton(
1344
+ onPressed: () => Navigator.of(context).pop(true),
1345
+ child: Text('Import'),
1346
+ ),
1347
+ ],
1348
+ );
1349
+ },
1350
+ );
1351
+ if (confirmImport != true) {
1352
+ return;
1353
+ }
1354
+ setState(() {
1355
+ _llmImporting = true;
1356
+ });
1357
+ try {
1358
+ final result = await controller.importMemoryTransfer(
1359
+ text,
1360
+ applyBehaviorNotes: _llmApplyBehaviorNotes,
1361
+ applyCoreMemory: _llmApplyCoreMemory,
1362
+ );
1363
+ if (!mounted) {
1364
+ return;
1365
+ }
1366
+ _llmImportController.clear();
1367
+ final warningText = result.warnings.isEmpty
1368
+ ? ''
1369
+ : ' ${result.warnings.join(' ')}';
1370
+ ScaffoldMessenger.of(context).showSnackBar(
1371
+ SnackBar(
1372
+ content: Text(
1373
+ 'Imported ${result.importedCount} memories, '
1374
+ '${result.coreUpdatedCount} core entries.'
1375
+ '${result.behaviorNotesUpdated ? ' Behavior notes updated.' : ''}'
1376
+ '$warningText',
1377
+ ),
1378
+ ),
1379
+ );
1380
+ } catch (error) {
1381
+ if (!mounted) {
1382
+ return;
1383
+ }
1384
+ ScaffoldMessenger.of(context).showSnackBar(
1385
+ SnackBar(content: Text('Import failed: $error')),
1386
+ );
1387
+ } finally {
1388
+ if (mounted) {
1389
+ setState(() {
1390
+ _llmImporting = false;
1391
+ });
1392
+ }
1393
+ }
1394
+ }
1395
+
1260
1396
  List<MemoryItem> get _visibleMemories {
1261
1397
  final controller = widget.controller;
1262
1398
  return controller.memoryRecallResults.isNotEmpty
@@ -1473,6 +1609,118 @@ class _MemoryPanelState extends State<MemoryPanel> {
1473
1609
  ),
1474
1610
  ),
1475
1611
  const SizedBox(height: 16),
1612
+ Card(
1613
+ child: Theme(
1614
+ data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
1615
+ child: ExpansionTile(
1616
+ initiallyExpanded: false,
1617
+ tilePadding: const EdgeInsets.symmetric(
1618
+ horizontal: 18,
1619
+ vertical: 6,
1620
+ ),
1621
+ childrenPadding: const EdgeInsets.fromLTRB(18, 0, 18, 18),
1622
+ leading: Icon(Icons.swap_horiz_outlined, color: _textSecondary),
1623
+ title: const _SectionTitle('LLM Memory Transfer'),
1624
+ subtitle: Text(
1625
+ 'Export/import memories with another AI in one shot.',
1626
+ style: TextStyle(color: _textSecondary),
1627
+ ),
1628
+ children: <Widget>[
1629
+ Text(
1630
+ 'Generate a prompt to use in another AI, then paste the response here to import memories.',
1631
+ style: TextStyle(color: _textSecondary),
1632
+ ),
1633
+ const SizedBox(height: 12),
1634
+ Wrap(
1635
+ spacing: 10,
1636
+ runSpacing: 10,
1637
+ children: <Widget>[
1638
+ FilledButton.icon(
1639
+ onPressed: _llmPromptLoading
1640
+ ? null
1641
+ : () => _loadLlmPrompt(controller),
1642
+ icon: Icon(Icons.auto_awesome_outlined),
1643
+ label: Text(
1644
+ _llmPromptLoading ? 'Generating...' : 'Generate Prompt',
1645
+ ),
1646
+ ),
1647
+ OutlinedButton.icon(
1648
+ onPressed: _llmPromptController.text.trim().isEmpty
1649
+ ? null
1650
+ : _copyLlmPrompt,
1651
+ icon: Icon(Icons.copy_all_outlined),
1652
+ label: Text('Copy Prompt'),
1653
+ ),
1654
+ ],
1655
+ ),
1656
+ const SizedBox(height: 12),
1657
+ TextField(
1658
+ controller: _llmPromptController,
1659
+ minLines: 6,
1660
+ maxLines: 10,
1661
+ readOnly: true,
1662
+ decoration: const InputDecoration(
1663
+ labelText: 'Prompt to paste into another AI',
1664
+ ),
1665
+ ),
1666
+ const SizedBox(height: 12),
1667
+ SwitchListTile.adaptive(
1668
+ contentPadding: EdgeInsets.zero,
1669
+ value: _llmApplyBehaviorNotes,
1670
+ onChanged: _llmImporting
1671
+ ? null
1672
+ : (value) {
1673
+ setState(() {
1674
+ _llmApplyBehaviorNotes = value;
1675
+ });
1676
+ },
1677
+ title: Text('Apply behavior notes'),
1678
+ subtitle: Text(
1679
+ 'Overwrite assistant behavior notes from the import.',
1680
+ ),
1681
+ ),
1682
+ SwitchListTile.adaptive(
1683
+ contentPadding: EdgeInsets.zero,
1684
+ value: _llmApplyCoreMemory,
1685
+ onChanged: _llmImporting
1686
+ ? null
1687
+ : (value) {
1688
+ setState(() {
1689
+ _llmApplyCoreMemory = value;
1690
+ });
1691
+ },
1692
+ title: Text('Apply core memory'),
1693
+ subtitle: Text(
1694
+ 'Update core memory key/value entries from the import.',
1695
+ ),
1696
+ ),
1697
+ const SizedBox(height: 16),
1698
+ Text(
1699
+ 'Paste the response from the other AI below, then import.',
1700
+ style: TextStyle(color: _textSecondary),
1701
+ ),
1702
+ const SizedBox(height: 12),
1703
+ TextField(
1704
+ controller: _llmImportController,
1705
+ minLines: 6,
1706
+ maxLines: 12,
1707
+ decoration: const InputDecoration(
1708
+ labelText: 'LLM memory export response',
1709
+ ),
1710
+ ),
1711
+ const SizedBox(height: 12),
1712
+ FilledButton.icon(
1713
+ onPressed: _llmImporting
1714
+ ? null
1715
+ : () => _importLlmMemories(controller),
1716
+ icon: Icon(Icons.file_download_outlined),
1717
+ label: Text(_llmImporting ? 'Importing...' : 'Import'),
1718
+ ),
1719
+ ],
1720
+ ),
1721
+ ),
1722
+ ),
1723
+ const SizedBox(height: 16),
1476
1724
  Card(
1477
1725
  child: Padding(
1478
1726
  padding: const EdgeInsets.all(18),
@@ -14,7 +14,7 @@ class _NeoAgentAppState extends State<NeoAgentApp>
14
14
  late final NeoAgentController _controller;
15
15
  late final WebAppUpdateMonitor _webAppUpdateMonitor;
16
16
  final AppLaunchBridge _appLaunchBridge = AppLaunchBridge();
17
- StreamSubscription<String>? _appLaunchSubscription;
17
+ StreamSubscription<AppLaunchRequest>? _appLaunchSubscription;
18
18
  StreamSubscription<String>? _widgetOpenSubscription;
19
19
  GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
20
20
  String? _navigatorScopeSignature;
@@ -93,9 +93,18 @@ class _NeoAgentAppState extends State<NeoAgentApp>
93
93
  unawaited(_syncDesktopShell());
94
94
  }
95
95
 
96
- void _handleAppLaunchRequest(String action) {
96
+ void _handleAppLaunchRequest(AppLaunchRequest request) {
97
+ final action = request.action;
97
98
  if (action == AppLaunchBridge.voiceAssistantAction) {
98
99
  _controller.openVoiceAssistantSurface();
100
+ return;
101
+ }
102
+ if (action == AppLaunchBridge.shareToChatAction) {
103
+ _controller.queueSharedChatPayload(
104
+ text: request.text,
105
+ subject: request.subject,
106
+ files: request.files,
107
+ );
99
108
  }
100
109
  }
101
110