neoagent 2.4.4-beta.7 → 2.4.4-beta.8

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.
@@ -1513,42 +1513,37 @@ class _SettingsPanelState extends State<SettingsPanel> {
1513
1513
 
1514
1514
  Widget _buildSecuritySection(BuildContext context, NeoAgentController controller) {
1515
1515
  return Card(
1516
- elevation: 0,
1517
- shape: RoundedRectangleBorder(
1518
- borderRadius: BorderRadius.circular(12),
1519
- side: BorderSide(color: Theme.of(context).colorScheme.outlineVariant),
1520
- ),
1521
- child: Column(
1522
- crossAxisAlignment: CrossAxisAlignment.start,
1523
- children: <Widget>[
1524
- ListTile(
1525
- leading: const Icon(Icons.shield_outlined),
1526
- title: const Text('Security', style: TextStyle(fontWeight: FontWeight.bold)),
1527
- subtitle: const Text('Tool allowlists, approval gates, and process isolation.'),
1528
- trailing: const SizedBox.shrink(),
1529
- ),
1530
- const Divider(height: 1),
1531
- ListTile(
1532
- leading: const Icon(Icons.checklist_outlined),
1533
- title: const Text('Tool Permissions'),
1534
- subtitle: const Text('Set block / ask / allow per tool category, or pick a global mode.'),
1535
- trailing: Row(
1536
- mainAxisSize: MainAxisSize.min,
1537
- children: const <Widget>[
1538
- Icon(Icons.shield_rounded, size: 16, color: Colors.green),
1539
- SizedBox(width: 4),
1540
- Icon(Icons.chevron_right),
1541
- ],
1516
+ child: Padding(
1517
+ padding: const EdgeInsets.all(20),
1518
+ child: Column(
1519
+ crossAxisAlignment: CrossAxisAlignment.start,
1520
+ children: <Widget>[
1521
+ const _SectionTitle('Security'),
1522
+ const SizedBox(height: 10),
1523
+ Text(
1524
+ 'Per-tool permission policies, approval gates, and process isolation for shell execution.',
1525
+ style: TextStyle(color: _textSecondary, height: 1.45),
1542
1526
  ),
1543
- onTap: () {
1544
- Navigator.of(context).push(
1545
- MaterialPageRoute<void>(
1546
- builder: (_) => MainSecurity(controller: controller),
1547
- ),
1548
- );
1549
- },
1550
- ),
1551
- ],
1527
+ const SizedBox(height: 8),
1528
+ ListTile(
1529
+ contentPadding: EdgeInsets.zero,
1530
+ leading: Icon(Icons.checklist_outlined, color: _accentAlt),
1531
+ title: const Text('Tool Permissions'),
1532
+ subtitle: Text(
1533
+ 'Set block / ask / allow per tool category, or pick a global mode.',
1534
+ style: TextStyle(color: _textSecondary),
1535
+ ),
1536
+ trailing: const Icon(Icons.chevron_right),
1537
+ onTap: () {
1538
+ Navigator.of(context).push(
1539
+ MaterialPageRoute<void>(
1540
+ builder: (_) => MainSecurity(controller: controller),
1541
+ ),
1542
+ );
1543
+ },
1544
+ ),
1545
+ ],
1546
+ ),
1552
1547
  ),
1553
1548
  );
1554
1549
  }
@@ -196,7 +196,7 @@ function migrateToolPermissions(db) {
196
196
  CREATE TABLE IF NOT EXISTS tool_policies (
197
197
  user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
198
198
  category TEXT NOT NULL,
199
- policy TEXT NOT NULL CHECK(policy IN ('allow','deny','require_approval')),
199
+ policy TEXT NOT NULL CHECK(policy IN ('allow','deny','require_approval','allow_always')),
200
200
  updated_at TEXT DEFAULT (datetime('now')),
201
201
  PRIMARY KEY (user_id, category)
202
202
  );
@@ -208,7 +208,7 @@ function migrateToolPermissions(db) {
208
208
  tool_name TEXT NOT NULL,
209
209
  tool_args_json TEXT,
210
210
  decision TEXT NOT NULL CHECK(decision IN ('approved','denied','timeout')),
211
- scope TEXT NOT NULL CHECK(scope IN ('once','session')),
211
+ scope TEXT NOT NULL CHECK(scope IN ('once','session','always')),
212
212
  decided_at TEXT DEFAULT (datetime('now'))
213
213
  );
214
214
 
@@ -217,6 +217,29 @@ function migrateToolPermissions(db) {
217
217
  `);
218
218
  }
219
219
 
220
+ function migrateToolPoliciesAllowAlways(db) {
221
+ // SQLite doesn't support ALTER COLUMN — recreate the table to add 'allow_always'
222
+ // to the CHECK constraint on existing installations.
223
+ const tableInfo = db.prepare("PRAGMA table_info(tool_policies)").all();
224
+ if (!tableInfo.length) return; // table doesn't exist yet; migrateToolPermissions will create it correctly
225
+ const checkRow = db.prepare(
226
+ "SELECT sql FROM sqlite_master WHERE type='table' AND name='tool_policies'",
227
+ ).get();
228
+ if (checkRow && checkRow.sql.includes("'allow_always'")) return; // already migrated
229
+ db.exec(`
230
+ CREATE TABLE IF NOT EXISTS tool_policies_v2 (
231
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
232
+ category TEXT NOT NULL,
233
+ policy TEXT NOT NULL CHECK(policy IN ('allow','deny','require_approval','allow_always')),
234
+ updated_at TEXT DEFAULT (datetime('now')),
235
+ PRIMARY KEY (user_id, category)
236
+ );
237
+ INSERT OR IGNORE INTO tool_policies_v2 SELECT * FROM tool_policies;
238
+ DROP TABLE tool_policies;
239
+ ALTER TABLE tool_policies_v2 RENAME TO tool_policies;
240
+ `);
241
+ }
242
+
220
243
  function runSchemaMigrations(db) {
221
244
  migrateMemoryEmbeddingIndex(db);
222
245
  migrateMemoryProvenance(db);
@@ -224,6 +247,7 @@ function runSchemaMigrations(db) {
224
247
  migrateMemoryRetrievalEvents(db);
225
248
  migrateMemoryEmbeddingMetadata(db);
226
249
  migrateToolPermissions(db);
250
+ migrateToolPoliciesAllowAlways(db);
227
251
  }
228
252
 
229
253
  module.exports = {
@@ -233,5 +257,6 @@ module.exports = {
233
257
  migrateMemoryRetrievalEvents,
234
258
  migrateMemoryEmbeddingMetadata,
235
259
  migrateToolPermissions,
260
+ migrateToolPoliciesAllowAlways,
236
261
  runSchemaMigrations,
237
262
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.4.4-beta.7",
3
+ "version": "2.4.4-beta.8",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "AGPL-3.0-only",
6
6
  "main": "server/index.js",
@@ -1 +1 @@
1
- 29d7d0faaf7d97f5cfec115cfea8fcbc
1
+ 7e73207d8404cf818eebed5972cebc61
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"77e2e94772b6eb43759e34ed1ad7da4674e19c
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "149219383" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "2478318604" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });