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.
- package/docs/capabilities.md +2 -0
- package/flutter_app/android/app/src/main/AndroidManifest.xml +14 -0
- package/flutter_app/android/app/src/main/kotlin/com/neoagent/flutter_app/MainActivity.kt +84 -0
- package/flutter_app/lib/main_chat.dart +156 -2
- package/flutter_app/lib/main_controller.dart +137 -10
- package/flutter_app/lib/main_models.dart +69 -0
- package/flutter_app/lib/main_operations.dart +248 -0
- package/flutter_app/lib/main_runtime.dart +11 -2
- package/flutter_app/lib/main_settings.dart +173 -176
- package/flutter_app/lib/main_shared.dart +78 -0
- package/flutter_app/lib/src/app_launch_bridge.dart +39 -10
- package/flutter_app/lib/src/backend_client.dart +28 -0
- package/package.json +1 -1
- package/server/guest-agent.android.package.json +13 -0
- package/server/guest-agent.browser.package.json +14 -0
- package/server/guest_agent.js +61 -44
- package/server/http/routes.js +1 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +69936 -69277
- package/server/routes/android.js +2 -11
- package/server/routes/browser.js +2 -2
- package/server/routes/memory.js +90 -0
- package/server/routes/social_video.js +62 -0
- package/server/services/ai/capabilityHealth.js +6 -14
- package/server/services/ai/systemPrompt.js +1 -0
- package/server/services/ai/toolResult.js +20 -0
- package/server/services/ai/tools.js +29 -0
- package/server/services/android/android_bootstrap_worker.js +2 -2
- package/server/services/android/controller.js +528 -132
- package/server/services/browser/controller.js +51 -68
- package/server/services/manager.js +15 -0
- package/server/services/memory/llm_transfer.js +217 -0
- package/server/services/runtime/backends/local-vm.js +16 -3
- package/server/services/runtime/guest_bootstrap.js +224 -56
- package/server/services/runtime/manager.js +53 -15
- package/server/services/runtime/qemu.js +149 -24
- package/server/services/runtime/settings.js +9 -14
- package/server/services/runtime/validation.js +10 -11
- package/server/services/social_video/adapters/base.js +26 -0
- package/server/services/social_video/adapters/index.js +27 -0
- package/server/services/social_video/adapters/instagram.js +17 -0
- package/server/services/social_video/adapters/tiktok.js +17 -0
- package/server/services/social_video/adapters/x.js +17 -0
- package/server/services/social_video/adapters/youtube.js +17 -0
- package/server/services/social_video/captions.js +187 -0
- package/server/services/social_video/frame.js +42 -0
- package/server/services/social_video/index.js +7 -0
- package/server/services/social_video/metadata.js +63 -0
- package/server/services/social_video/result.js +63 -0
- package/server/services/social_video/service.js +576 -0
- package/server/services/social_video/url.js +83 -0
- package/server/utils/deployment.js +4 -4
- 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<
|
|
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(
|
|
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
|
|