neoagent 2.4.1 → 2.4.2-beta.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.
- package/flutter_app/lib/main_operations.dart +87 -10
- package/landing/assets/logo.svg +43 -0
- package/landing/images/dashboard-dark.png +0 -0
- package/landing/images/dashboard-light.png +0 -0
- package/landing/images/favicon.png +0 -0
- package/landing/images/memory-dark.png +0 -0
- package/landing/images/memory-light.png +0 -0
- package/landing/images/remote-devices-dark.png +0 -0
- package/landing/images/remote-devices-light.png +0 -0
- package/landing/index.html +1293 -0
- package/landing/js/main.js +77 -0
- package/package.json +2 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +21464 -21409
- package/server/routes/admin.js +1 -4
- package/server/routes/android.js +15 -2
- package/server/routes/browser.js +6 -0
- package/server/services/ai/systemPrompt.js +4 -4
- package/server/services/browser/controller.js +66 -0
- package/server/services/browser/extension/provider.js +1 -0
- package/server/utils/cloud-security.js +80 -0
|
@@ -4841,6 +4841,7 @@ class _TaskTriggerOption {
|
|
|
4841
4841
|
required this.label,
|
|
4842
4842
|
required this.description,
|
|
4843
4843
|
required this.icon,
|
|
4844
|
+
this.providerKey,
|
|
4844
4845
|
});
|
|
4845
4846
|
|
|
4846
4847
|
final String type;
|
|
@@ -4848,6 +4849,11 @@ class _TaskTriggerOption {
|
|
|
4848
4849
|
final String label;
|
|
4849
4850
|
final String description;
|
|
4850
4851
|
final IconData icon;
|
|
4852
|
+
|
|
4853
|
+
/// The official integration provider key this trigger binds to, if any.
|
|
4854
|
+
/// When set, the task editor shows a connected-account dropdown instead of
|
|
4855
|
+
/// a raw connection ID text field.
|
|
4856
|
+
final String? providerKey;
|
|
4851
4857
|
}
|
|
4852
4858
|
|
|
4853
4859
|
const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
@@ -4871,6 +4877,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4871
4877
|
label: 'Gmail Message Received',
|
|
4872
4878
|
description: 'Run when a matching Gmail message arrives.',
|
|
4873
4879
|
icon: Icons.mail_rounded,
|
|
4880
|
+
providerKey: 'google_workspace',
|
|
4874
4881
|
),
|
|
4875
4882
|
_TaskTriggerOption(
|
|
4876
4883
|
type: 'outlook_email_received',
|
|
@@ -4878,6 +4885,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4878
4885
|
label: 'Outlook Email Received',
|
|
4879
4886
|
description: 'Run when a matching Outlook email arrives.',
|
|
4880
4887
|
icon: Icons.markunread_rounded,
|
|
4888
|
+
providerKey: 'microsoft_365',
|
|
4881
4889
|
),
|
|
4882
4890
|
_TaskTriggerOption(
|
|
4883
4891
|
type: 'slack_message_received',
|
|
@@ -4885,6 +4893,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4885
4893
|
label: 'Slack Message Received',
|
|
4886
4894
|
description: 'Run when a Slack message matches the selected scope.',
|
|
4887
4895
|
icon: Icons.forum_rounded,
|
|
4896
|
+
providerKey: 'slack',
|
|
4888
4897
|
),
|
|
4889
4898
|
_TaskTriggerOption(
|
|
4890
4899
|
type: 'teams_message_received',
|
|
@@ -4892,6 +4901,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4892
4901
|
label: 'Teams Message Received',
|
|
4893
4902
|
description: 'Run when a Teams chat message matches the selected scope.',
|
|
4894
4903
|
icon: Icons.groups_rounded,
|
|
4904
|
+
providerKey: 'microsoft_365',
|
|
4895
4905
|
),
|
|
4896
4906
|
_TaskTriggerOption(
|
|
4897
4907
|
type: 'weather_event',
|
|
@@ -4900,6 +4910,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4900
4910
|
description:
|
|
4901
4911
|
'Run when configured weather events are forecast for a location.',
|
|
4902
4912
|
icon: Icons.cloudy_snowing,
|
|
4913
|
+
providerKey: 'weather',
|
|
4903
4914
|
),
|
|
4904
4915
|
_TaskTriggerOption(
|
|
4905
4916
|
type: 'whatsapp_personal_message_received',
|
|
@@ -4907,6 +4918,7 @@ const List<_TaskTriggerOption> _taskTriggerOptions = <_TaskTriggerOption>[
|
|
|
4907
4918
|
label: 'WhatsApp Personal Message Received',
|
|
4908
4919
|
description: 'Run on inbound personal WhatsApp messages.',
|
|
4909
4920
|
icon: Icons.chat_bubble_rounded,
|
|
4921
|
+
providerKey: 'whatsapp_personal',
|
|
4910
4922
|
),
|
|
4911
4923
|
];
|
|
4912
4924
|
|
|
@@ -4917,6 +4929,7 @@ _TaskTriggerOption _taskTriggerOptionForType(String type) {
|
|
|
4917
4929
|
);
|
|
4918
4930
|
}
|
|
4919
4931
|
|
|
4932
|
+
|
|
4920
4933
|
Future<String?> _pickTaskTriggerType(
|
|
4921
4934
|
BuildContext context,
|
|
4922
4935
|
String selectedType,
|
|
@@ -5562,6 +5575,62 @@ class _TasksPanelState extends State<TasksPanel> {
|
|
|
5562
5575
|
);
|
|
5563
5576
|
}
|
|
5564
5577
|
|
|
5578
|
+
List<OfficialIntegrationAccountItem> _connectedAccountsForTrigger(
|
|
5579
|
+
String triggerType,
|
|
5580
|
+
) {
|
|
5581
|
+
final providerKey = _taskTriggerOptionForType(triggerType).providerKey;
|
|
5582
|
+
if (providerKey == null) return const <OfficialIntegrationAccountItem>[];
|
|
5583
|
+
final seen = <int>{};
|
|
5584
|
+
final result = <OfficialIntegrationAccountItem>[];
|
|
5585
|
+
for (final integration in controller.officialIntegrations) {
|
|
5586
|
+
if (integration.id != providerKey) continue;
|
|
5587
|
+
for (final app in integration.apps) {
|
|
5588
|
+
for (final account in app.accounts) {
|
|
5589
|
+
if (account.connected && seen.add(account.id)) {
|
|
5590
|
+
result.add(account);
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5595
|
+
return result;
|
|
5596
|
+
}
|
|
5597
|
+
|
|
5598
|
+
Widget _buildConnectionIdSelector({
|
|
5599
|
+
required String triggerType,
|
|
5600
|
+
required ValueNotifier<int?> selectedConnectionId,
|
|
5601
|
+
required TextEditingController fallbackController,
|
|
5602
|
+
required StateSetter setLocalState,
|
|
5603
|
+
}) {
|
|
5604
|
+
final accounts = _connectedAccountsForTrigger(triggerType);
|
|
5605
|
+
if (accounts.isEmpty) {
|
|
5606
|
+
return TextField(
|
|
5607
|
+
controller: fallbackController,
|
|
5608
|
+
keyboardType: TextInputType.number,
|
|
5609
|
+
decoration: const InputDecoration(
|
|
5610
|
+
labelText: 'Connection ID',
|
|
5611
|
+
helperText: 'Connect this integration first to pick an account.',
|
|
5612
|
+
),
|
|
5613
|
+
);
|
|
5614
|
+
}
|
|
5615
|
+
return DropdownButtonFormField<int>(
|
|
5616
|
+
value: accounts.any((a) => a.id == selectedConnectionId.value)
|
|
5617
|
+
? selectedConnectionId.value
|
|
5618
|
+
: null,
|
|
5619
|
+
isExpanded: true,
|
|
5620
|
+
decoration: const InputDecoration(labelText: 'Account'),
|
|
5621
|
+
items: accounts
|
|
5622
|
+
.map(
|
|
5623
|
+
(account) => DropdownMenuItem<int>(
|
|
5624
|
+
value: account.id,
|
|
5625
|
+
child: Text(account.accountEmail ?? 'Account #${account.id}'),
|
|
5626
|
+
),
|
|
5627
|
+
)
|
|
5628
|
+
.toList(),
|
|
5629
|
+
onChanged: (value) =>
|
|
5630
|
+
setLocalState(() => selectedConnectionId.value = value),
|
|
5631
|
+
);
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5565
5634
|
Future<void> _openTaskEditor(
|
|
5566
5635
|
BuildContext context, {
|
|
5567
5636
|
TaskItem? task,
|
|
@@ -5578,6 +5647,13 @@ class _TasksPanelState extends State<TasksPanel> {
|
|
|
5578
5647
|
final connectionIdController = TextEditingController(
|
|
5579
5648
|
text: task?.triggerConfig['connectionId']?.toString() ?? '',
|
|
5580
5649
|
);
|
|
5650
|
+
final selectedConnectionId = ValueNotifier<int?>(
|
|
5651
|
+
task?.triggerConfig['connectionId'] is int
|
|
5652
|
+
? task!.triggerConfig['connectionId'] as int
|
|
5653
|
+
: int.tryParse(
|
|
5654
|
+
task?.triggerConfig['connectionId']?.toString() ?? '',
|
|
5655
|
+
),
|
|
5656
|
+
);
|
|
5581
5657
|
final queryController = TextEditingController(
|
|
5582
5658
|
text:
|
|
5583
5659
|
task?.triggerConfig['query']?.toString() ??
|
|
@@ -5659,6 +5735,8 @@ class _TasksPanelState extends State<TasksPanel> {
|
|
|
5659
5735
|
);
|
|
5660
5736
|
if (nextType != null) {
|
|
5661
5737
|
triggerType.value = nextType;
|
|
5738
|
+
selectedConnectionId.value = null;
|
|
5739
|
+
connectionIdController.clear();
|
|
5662
5740
|
}
|
|
5663
5741
|
},
|
|
5664
5742
|
child: InputDecorator(
|
|
@@ -5778,12 +5856,11 @@ class _TasksPanelState extends State<TasksPanel> {
|
|
|
5778
5856
|
|
|
5779
5857
|
return Column(
|
|
5780
5858
|
children: <Widget>[
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
),
|
|
5859
|
+
_buildConnectionIdSelector(
|
|
5860
|
+
triggerType: selectedTriggerType,
|
|
5861
|
+
selectedConnectionId: selectedConnectionId,
|
|
5862
|
+
fallbackController: connectionIdController,
|
|
5863
|
+
setLocalState: setLocalState,
|
|
5787
5864
|
),
|
|
5788
5865
|
const SizedBox(height: 12),
|
|
5789
5866
|
if (selectedTriggerType ==
|
|
@@ -5961,15 +6038,15 @@ class _TasksPanelState extends State<TasksPanel> {
|
|
|
5961
6038
|
triggerConfig['runAt'] = runAt;
|
|
5962
6039
|
}
|
|
5963
6040
|
} else {
|
|
5964
|
-
final parsedConnectionId =
|
|
5965
|
-
|
|
5966
|
-
|
|
6041
|
+
final parsedConnectionId =
|
|
6042
|
+
selectedConnectionId.value ??
|
|
6043
|
+
int.tryParse(connectionIdController.text.trim());
|
|
5967
6044
|
if (parsedConnectionId == null ||
|
|
5968
6045
|
parsedConnectionId <= 0) {
|
|
5969
6046
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
5970
6047
|
const SnackBar(
|
|
5971
6048
|
content: Text(
|
|
5972
|
-
'
|
|
6049
|
+
'Please select an account or enter a valid connection ID.',
|
|
5973
6050
|
),
|
|
5974
6051
|
backgroundColor: Colors.red,
|
|
5975
6052
|
),
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 100 100">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="tile" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#705331"></stop>
|
|
5
|
+
<stop offset="100%" stop-color="#22564c"></stop>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<radialGradient id="shine" cx="26%" cy="14%" r="72%">
|
|
8
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.22"></stop>
|
|
9
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"></stop>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<radialGradient id="core" cx="38%" cy="32%" r="75%">
|
|
12
|
+
<stop offset="0%" stop-color="#fffdf6"></stop>
|
|
13
|
+
<stop offset="48%" stop-color="#eee3cc"></stop>
|
|
14
|
+
<stop offset="100%" stop-color="#b5a888"></stop>
|
|
15
|
+
</radialGradient>
|
|
16
|
+
<radialGradient id="node" cx="36%" cy="30%" r="80%">
|
|
17
|
+
<stop offset="0%" stop-color="#f8dca8"></stop>
|
|
18
|
+
<stop offset="52%" stop-color="#d3a85f"></stop>
|
|
19
|
+
<stop offset="100%" stop-color="#9b6f2f"></stop>
|
|
20
|
+
</radialGradient>
|
|
21
|
+
<linearGradient id="tube" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
22
|
+
<stop offset="0%" stop-color="#fffaf0"></stop>
|
|
23
|
+
<stop offset="52%" stop-color="#efe7d6"></stop>
|
|
24
|
+
<stop offset="100%" stop-color="#cabf9f"></stop>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%">
|
|
27
|
+
<feDropShadow dx="0" dy="1.1" stdDeviation="1.1" flood-color="#000000" flood-opacity="0.45"></feDropShadow>
|
|
28
|
+
</filter>
|
|
29
|
+
<clipPath id="tc"><rect x="0" y="0" width="100" height="100" rx="22.5"></rect></clipPath>
|
|
30
|
+
</defs>
|
|
31
|
+
<g clip-path="url(#tc)">
|
|
32
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#tile)"></rect>
|
|
33
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#shine)"></rect>
|
|
34
|
+
<g fill="none" stroke="url(#tube)" stroke-linecap="round" filter="url(#sh)">
|
|
35
|
+
<circle cx="50" cy="50" r="17" stroke-width="5" stroke-dasharray="78 29" transform="rotate(-35 50 50)" stroke-opacity="0.92"></circle>
|
|
36
|
+
<circle cx="50" cy="50" r="30" stroke-width="5" stroke-dasharray="150 39" transform="rotate(70 50 50)" stroke-opacity="0.8"></circle>
|
|
37
|
+
</g>
|
|
38
|
+
<circle cx="50" cy="50" r="7" fill="url(#core)"></circle>
|
|
39
|
+
<circle cx="50" cy="20" r="5.6" fill="url(#node)"></circle>
|
|
40
|
+
<circle cx="48" cy="18.4" r="1.7" fill="#fff7e6" fill-opacity="0.8"></circle>
|
|
41
|
+
</g>
|
|
42
|
+
<rect x="0.6" y="0.6" width="98.8" height="98.8" rx="22" fill="none" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1.2"></rect>
|
|
43
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|