neoagent 2.3.1-beta.41 → 2.3.1-beta.43
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/configuration.md +0 -6
- package/flutter_app/lib/main_integrations.dart +0 -220
- package/lib/manager.js +0 -26
- package/package.json +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +29442 -29682
- package/server/services/integrations/registry.js +0 -2
- package/server/services/voice/providers.js +94 -5
- package/server/services/voice/runtimeManager.js +4 -0
- package/server/services/wearable/firmware_manifest.js +3 -24
- package/server/services/wearable/service.js +1 -5
- package/server/services/integrations/home_assistant/provider.js +0 -649
package/docs/configuration.md
CHANGED
|
@@ -90,18 +90,12 @@ All OAuth callbacks default to `PUBLIC_URL + /api/integrations/oauth/callback` u
|
|
|
90
90
|
| `FIGMA_OAUTH_CLIENT_ID` | Figma OAuth client ID |
|
|
91
91
|
| `FIGMA_OAUTH_CLIENT_SECRET` | Figma OAuth client secret |
|
|
92
92
|
| `FIGMA_OAUTH_REDIRECT_URI` | Optional Figma OAuth callback URL |
|
|
93
|
-
| `HOME_ASSISTANT_BASE_URL` | Optional fallback Home Assistant base URL. Users can configure this per account in Official Integrations. |
|
|
94
|
-
| `HOME_ASSISTANT_OAUTH_CLIENT_ID` | Optional fallback Home Assistant OAuth client ID. |
|
|
95
|
-
| `HOME_ASSISTANT_OAUTH_CLIENT_SECRET` | Optional fallback Home Assistant OAuth client secret. |
|
|
96
|
-
| `HOME_ASSISTANT_OAUTH_REDIRECT_URI` | Optional fallback Home Assistant OAuth callback URL. |
|
|
97
|
-
| `HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL` | Optional safety override. Set to `1` only if you intentionally allow Home Assistant base URLs on localhost/private networks. |
|
|
98
93
|
| `TRELLO_API_KEY` | Optional Trello Power-Up API key. If set, users only need to provide their personal token in Official Integrations. |
|
|
99
94
|
| `SPOTIFY_OAUTH_CLIENT_ID` | Spotify OAuth client ID |
|
|
100
95
|
| `SPOTIFY_OAUTH_CLIENT_SECRET` | Spotify OAuth client secret |
|
|
101
96
|
| `SPOTIFY_OAUTH_REDIRECT_URI` | Optional Spotify OAuth callback URL |
|
|
102
97
|
|
|
103
98
|
Home Assistant and Trello no longer require server-side setup. Each user can open Official Integrations and enter their own provider-specific credentials in the Flutter UI.
|
|
104
|
-
For safety, local/private Home Assistant targets are blocked by default unless `HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL=1` is set on the server.
|
|
105
99
|
|
|
106
100
|
Trello integration is flexible: users can provide both API key and token in the UI, or if `TRELLO_API_KEY` is set as a server environment variable, users only need to authenticate with their personal token. Tokens are stored securely per user and are never added to server environment variables.
|
|
107
101
|
|
|
@@ -212,232 +212,12 @@ void _openOfficialIntegrationSetupDialog(
|
|
|
212
212
|
String providerId,
|
|
213
213
|
) {
|
|
214
214
|
switch (providerId) {
|
|
215
|
-
case 'home_assistant':
|
|
216
|
-
_showHomeAssistantSetupDialog(context, controller);
|
|
217
|
-
return;
|
|
218
215
|
case 'trello':
|
|
219
216
|
_showTrelloSetupDialog(context, controller);
|
|
220
217
|
return;
|
|
221
218
|
}
|
|
222
219
|
}
|
|
223
220
|
|
|
224
|
-
Future<void> _showHomeAssistantSetupDialog(
|
|
225
|
-
BuildContext context,
|
|
226
|
-
NeoAgentController controller,
|
|
227
|
-
) async {
|
|
228
|
-
Map<String, dynamic> existing;
|
|
229
|
-
try {
|
|
230
|
-
existing = await controller.getOfficialIntegrationConfig('home_assistant');
|
|
231
|
-
} catch (error) {
|
|
232
|
-
if (context.mounted) {
|
|
233
|
-
ScaffoldMessenger.of(context).showSnackBar(
|
|
234
|
-
SnackBar(content: Text(controller.errorMessage ?? error.toString())),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
final baseUrlController = TextEditingController(
|
|
241
|
-
text: existing['baseUrl']?.toString() ?? '',
|
|
242
|
-
);
|
|
243
|
-
final clientIdController = TextEditingController(
|
|
244
|
-
text: existing['clientId']?.toString() ?? '',
|
|
245
|
-
);
|
|
246
|
-
final clientSecretController = TextEditingController();
|
|
247
|
-
final redirectUriController = TextEditingController(
|
|
248
|
-
text: existing['redirectUri']?.toString() ?? '',
|
|
249
|
-
);
|
|
250
|
-
final hasSavedSetup =
|
|
251
|
-
(existing['baseUrl']?.toString().trim().isNotEmpty ?? false) ||
|
|
252
|
-
(existing['clientId']?.toString().trim().isNotEmpty ?? false) ||
|
|
253
|
-
existing['hasClientSecret'] == true;
|
|
254
|
-
var formError = '';
|
|
255
|
-
var saving = false;
|
|
256
|
-
|
|
257
|
-
await showDialog<void>(
|
|
258
|
-
context: context,
|
|
259
|
-
builder: (dialogContext) {
|
|
260
|
-
return StatefulBuilder(
|
|
261
|
-
builder: (dialogContext, setState) {
|
|
262
|
-
return AlertDialog(
|
|
263
|
-
title: const Text('Home Assistant Setup'),
|
|
264
|
-
content: SizedBox(
|
|
265
|
-
width: 520,
|
|
266
|
-
child: Column(
|
|
267
|
-
mainAxisSize: MainAxisSize.min,
|
|
268
|
-
children: <Widget>[
|
|
269
|
-
TextField(
|
|
270
|
-
controller: baseUrlController,
|
|
271
|
-
decoration: const InputDecoration(
|
|
272
|
-
labelText: 'Base URL',
|
|
273
|
-
hintText: 'https://ha.example.com',
|
|
274
|
-
),
|
|
275
|
-
),
|
|
276
|
-
const SizedBox(height: 10),
|
|
277
|
-
TextField(
|
|
278
|
-
controller: clientIdController,
|
|
279
|
-
decoration: const InputDecoration(
|
|
280
|
-
labelText: 'OAuth Client ID',
|
|
281
|
-
),
|
|
282
|
-
),
|
|
283
|
-
const SizedBox(height: 10),
|
|
284
|
-
TextField(
|
|
285
|
-
controller: clientSecretController,
|
|
286
|
-
obscureText: true,
|
|
287
|
-
decoration: InputDecoration(
|
|
288
|
-
labelText: 'OAuth Client Secret',
|
|
289
|
-
hintText: existing['hasClientSecret'] == true
|
|
290
|
-
? 'Saved secret exists. Enter to replace it.'
|
|
291
|
-
: null,
|
|
292
|
-
),
|
|
293
|
-
),
|
|
294
|
-
const SizedBox(height: 10),
|
|
295
|
-
TextField(
|
|
296
|
-
controller: redirectUriController,
|
|
297
|
-
decoration: const InputDecoration(
|
|
298
|
-
labelText: 'Redirect URI (optional)',
|
|
299
|
-
hintText: 'Leave blank to use the default callback URL',
|
|
300
|
-
),
|
|
301
|
-
),
|
|
302
|
-
if (formError.isNotEmpty) ...<Widget>[
|
|
303
|
-
const SizedBox(height: 10),
|
|
304
|
-
Align(
|
|
305
|
-
alignment: Alignment.centerLeft,
|
|
306
|
-
child: Text(formError, style: TextStyle(color: _danger)),
|
|
307
|
-
),
|
|
308
|
-
],
|
|
309
|
-
],
|
|
310
|
-
),
|
|
311
|
-
),
|
|
312
|
-
actions: <Widget>[
|
|
313
|
-
if (hasSavedSetup)
|
|
314
|
-
TextButton(
|
|
315
|
-
onPressed: saving
|
|
316
|
-
? null
|
|
317
|
-
: () async {
|
|
318
|
-
final shouldClear =
|
|
319
|
-
await showDialog<bool>(
|
|
320
|
-
context: dialogContext,
|
|
321
|
-
builder: (context) {
|
|
322
|
-
return AlertDialog(
|
|
323
|
-
title: const Text('Clear Setup?'),
|
|
324
|
-
content: const Text(
|
|
325
|
-
'This removes your saved Home Assistant base URL and OAuth client credentials for this agent.',
|
|
326
|
-
),
|
|
327
|
-
actions: [
|
|
328
|
-
TextButton(
|
|
329
|
-
onPressed: () =>
|
|
330
|
-
Navigator.of(context).pop(false),
|
|
331
|
-
child: const Text('Cancel'),
|
|
332
|
-
),
|
|
333
|
-
FilledButton(
|
|
334
|
-
onPressed: () =>
|
|
335
|
-
Navigator.of(context).pop(true),
|
|
336
|
-
child: const Text('Clear Setup'),
|
|
337
|
-
),
|
|
338
|
-
],
|
|
339
|
-
);
|
|
340
|
-
},
|
|
341
|
-
) ??
|
|
342
|
-
false;
|
|
343
|
-
if (!shouldClear) {
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
setState(() {
|
|
347
|
-
formError = '';
|
|
348
|
-
saving = true;
|
|
349
|
-
});
|
|
350
|
-
try {
|
|
351
|
-
await controller.clearOfficialIntegrationConfig(
|
|
352
|
-
'home_assistant',
|
|
353
|
-
);
|
|
354
|
-
if (dialogContext.mounted) {
|
|
355
|
-
Navigator.of(dialogContext).pop();
|
|
356
|
-
}
|
|
357
|
-
} catch (_) {
|
|
358
|
-
setState(() {
|
|
359
|
-
formError =
|
|
360
|
-
controller.errorMessage ??
|
|
361
|
-
'Could not clear Home Assistant setup.';
|
|
362
|
-
saving = false;
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
child: const Text('Clear Setup'),
|
|
367
|
-
),
|
|
368
|
-
TextButton(
|
|
369
|
-
onPressed: saving
|
|
370
|
-
? null
|
|
371
|
-
: () => Navigator.of(dialogContext).pop(),
|
|
372
|
-
child: const Text('Cancel'),
|
|
373
|
-
),
|
|
374
|
-
FilledButton(
|
|
375
|
-
onPressed: saving
|
|
376
|
-
? null
|
|
377
|
-
: () async {
|
|
378
|
-
setState(() {
|
|
379
|
-
formError = '';
|
|
380
|
-
});
|
|
381
|
-
final baseUrl = baseUrlController.text.trim();
|
|
382
|
-
final clientId = clientIdController.text.trim();
|
|
383
|
-
final clientSecret = clientSecretController.text.trim();
|
|
384
|
-
final hasSavedSecret =
|
|
385
|
-
existing['hasClientSecret'] == true;
|
|
386
|
-
if (baseUrl.isEmpty || clientId.isEmpty) {
|
|
387
|
-
setState(() {
|
|
388
|
-
formError =
|
|
389
|
-
'Base URL and OAuth Client ID are required.';
|
|
390
|
-
});
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
if (clientSecret.isEmpty && !hasSavedSecret) {
|
|
394
|
-
setState(() {
|
|
395
|
-
formError = 'OAuth Client Secret is required.';
|
|
396
|
-
});
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
setState(() {
|
|
401
|
-
saving = true;
|
|
402
|
-
});
|
|
403
|
-
try {
|
|
404
|
-
await controller.saveOfficialIntegrationConfig(
|
|
405
|
-
'home_assistant',
|
|
406
|
-
config: <String, dynamic>{
|
|
407
|
-
'baseUrl': baseUrl,
|
|
408
|
-
'clientId': clientId,
|
|
409
|
-
if (clientSecret.isNotEmpty)
|
|
410
|
-
'clientSecret': clientSecret,
|
|
411
|
-
'redirectUri': redirectUriController.text.trim(),
|
|
412
|
-
},
|
|
413
|
-
);
|
|
414
|
-
if (dialogContext.mounted) {
|
|
415
|
-
Navigator.of(dialogContext).pop();
|
|
416
|
-
}
|
|
417
|
-
} catch (_) {
|
|
418
|
-
setState(() {
|
|
419
|
-
formError =
|
|
420
|
-
controller.errorMessage ??
|
|
421
|
-
'Could not save Home Assistant setup.';
|
|
422
|
-
saving = false;
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
},
|
|
426
|
-
child: Text(saving ? 'Saving...' : 'Save Setup'),
|
|
427
|
-
),
|
|
428
|
-
],
|
|
429
|
-
);
|
|
430
|
-
},
|
|
431
|
-
);
|
|
432
|
-
},
|
|
433
|
-
);
|
|
434
|
-
|
|
435
|
-
baseUrlController.dispose();
|
|
436
|
-
clientIdController.dispose();
|
|
437
|
-
clientSecretController.dispose();
|
|
438
|
-
redirectUriController.dispose();
|
|
439
|
-
}
|
|
440
|
-
|
|
441
221
|
Future<void> _showTrelloSetupDialog(
|
|
442
222
|
BuildContext context,
|
|
443
223
|
NeoAgentController controller,
|
package/lib/manager.js
CHANGED
|
@@ -555,27 +555,6 @@ async function cmdSetup() {
|
|
|
555
555
|
current.GITHUB_OAUTH_REDIRECT_URI || ''
|
|
556
556
|
);
|
|
557
557
|
|
|
558
|
-
const homeAssistantOauthClientId = await askSecret(
|
|
559
|
-
'Home Assistant OAuth client ID',
|
|
560
|
-
current.HOME_ASSISTANT_OAUTH_CLIENT_ID || ''
|
|
561
|
-
);
|
|
562
|
-
const homeAssistantOauthClientSecret = await askSecret(
|
|
563
|
-
'Home Assistant OAuth client secret',
|
|
564
|
-
current.HOME_ASSISTANT_OAUTH_CLIENT_SECRET || ''
|
|
565
|
-
);
|
|
566
|
-
const homeAssistantOauthRedirectUri = await ask(
|
|
567
|
-
'Home Assistant OAuth redirect URI',
|
|
568
|
-
current.HOME_ASSISTANT_OAUTH_REDIRECT_URI || ''
|
|
569
|
-
);
|
|
570
|
-
const homeAssistantBaseUrl = await ask(
|
|
571
|
-
'Home Assistant base URL (e.g., https://ha.example.com)',
|
|
572
|
-
current.HOME_ASSISTANT_BASE_URL || ''
|
|
573
|
-
);
|
|
574
|
-
const homeAssistantAllowPrivateUrl = current.HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL === '1' ? 'true' : await ask(
|
|
575
|
-
'Allow local/private Home Assistant base URLs? (true/false)',
|
|
576
|
-
'false'
|
|
577
|
-
);
|
|
578
|
-
|
|
579
558
|
const lines = [
|
|
580
559
|
`NODE_ENV=production`,
|
|
581
560
|
`PORT=${port}`,
|
|
@@ -613,11 +592,6 @@ async function cmdSetup() {
|
|
|
613
592
|
githubOauthClientId ? `GITHUB_OAUTH_CLIENT_ID=${githubOauthClientId}` : '',
|
|
614
593
|
githubOauthClientSecret ? `GITHUB_OAUTH_CLIENT_SECRET=${githubOauthClientSecret}` : '',
|
|
615
594
|
githubOauthRedirectUri ? `GITHUB_OAUTH_REDIRECT_URI=${githubOauthRedirectUri}` : '',
|
|
616
|
-
homeAssistantOauthClientId ? `HOME_ASSISTANT_OAUTH_CLIENT_ID=${homeAssistantOauthClientId}` : '',
|
|
617
|
-
homeAssistantOauthClientSecret ? `HOME_ASSISTANT_OAUTH_CLIENT_SECRET=${homeAssistantOauthClientSecret}` : '',
|
|
618
|
-
homeAssistantOauthRedirectUri ? `HOME_ASSISTANT_OAUTH_REDIRECT_URI=${homeAssistantOauthRedirectUri}` : '',
|
|
619
|
-
homeAssistantBaseUrl ? `HOME_ASSISTANT_BASE_URL=${homeAssistantBaseUrl}` : '',
|
|
620
|
-
String(homeAssistantAllowPrivateUrl || '').trim().toLowerCase() === 'true' ? `HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL=1` : '',
|
|
621
595
|
deepgramApiKey ? `DEEPGRAM_API_KEY=${deepgramApiKey}` : '',
|
|
622
596
|
deepgramBaseUrl ? `DEEPGRAM_BASE_URL=${deepgramBaseUrl}` : '',
|
|
623
597
|
deepgramModel ? `DEEPGRAM_MODEL=${deepgramModel}` : '',
|
package/package.json
CHANGED
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"42d3d75a56efe1a2e9902f52dc8006099c45d9
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "555509852" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|