@agenticmail/enterprise 0.5.276 → 0.5.277
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/dist/agent-heartbeat-TPP4LBIA.js +510 -0
- package/dist/chunk-LJHLPJ7C.js +3778 -0
- package/dist/chunk-MCAYYM7I.js +1224 -0
- package/dist/chunk-XEN7XQ7S.js +4732 -0
- package/dist/cli-agent-FAPARUB4.js +1768 -0
- package/dist/cli-serve-HO3KFM2X.js +114 -0
- package/dist/cli.js +3 -3
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/pages/database-access.js +49 -31
- package/dist/dashboard/vendor/react-dom.development.js +29924 -0
- package/dist/dashboard/vendor/react.development.js +3343 -0
- package/dist/index.js +3 -3
- package/dist/routes-5JAOG5NP.js +14678 -0
- package/dist/runtime-OUJIXSKS.js +45 -0
- package/dist/server-QW7UBHSV.js +15 -0
- package/dist/setup-R66K242G.js +20 -0
- package/package.json +1 -1
- package/src/dashboard/index.html +2 -2
- package/src/dashboard/pages/database-access.js +49 -31
- package/src/dashboard/vendor/react-dom.development.js +29924 -0
- package/src/dashboard/vendor/react.development.js +3343 -0
- package/src/engine/agent-routes.ts +1 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import "./chunk-KFQGP6VL.js";
|
|
2
|
+
|
|
3
|
+
// src/cli-serve.ts
|
|
4
|
+
import { existsSync, readFileSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
function loadEnvFile() {
|
|
8
|
+
const candidates = [
|
|
9
|
+
join(process.cwd(), ".env"),
|
|
10
|
+
join(homedir(), ".agenticmail", ".env")
|
|
11
|
+
];
|
|
12
|
+
for (const envPath of candidates) {
|
|
13
|
+
if (!existsSync(envPath)) continue;
|
|
14
|
+
try {
|
|
15
|
+
const content = readFileSync(envPath, "utf8");
|
|
16
|
+
for (const line of content.split("\n")) {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
19
|
+
const eq = trimmed.indexOf("=");
|
|
20
|
+
if (eq < 0) continue;
|
|
21
|
+
const key = trimmed.slice(0, eq).trim();
|
|
22
|
+
let val = trimmed.slice(eq + 1).trim();
|
|
23
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
24
|
+
val = val.slice(1, -1);
|
|
25
|
+
}
|
|
26
|
+
if (!process.env[key]) process.env[key] = val;
|
|
27
|
+
}
|
|
28
|
+
console.log(`Loaded config from ${envPath}`);
|
|
29
|
+
return;
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function ensureSecrets() {
|
|
35
|
+
const { randomUUID } = await import("crypto");
|
|
36
|
+
const envDir = join(homedir(), ".agenticmail");
|
|
37
|
+
const envPath = join(envDir, ".env");
|
|
38
|
+
let dirty = false;
|
|
39
|
+
if (!process.env.JWT_SECRET) {
|
|
40
|
+
process.env.JWT_SECRET = randomUUID() + randomUUID();
|
|
41
|
+
dirty = true;
|
|
42
|
+
console.log("[startup] Generated new JWT_SECRET (existing sessions will need to re-login)");
|
|
43
|
+
}
|
|
44
|
+
if (!process.env.AGENTICMAIL_VAULT_KEY) {
|
|
45
|
+
process.env.AGENTICMAIL_VAULT_KEY = randomUUID() + randomUUID();
|
|
46
|
+
dirty = true;
|
|
47
|
+
console.log("[startup] Generated new AGENTICMAIL_VAULT_KEY");
|
|
48
|
+
console.log("[startup] \u26A0\uFE0F Previously encrypted credentials will need to be re-entered in the dashboard");
|
|
49
|
+
}
|
|
50
|
+
if (dirty) {
|
|
51
|
+
try {
|
|
52
|
+
if (!existsSync(envDir)) {
|
|
53
|
+
const { mkdirSync } = await import("fs");
|
|
54
|
+
mkdirSync(envDir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
const { appendFileSync } = await import("fs");
|
|
57
|
+
const lines = [];
|
|
58
|
+
let existing = "";
|
|
59
|
+
if (existsSync(envPath)) {
|
|
60
|
+
existing = readFileSync(envPath, "utf8");
|
|
61
|
+
}
|
|
62
|
+
if (!existing.includes("JWT_SECRET=")) {
|
|
63
|
+
lines.push(`JWT_SECRET=${process.env.JWT_SECRET}`);
|
|
64
|
+
}
|
|
65
|
+
if (!existing.includes("AGENTICMAIL_VAULT_KEY=")) {
|
|
66
|
+
lines.push(`AGENTICMAIL_VAULT_KEY=${process.env.AGENTICMAIL_VAULT_KEY}`);
|
|
67
|
+
}
|
|
68
|
+
if (lines.length) {
|
|
69
|
+
appendFileSync(envPath, "\n" + lines.join("\n") + "\n", { mode: 384 });
|
|
70
|
+
console.log(`[startup] Saved secrets to ${envPath}`);
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.warn(`[startup] Could not save secrets to ${envPath}: ${e.message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function runServe(_args) {
|
|
78
|
+
loadEnvFile();
|
|
79
|
+
const DATABASE_URL = process.env.DATABASE_URL;
|
|
80
|
+
const PORT = parseInt(process.env.PORT || "8080", 10);
|
|
81
|
+
await ensureSecrets();
|
|
82
|
+
const JWT_SECRET = process.env.JWT_SECRET;
|
|
83
|
+
const VAULT_KEY = process.env.AGENTICMAIL_VAULT_KEY;
|
|
84
|
+
if (!DATABASE_URL) {
|
|
85
|
+
console.error("ERROR: DATABASE_URL is required.");
|
|
86
|
+
console.error("");
|
|
87
|
+
console.error("Set it via environment variable or .env file:");
|
|
88
|
+
console.error(" DATABASE_URL=postgresql://user:pass@host:5432/db npx @agenticmail/enterprise start");
|
|
89
|
+
console.error("");
|
|
90
|
+
console.error("Or create a .env file (in cwd or ~/.agenticmail/.env):");
|
|
91
|
+
console.error(" DATABASE_URL=postgresql://user:pass@host:5432/db");
|
|
92
|
+
console.error(" JWT_SECRET=your-secret-here");
|
|
93
|
+
console.error(" PORT=3200");
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const { createAdapter } = await import("./factory-672W7A5B.js");
|
|
97
|
+
const { createServer } = await import("./server-QW7UBHSV.js");
|
|
98
|
+
const db = await createAdapter({
|
|
99
|
+
type: DATABASE_URL.startsWith("postgres") ? "postgres" : "sqlite",
|
|
100
|
+
connectionString: DATABASE_URL
|
|
101
|
+
});
|
|
102
|
+
await db.migrate();
|
|
103
|
+
const server = createServer({
|
|
104
|
+
port: PORT,
|
|
105
|
+
db,
|
|
106
|
+
jwtSecret: JWT_SECRET,
|
|
107
|
+
corsOrigins: ["*"]
|
|
108
|
+
});
|
|
109
|
+
await server.start();
|
|
110
|
+
console.log(`AgenticMail Enterprise server running on :${PORT}`);
|
|
111
|
+
}
|
|
112
|
+
export {
|
|
113
|
+
runServe
|
|
114
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -53,14 +53,14 @@ Skill Development:
|
|
|
53
53
|
break;
|
|
54
54
|
case "serve":
|
|
55
55
|
case "start":
|
|
56
|
-
import("./cli-serve-
|
|
56
|
+
import("./cli-serve-HO3KFM2X.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
|
|
57
57
|
break;
|
|
58
58
|
case "agent":
|
|
59
|
-
import("./cli-agent-
|
|
59
|
+
import("./cli-agent-FAPARUB4.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
|
|
60
60
|
break;
|
|
61
61
|
case "setup":
|
|
62
62
|
default:
|
|
63
|
-
import("./setup-
|
|
63
|
+
import("./setup-R66K242G.js").then((m) => m.runSetupWizard()).catch(fatal);
|
|
64
64
|
break;
|
|
65
65
|
}
|
|
66
66
|
function fatal(err) {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
6
6
|
<title>AgenticMail Enterprise</title>
|
|
7
7
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><defs><linearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'><stop offset='0%25' stop-color='%23f43f5e'/><stop offset='100%25' stop-color='%23e11d48'/></linearGradient></defs><rect x='2' y='5' width='20' height='14' rx='2.5' fill='url(%23g)'/><polyline points='2 5 12 13 22 5' stroke='white' stroke-width='1.8' fill='none' stroke-linejoin='round' opacity='0.85'/></svg>"/>
|
|
8
|
-
<script src="/dashboard/vendor/react.
|
|
9
|
-
<script src="/dashboard/vendor/react-dom.
|
|
8
|
+
<script src="/dashboard/vendor/react.development.js"></script>
|
|
9
|
+
<script src="/dashboard/vendor/react-dom.development.js"></script>
|
|
10
10
|
<style>
|
|
11
11
|
/* ═══════════════════════════════════════════════════════════
|
|
12
12
|
THEME SYSTEM — CSS Custom Properties
|
|
@@ -38,7 +38,22 @@ var PERMISSIONS = [
|
|
|
38
38
|
|
|
39
39
|
// ─── Styles ──────────────────────────────────────────────────────────────────
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// Convert CSS string to React style object
|
|
42
|
+
function css(str) {
|
|
43
|
+
var obj = {};
|
|
44
|
+
str.split(';').forEach(function(pair) {
|
|
45
|
+
var p = pair.trim(); if (!p) return;
|
|
46
|
+
var i = p.indexOf(':'); if (i < 0) return;
|
|
47
|
+
var key = p.slice(0, i).trim();
|
|
48
|
+
var val = p.slice(i + 1).trim();
|
|
49
|
+
// camelCase the key
|
|
50
|
+
key = key.replace(/-([a-z])/g, function(_, c) { return c.toUpperCase(); });
|
|
51
|
+
obj[key] = val;
|
|
52
|
+
});
|
|
53
|
+
return obj;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var _s = {
|
|
42
57
|
page: 'padding: 24px; max-width: 1200px; margin: 0 auto;',
|
|
43
58
|
header: 'display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; flex-wrap: wrap; gap: 12px;',
|
|
44
59
|
title: 'font-size: 24px; font-weight: 700; display: flex; align-items: center; gap: 10px;',
|
|
@@ -84,6 +99,9 @@ var s = {
|
|
|
84
99
|
dbPickerItem: 'padding: 12px; border-radius: 8px; border: 1px solid var(--border); cursor: pointer; text-align: center; transition: all 0.15s; background: var(--bg-secondary);',
|
|
85
100
|
dbPickerItemActive: 'padding: 12px; border-radius: 8px; border: 2px solid var(--accent); cursor: pointer; text-align: center; background: var(--accent-soft);',
|
|
86
101
|
};
|
|
102
|
+
// Convert all string styles to React style objects
|
|
103
|
+
var s = {};
|
|
104
|
+
Object.keys(_s).forEach(function(k) { s[k] = css(_s[k]); });
|
|
87
105
|
|
|
88
106
|
// ─── Main Page ───────────────────────────────────────────────────────────────
|
|
89
107
|
|
|
@@ -174,7 +192,7 @@ function ConnectionsTab(props) {
|
|
|
174
192
|
if (connections.length === 0) {
|
|
175
193
|
return h('div', { style: s.emptyState },
|
|
176
194
|
h('div', { style: s.emptyIcon }, I.database()),
|
|
177
|
-
h('div', { style: 'font-size: 16px; font-weight: 600; margin-bottom: 8px;' }, 'No Database Connections'),
|
|
195
|
+
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Database Connections'),
|
|
178
196
|
h('div', null, 'Add a connection to let your agents query external databases.'),
|
|
179
197
|
);
|
|
180
198
|
}
|
|
@@ -192,11 +210,11 @@ function ConnectionsTab(props) {
|
|
|
192
210
|
h('div', { style: s.cardTitle }, conn.name),
|
|
193
211
|
h('div', { style: s.cardType }, dbType ? dbType.label : conn.type),
|
|
194
212
|
),
|
|
195
|
-
h('span', { style: s.badge
|
|
213
|
+
h('span', { style: Object.assign({}, s.badge, statusStyle) }, conn.status),
|
|
196
214
|
),
|
|
197
215
|
conn.host && h('div', { style: s.meta }, conn.host + (conn.port ? ':' + conn.port : '') + (conn.database ? ' / ' + conn.database : '')),
|
|
198
216
|
conn.description && h('div', { style: s.meta }, conn.description),
|
|
199
|
-
conn.lastError && h('div', { style: 'font-size: 11px; color: var(--danger); margin-top: 4px;' }, conn.lastError),
|
|
217
|
+
conn.lastError && h('div', { style: css('font-size: 11px; color: var(--danger); margin-top: 4px;') }, conn.lastError),
|
|
200
218
|
h('div', { style: s.actions },
|
|
201
219
|
h('button', { style: s.btn, onClick: function() { props.onTest(conn.id); } }, 'Test'),
|
|
202
220
|
h('button', { style: s.btnPrimary, onClick: function() { props.onGrant(conn.id); } }, 'Grant Access'),
|
|
@@ -229,14 +247,14 @@ function AgentAccessTab(props) {
|
|
|
229
247
|
load();
|
|
230
248
|
}, [props.agents]);
|
|
231
249
|
|
|
232
|
-
if (loading) return h('div', { style: 'padding: 40px; text-align: center; color: var(--text-muted);' }, 'Loading agent access...');
|
|
250
|
+
if (loading) return h('div', { style: css('padding: 40px; text-align: center; color: var(--text-muted);') }, 'Loading agent access...');
|
|
233
251
|
|
|
234
252
|
var agentsWithAccess = props.agents.filter(function(a) { return accessMap[a.id] && accessMap[a.id].length > 0; });
|
|
235
253
|
|
|
236
254
|
if (agentsWithAccess.length === 0) {
|
|
237
255
|
return h('div', { style: s.emptyState },
|
|
238
256
|
h('div', { style: s.emptyIcon }, '🔒'),
|
|
239
|
-
h('div', { style: 'font-size: 16px; font-weight: 600; margin-bottom: 8px;' }, 'No Agents Have Database Access'),
|
|
257
|
+
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Agents Have Database Access'),
|
|
240
258
|
h('div', null, 'Grant access from the Connections tab to allow agents to query databases.'),
|
|
241
259
|
);
|
|
242
260
|
}
|
|
@@ -244,9 +262,9 @@ function AgentAccessTab(props) {
|
|
|
244
262
|
return h('div', null,
|
|
245
263
|
agentsWithAccess.map(function(agent) {
|
|
246
264
|
var grants = accessMap[agent.id] || [];
|
|
247
|
-
return h('div', { key: agent.id, style: s.card
|
|
265
|
+
return h('div', { key: agent.id, style: Object.assign({}, s.card, { marginBottom: '16px' }) },
|
|
248
266
|
h('div', { style: s.cardHeader },
|
|
249
|
-
h('div', { style: 'width: 32px; height: 32px; border-radius: 50%; background: var(--accent-soft); display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: var(--accent);' }, (agent.displayName || agent.name || '?')[0].toUpperCase()),
|
|
267
|
+
h('div', { style: css('width: 32px; height: 32px; border-radius: 50%; background: var(--accent-soft); display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: var(--accent);') }, (agent.displayName || agent.name || '?')[0].toUpperCase()),
|
|
250
268
|
h('div', null,
|
|
251
269
|
h('div', { style: s.cardTitle }, agent.displayName || agent.name),
|
|
252
270
|
h('div', { style: s.cardType }, grants.length + ' database' + (grants.length !== 1 ? 's' : '')),
|
|
@@ -256,17 +274,17 @@ function AgentAccessTab(props) {
|
|
|
256
274
|
var conn = grant.connection || {};
|
|
257
275
|
var dbType = ALL_DB_TYPES.find(function(t) { return t.value === conn.type; });
|
|
258
276
|
return h('div', { key: grant.connectionId, style: s.agentRow },
|
|
259
|
-
h('div', { style: 'display: flex; align-items: center; gap: 8px;' },
|
|
277
|
+
h('div', { style: css('display: flex; align-items: center; gap: 8px;') },
|
|
260
278
|
h('span', null, dbType ? dbType.icon : '🗄️'),
|
|
261
279
|
h('span', { style: s.agentName }, conn.name || grant.connectionId),
|
|
262
280
|
),
|
|
263
281
|
h('div', { style: s.agentPerms },
|
|
264
282
|
(grant.permissions || []).map(function(p) {
|
|
265
283
|
var permDef = PERMISSIONS.find(function(x) { return x.value === p; });
|
|
266
|
-
return h('span', { key: p, style: s.miniChip
|
|
284
|
+
return h('span', { key: p, style: Object.assign({}, s.miniChip, { background: (permDef ? permDef.color : 'var(--text-muted)') + '22', color: permDef ? permDef.color : 'var(--text-muted)' }) }, p);
|
|
267
285
|
})
|
|
268
286
|
),
|
|
269
|
-
h('button', { style: s.btnDanger
|
|
287
|
+
h('button', { style: Object.assign({}, s.btnDanger, { padding: '3px 8px', fontSize: '11px' }), onClick: async function() {
|
|
270
288
|
if (!confirm('Revoke ' + (agent.displayName || agent.name) + ' access to ' + (conn.name || 'this database') + '?')) return;
|
|
271
289
|
await engineCall('/database/connections/' + grant.connectionId + '/agents/' + agent.id, { method: 'DELETE' });
|
|
272
290
|
props.onRefresh();
|
|
@@ -284,12 +302,12 @@ function AuditTab(props) {
|
|
|
284
302
|
if (props.auditLog.length === 0) {
|
|
285
303
|
return h('div', { style: s.emptyState },
|
|
286
304
|
h('div', { style: s.emptyIcon }, '📋'),
|
|
287
|
-
h('div', { style: 'font-size: 16px; font-weight: 600; margin-bottom: 8px;' }, 'No Query Activity Yet'),
|
|
305
|
+
h('div', { style: css('font-size: 16px; font-weight: 600; margin-bottom: 8px;') }, 'No Query Activity Yet'),
|
|
288
306
|
h('div', null, 'Queries executed by agents will appear here with full audit details.'),
|
|
289
307
|
);
|
|
290
308
|
}
|
|
291
309
|
|
|
292
|
-
return h('div', { style: 'overflow-x: auto;' },
|
|
310
|
+
return h('div', { style: css('overflow-x: auto;') },
|
|
293
311
|
h('table', { style: s.auditTable },
|
|
294
312
|
h('thead', null, h('tr', null,
|
|
295
313
|
h('th', { style: s.auditTh }, 'Time'),
|
|
@@ -308,13 +326,13 @@ function AuditTab(props) {
|
|
|
308
326
|
h('td', { style: s.auditTd }, new Date(entry.timestamp).toLocaleString()),
|
|
309
327
|
h('td', { style: s.auditTd }, entry.agent_name || entry.agent_id?.slice(0, 8)),
|
|
310
328
|
h('td', { style: s.auditTd }, entry.connection_name || entry.connection_id?.slice(0, 8)),
|
|
311
|
-
h('td', { style: s.auditTd
|
|
312
|
-
h('td', { style: s.auditTd
|
|
329
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontWeight: 600, color: opColor }) }, entry.operation),
|
|
330
|
+
h('td', { style: Object.assign({}, s.auditTd, { fontFamily: 'monospace', fontSize: '11px', maxWidth: '300px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }) }, entry.query),
|
|
313
331
|
h('td', { style: s.auditTd }, entry.rows_affected),
|
|
314
332
|
h('td', { style: s.auditTd }, entry.execution_time_ms + 'ms'),
|
|
315
333
|
h('td', { style: s.auditTd }, entry.success
|
|
316
|
-
? h('span', { style: s.badge
|
|
317
|
-
: h('span', { style: s.badge
|
|
334
|
+
? h('span', { style: Object.assign({}, s.badge, s.badgeActive) }, 'OK')
|
|
335
|
+
: h('span', { style: Object.assign({}, s.badge, s.badgeError), title: entry.error }, 'FAIL')
|
|
318
336
|
),
|
|
319
337
|
);
|
|
320
338
|
})
|
|
@@ -373,14 +391,14 @@ function AddConnectionModal(props) {
|
|
|
373
391
|
style: isActive ? s.dbPickerItemActive : s.dbPickerItem,
|
|
374
392
|
onClick: function() { setDbType(item.value); },
|
|
375
393
|
},
|
|
376
|
-
h('div', { style: 'font-size: 24px; margin-bottom: 4px;' }, item.icon),
|
|
377
|
-
h('div', { style: 'font-size: 12px; font-weight: 500;' }, item.label),
|
|
394
|
+
h('div', { style: css('font-size: 24px; margin-bottom: 4px;') }, item.icon),
|
|
395
|
+
h('div', { style: css('font-size: 12px; font-weight: 500;') }, item.label),
|
|
378
396
|
);
|
|
379
397
|
})
|
|
380
398
|
),
|
|
381
399
|
);
|
|
382
400
|
}),
|
|
383
|
-
h('div', { style: 'display: flex; justify-content: flex-end; margin-top: 8px;' },
|
|
401
|
+
h('div', { style: css('display: flex; justify-content: flex-end; margin-top: 8px;') },
|
|
384
402
|
h('button', { style: s.btnPrimary, disabled: !dbType, onClick: function() { setStep(2); } }, 'Next →'),
|
|
385
403
|
),
|
|
386
404
|
),
|
|
@@ -395,13 +413,13 @@ function AddConnectionModal(props) {
|
|
|
395
413
|
h('input', { style: s.input, type: 'password', placeholder: 'postgresql://user:pass@host:5432/db', value: form.connectionString, onInput: function(e) { set('connectionString', e.target.value); } }),
|
|
396
414
|
),
|
|
397
415
|
!isConnString && h(Fragment, null,
|
|
398
|
-
h('div', { style: 'text-align: center; font-size: 12px; color: var(--text-muted); margin: -8px 0;' }, '— or enter fields —'),
|
|
416
|
+
h('div', { style: css('text-align: center; font-size: 12px; color: var(--text-muted); margin: -8px 0;') }, '— or enter fields —'),
|
|
399
417
|
h('div', { style: s.row },
|
|
400
418
|
h('div', { style: s.col },
|
|
401
419
|
h('div', { style: s.label }, 'Host'),
|
|
402
420
|
h('input', { style: s.input, placeholder: 'localhost', value: form.host, onInput: function(e) { set('host', e.target.value); } }),
|
|
403
421
|
),
|
|
404
|
-
h('div', { style: 'width: 100px;' },
|
|
422
|
+
h('div', { style: css('width: 100px;') },
|
|
405
423
|
h('div', { style: s.label }, 'Port'),
|
|
406
424
|
h('input', { style: s.input, placeholder: '5432', value: form.port, onInput: function(e) { set('port', e.target.value); } }),
|
|
407
425
|
),
|
|
@@ -420,7 +438,7 @@ function AddConnectionModal(props) {
|
|
|
420
438
|
h('input', { style: s.input, type: 'password', value: form.password, onInput: function(e) { set('password', e.target.value); } }),
|
|
421
439
|
),
|
|
422
440
|
),
|
|
423
|
-
h('label', { style: 'display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;' },
|
|
441
|
+
h('label', { style: css('display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;') },
|
|
424
442
|
h('input', { type: 'checkbox', checked: form.ssl, onChange: function(e) { set('ssl', e.target.checked); } }),
|
|
425
443
|
'Use SSL/TLS',
|
|
426
444
|
),
|
|
@@ -429,7 +447,7 @@ function AddConnectionModal(props) {
|
|
|
429
447
|
h('div', { style: s.label }, 'Description (optional)'),
|
|
430
448
|
h('input', { style: s.input, placeholder: 'What is this database used for?', value: form.description, onInput: function(e) { set('description', e.target.value); } }),
|
|
431
449
|
),
|
|
432
|
-
h('div', { style: 'display: flex; justify-content: space-between; margin-top: 8px;' },
|
|
450
|
+
h('div', { style: css('display: flex; justify-content: space-between; margin-top: 8px;') },
|
|
433
451
|
h('button', { style: s.btn, onClick: function() { setStep(1); } }, '← Back'),
|
|
434
452
|
h('button', { style: s.btnPrimary, disabled: saving || (!isConnString && !form.host), onClick: save }, saving ? 'Saving...' : 'Add Connection'),
|
|
435
453
|
),
|
|
@@ -507,7 +525,7 @@ function GrantAccessModal(props) {
|
|
|
507
525
|
key: p.value,
|
|
508
526
|
style: active ? s.permChipActive : s.permChip,
|
|
509
527
|
onClick: function() { togglePerm(p.value); },
|
|
510
|
-
}, p.label, h('span', { style: 'font-size: 10px; color: var(--text-muted); margin-left: 4px;' }, p.desc));
|
|
528
|
+
}, p.label, h('span', { style: css('font-size: 10px; color: var(--text-muted); margin-left: 4px;') }, p.desc));
|
|
511
529
|
})
|
|
512
530
|
),
|
|
513
531
|
),
|
|
@@ -529,15 +547,15 @@ function GrantAccessModal(props) {
|
|
|
529
547
|
h('div', { style: s.label }, 'Blocked Tables (comma-separated)'),
|
|
530
548
|
h('input', { style: s.input, placeholder: 'users_secrets, payment_tokens', value: blockedTables, onInput: function(e) { setBlockedTables(e.target.value); } }),
|
|
531
549
|
),
|
|
532
|
-
h('label', { style: 'display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;' },
|
|
550
|
+
h('label', { style: css('display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;') },
|
|
533
551
|
h('input', { type: 'checkbox', checked: logAll, onChange: function(e) { setLogAll(e.target.checked); } }),
|
|
534
552
|
'Log ALL queries (including reads)',
|
|
535
553
|
),
|
|
536
|
-
h('label', { style: 'display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;' },
|
|
554
|
+
h('label', { style: css('display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;') },
|
|
537
555
|
h('input', { type: 'checkbox', checked: requireApproval, onChange: function(e) { setRequireApproval(e.target.checked); } }),
|
|
538
556
|
'Require human approval for write/delete',
|
|
539
557
|
),
|
|
540
|
-
h('div', { style: 'display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px;' },
|
|
558
|
+
h('div', { style: css('display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px;') },
|
|
541
559
|
h('button', { style: s.btn, onClick: props.onClose }, 'Cancel'),
|
|
542
560
|
h('button', { style: s.btnPrimary, disabled: saving || !agentId, onClick: save }, saving ? 'Granting...' : 'Grant Access'),
|
|
543
561
|
),
|
|
@@ -585,7 +603,7 @@ function EditConnectionModal(props) {
|
|
|
585
603
|
h('div', { style: s.label }, 'Host'),
|
|
586
604
|
h('input', { style: s.input, value: form.host, onInput: function(e) { set('host', e.target.value); } }),
|
|
587
605
|
),
|
|
588
|
-
h('div', { style: 'width: 100px;' },
|
|
606
|
+
h('div', { style: css('width: 100px;') },
|
|
589
607
|
h('div', { style: s.label }, 'Port'),
|
|
590
608
|
h('input', { style: s.input, value: form.port, onInput: function(e) { set('port', e.target.value); } }),
|
|
591
609
|
),
|
|
@@ -598,11 +616,11 @@ function EditConnectionModal(props) {
|
|
|
598
616
|
h('div', { style: s.label }, 'Description'),
|
|
599
617
|
h('input', { style: s.input, value: form.description, onInput: function(e) { set('description', e.target.value); } }),
|
|
600
618
|
),
|
|
601
|
-
h('label', { style: 'display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;' },
|
|
619
|
+
h('label', { style: css('display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;') },
|
|
602
620
|
h('input', { type: 'checkbox', checked: form.ssl, onChange: function(e) { set('ssl', e.target.checked); } }),
|
|
603
621
|
'Use SSL/TLS',
|
|
604
622
|
),
|
|
605
|
-
h('div', { style: 'display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px;' },
|
|
623
|
+
h('div', { style: css('display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px;') },
|
|
606
624
|
h('button', { style: s.btn, onClick: props.onClose }, 'Cancel'),
|
|
607
625
|
h('button', { style: s.btnPrimary, disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Changes'),
|
|
608
626
|
),
|