@agenticmail/enterprise 0.5.167 → 0.5.169
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-autonomy-GSH6XDPR.js +650 -0
- package/dist/agent-autonomy-VSPXV7QH.js +591 -0
- package/dist/chunk-2ALM5WEM.js +2195 -0
- package/dist/chunk-OZ7OBEUD.js +16484 -0
- package/dist/chunk-RNHBMPPK.js +898 -0
- package/dist/cli-agent-7225VCWQ.js +987 -0
- package/dist/cli-agent-SHOCSBKU.js +993 -0
- package/dist/cli-serve-D5G3XNSI.js +34 -0
- package/dist/cli.js +3 -3
- package/dist/dashboard/pages/agent-detail.js +224 -2
- package/dist/index.js +3 -3
- package/dist/runtime-RNR3Y7HR.js +49 -0
- package/dist/server-O45YMZQ3.js +12 -0
- package/dist/setup-NLVGTWZ3.js +20 -0
- package/package.json +1 -1
- package/src/agent-tools/tools/google/drive.ts +72 -2
- package/src/cli-agent.ts +112 -1
- package/src/dashboard/pages/agent-detail.js +224 -2
- package/src/engine/agent-autonomy.ts +837 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "./chunk-KFQGP6VL.js";
|
|
2
|
+
|
|
3
|
+
// src/cli-serve.ts
|
|
4
|
+
async function runServe(_args) {
|
|
5
|
+
const DATABASE_URL = process.env.DATABASE_URL;
|
|
6
|
+
const JWT_SECRET = process.env.JWT_SECRET;
|
|
7
|
+
const PORT = parseInt(process.env.PORT || "8080", 10);
|
|
8
|
+
if (!DATABASE_URL) {
|
|
9
|
+
console.error("ERROR: DATABASE_URL environment variable is required");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
if (!JWT_SECRET) {
|
|
13
|
+
console.error("ERROR: JWT_SECRET environment variable is required");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const { createAdapter } = await import("./factory-MBP7N2OQ.js");
|
|
17
|
+
const { createServer } = await import("./server-O45YMZQ3.js");
|
|
18
|
+
const db = await createAdapter({
|
|
19
|
+
type: DATABASE_URL.startsWith("postgres") ? "postgres" : "sqlite",
|
|
20
|
+
connectionString: DATABASE_URL
|
|
21
|
+
});
|
|
22
|
+
await db.migrate();
|
|
23
|
+
const server = createServer({
|
|
24
|
+
port: PORT,
|
|
25
|
+
db,
|
|
26
|
+
jwtSecret: JWT_SECRET,
|
|
27
|
+
corsOrigins: ["*"]
|
|
28
|
+
});
|
|
29
|
+
await server.start();
|
|
30
|
+
console.log(`AgenticMail Enterprise server running on :${PORT}`);
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
runServe
|
|
34
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -47,14 +47,14 @@ Skill Development:
|
|
|
47
47
|
`);
|
|
48
48
|
break;
|
|
49
49
|
case "serve":
|
|
50
|
-
import("./cli-serve-
|
|
50
|
+
import("./cli-serve-D5G3XNSI.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
|
|
51
51
|
break;
|
|
52
52
|
case "agent":
|
|
53
|
-
import("./cli-agent-
|
|
53
|
+
import("./cli-agent-SHOCSBKU.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
|
|
54
54
|
break;
|
|
55
55
|
case "setup":
|
|
56
56
|
default:
|
|
57
|
-
import("./setup-
|
|
57
|
+
import("./setup-NLVGTWZ3.js").then((m) => m.runSetupWizard()).catch(fatal);
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
60
60
|
function fatal(err) {
|
|
@@ -6410,6 +6410,227 @@ function ToolSecuritySection(props) {
|
|
|
6410
6410
|
// AGENT DETAIL PAGE (Main Orchestrator)
|
|
6411
6411
|
// ════════════════════════════════════════════════════════════
|
|
6412
6412
|
|
|
6413
|
+
// ─── Autonomy Settings Section ──────────────────────────
|
|
6414
|
+
|
|
6415
|
+
function AutonomySection(props) {
|
|
6416
|
+
var agentId = props.agentId;
|
|
6417
|
+
var engineAgent = props.engineAgent;
|
|
6418
|
+
var reload = props.reload;
|
|
6419
|
+
var app = useApp();
|
|
6420
|
+
var toast = app.toast;
|
|
6421
|
+
|
|
6422
|
+
var defaults = {
|
|
6423
|
+
enabled: true,
|
|
6424
|
+
clockEnabled: true,
|
|
6425
|
+
dailyCatchupEnabled: true, dailyCatchupHour: 9, dailyCatchupMinute: 0,
|
|
6426
|
+
weeklyCatchupEnabled: true, weeklyCatchupDay: 1, weeklyCatchupHour: 9, weeklyCatchupMinute: 0,
|
|
6427
|
+
goalCheckEnabled: true, goalCheckHours: [14, 17],
|
|
6428
|
+
knowledgeContribEnabled: true, knowledgeContribDay: 5, knowledgeContribHour: 15,
|
|
6429
|
+
escalationEnabled: true, guardrailEnforcementEnabled: true, driveAccessRequestEnabled: true,
|
|
6430
|
+
};
|
|
6431
|
+
|
|
6432
|
+
var existing = (engineAgent?.config?.autonomy) || {};
|
|
6433
|
+
var _form = useState(Object.assign({}, defaults, existing));
|
|
6434
|
+
var form = _form[0]; var setForm = _form[1];
|
|
6435
|
+
var _saving = useState(false);
|
|
6436
|
+
var saving = _saving[0]; var setSaving = _saving[1];
|
|
6437
|
+
var _dirty = useState(false);
|
|
6438
|
+
var dirty = _dirty[0]; var setDirty = _dirty[1];
|
|
6439
|
+
|
|
6440
|
+
var set = function(key, val) {
|
|
6441
|
+
var u = Object.assign({}, form);
|
|
6442
|
+
u[key] = val;
|
|
6443
|
+
setForm(u);
|
|
6444
|
+
setDirty(true);
|
|
6445
|
+
};
|
|
6446
|
+
|
|
6447
|
+
var save = function() {
|
|
6448
|
+
setSaving(true);
|
|
6449
|
+
var ea = engineAgent || {};
|
|
6450
|
+
var isRunning = ea.state === 'running' || ea.state === 'active' || ea.state === 'degraded';
|
|
6451
|
+
var endpoint = isRunning ? '/agents/' + agentId + '/hot-update' : '/agents/' + agentId + '/config';
|
|
6452
|
+
var method = isRunning ? 'POST' : 'PATCH';
|
|
6453
|
+
engineCall(endpoint, {
|
|
6454
|
+
method: method,
|
|
6455
|
+
body: JSON.stringify({ updates: { autonomy: form }, updatedBy: 'dashboard' })
|
|
6456
|
+
}).then(function() {
|
|
6457
|
+
toast('Autonomy settings saved' + (isRunning ? ' (agent will reload within 10 min)' : ''), 'success');
|
|
6458
|
+
setDirty(false);
|
|
6459
|
+
setSaving(false);
|
|
6460
|
+
if (reload) reload();
|
|
6461
|
+
}).catch(function(err) {
|
|
6462
|
+
toast(err.message, 'error');
|
|
6463
|
+
setSaving(false);
|
|
6464
|
+
});
|
|
6465
|
+
};
|
|
6466
|
+
|
|
6467
|
+
var DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
6468
|
+
|
|
6469
|
+
var toggleStyle = function(on) {
|
|
6470
|
+
return {
|
|
6471
|
+
width: 40, height: 22, borderRadius: 11,
|
|
6472
|
+
background: on ? 'var(--success)' : 'var(--border)',
|
|
6473
|
+
cursor: 'pointer', position: 'relative', flexShrink: 0,
|
|
6474
|
+
transition: 'background 0.2s', display: 'inline-block',
|
|
6475
|
+
};
|
|
6476
|
+
};
|
|
6477
|
+
var knobStyle = function(on) {
|
|
6478
|
+
return {
|
|
6479
|
+
width: 18, height: 18, borderRadius: '50%', background: '#fff',
|
|
6480
|
+
position: 'absolute', top: 2, left: on ? 20 : 2,
|
|
6481
|
+
transition: 'left 0.2s', boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
|
|
6482
|
+
};
|
|
6483
|
+
};
|
|
6484
|
+
|
|
6485
|
+
var Toggle = function(p) {
|
|
6486
|
+
return h('div', { style: { display: 'flex', alignItems: 'center', gap: 10 } },
|
|
6487
|
+
h('div', { style: toggleStyle(p.value), onClick: function() { set(p.field, !p.value); } },
|
|
6488
|
+
h('div', { style: knobStyle(p.value) })
|
|
6489
|
+
),
|
|
6490
|
+
h('span', { style: { fontSize: 13, fontWeight: 500 } }, p.label),
|
|
6491
|
+
p.desc && h('span', { style: { fontSize: 11, color: 'var(--text-muted)' } }, p.desc)
|
|
6492
|
+
);
|
|
6493
|
+
};
|
|
6494
|
+
|
|
6495
|
+
var TimeSelect = function(p) {
|
|
6496
|
+
return h('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
|
|
6497
|
+
h('select', { className: 'input', style: { width: 80 }, value: p.hour, onChange: function(e) { set(p.hourField, parseInt(e.target.value)); } },
|
|
6498
|
+
Array.from({length: 24}, function(_, i) {
|
|
6499
|
+
var label = i === 0 ? '12 AM' : i < 12 ? i + ' AM' : i === 12 ? '12 PM' : (i - 12) + ' PM';
|
|
6500
|
+
return h('option', { key: i, value: i }, label);
|
|
6501
|
+
})
|
|
6502
|
+
),
|
|
6503
|
+
h('span', null, ':'),
|
|
6504
|
+
h('select', { className: 'input', style: { width: 65 }, value: p.minute, onChange: function(e) { set(p.minuteField, parseInt(e.target.value)); } },
|
|
6505
|
+
[0, 15, 30, 45].map(function(m) { return h('option', { key: m, value: m }, String(m).padStart(2, '0')); })
|
|
6506
|
+
)
|
|
6507
|
+
);
|
|
6508
|
+
};
|
|
6509
|
+
|
|
6510
|
+
var DaySelect = function(p) {
|
|
6511
|
+
return h('select', { className: 'input', style: { width: 130 }, value: p.value, onChange: function(e) { set(p.field, parseInt(e.target.value)); } },
|
|
6512
|
+
DAYS.map(function(d, i) { return h('option', { key: i, value: i }, d); })
|
|
6513
|
+
);
|
|
6514
|
+
};
|
|
6515
|
+
|
|
6516
|
+
var cardStyle = { marginBottom: 12 };
|
|
6517
|
+
var rowStyle = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 16px', borderBottom: '1px solid var(--border)' };
|
|
6518
|
+
var configRow = { display: 'flex', gap: 12, alignItems: 'center', padding: '8px 16px 8px 48px', borderBottom: '1px solid var(--border)', fontSize: 13 };
|
|
6519
|
+
|
|
6520
|
+
return h(Fragment, null,
|
|
6521
|
+
// Header
|
|
6522
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 } },
|
|
6523
|
+
h('div', null,
|
|
6524
|
+
h('div', { style: { fontSize: 15, fontWeight: 600 } }, 'Agent Autonomy Settings'),
|
|
6525
|
+
h('div', { style: { fontSize: 12, color: 'var(--text-muted)' } }, 'Configure automated behaviors — all times use agent timezone')
|
|
6526
|
+
),
|
|
6527
|
+
h('div', { style: { display: 'flex', gap: 8 } },
|
|
6528
|
+
dirty && h('span', { style: { fontSize: 11, color: 'var(--warning)', alignSelf: 'center' } }, 'Unsaved changes'),
|
|
6529
|
+
h('button', { className: 'btn btn-primary btn-sm', disabled: !dirty || saving, onClick: save }, saving ? 'Saving...' : 'Save')
|
|
6530
|
+
)
|
|
6531
|
+
),
|
|
6532
|
+
|
|
6533
|
+
// Master switch
|
|
6534
|
+
h('div', { className: 'card', style: cardStyle },
|
|
6535
|
+
h('div', { style: rowStyle },
|
|
6536
|
+
h(Toggle, { field: 'enabled', value: form.enabled, label: 'Enable Autonomy System', desc: 'Master switch for all automated agent behaviors' })
|
|
6537
|
+
)
|
|
6538
|
+
),
|
|
6539
|
+
|
|
6540
|
+
// Clock In/Out
|
|
6541
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6542
|
+
h('div', { style: rowStyle },
|
|
6543
|
+
h(Toggle, { field: 'clockEnabled', value: form.clockEnabled, label: 'Auto Clock-In/Out', desc: 'Clock in/out based on work schedule' })
|
|
6544
|
+
),
|
|
6545
|
+
form.clockEnabled && h('div', { style: configRow },
|
|
6546
|
+
h('span', { style: { color: 'var(--text-muted)' } }, 'Uses times from the Workforce tab schedule')
|
|
6547
|
+
)
|
|
6548
|
+
),
|
|
6549
|
+
|
|
6550
|
+
// Daily Catchup
|
|
6551
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6552
|
+
h('div', { style: rowStyle },
|
|
6553
|
+
h(Toggle, { field: 'dailyCatchupEnabled', value: form.dailyCatchupEnabled, label: 'Daily Manager Catchup', desc: 'Email summary to manager each workday' })
|
|
6554
|
+
),
|
|
6555
|
+
form.dailyCatchupEnabled && h('div', { style: configRow },
|
|
6556
|
+
h('span', null, 'Send at'),
|
|
6557
|
+
h(TimeSelect, { hour: form.dailyCatchupHour, minute: form.dailyCatchupMinute, hourField: 'dailyCatchupHour', minuteField: 'dailyCatchupMinute' })
|
|
6558
|
+
)
|
|
6559
|
+
),
|
|
6560
|
+
|
|
6561
|
+
// Weekly Catchup
|
|
6562
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6563
|
+
h('div', { style: rowStyle },
|
|
6564
|
+
h(Toggle, { field: 'weeklyCatchupEnabled', value: form.weeklyCatchupEnabled, label: 'Weekly Manager Catchup', desc: 'Broader summary + goals, replaces daily on chosen day' })
|
|
6565
|
+
),
|
|
6566
|
+
form.weeklyCatchupEnabled && h('div', { style: configRow },
|
|
6567
|
+
h('span', null, 'Send on'),
|
|
6568
|
+
h(DaySelect, { value: form.weeklyCatchupDay, field: 'weeklyCatchupDay' }),
|
|
6569
|
+
h('span', null, 'at'),
|
|
6570
|
+
h(TimeSelect, { hour: form.weeklyCatchupHour, minute: form.weeklyCatchupMinute, hourField: 'weeklyCatchupHour', minuteField: 'weeklyCatchupMinute' })
|
|
6571
|
+
)
|
|
6572
|
+
),
|
|
6573
|
+
|
|
6574
|
+
// Goal Check
|
|
6575
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6576
|
+
h('div', { style: rowStyle },
|
|
6577
|
+
h(Toggle, { field: 'goalCheckEnabled', value: form.goalCheckEnabled, label: 'Goal Progress Checks', desc: 'Reviews Google Tasks at set hours (last = end-of-day review)' })
|
|
6578
|
+
),
|
|
6579
|
+
form.goalCheckEnabled && h('div', { style: configRow },
|
|
6580
|
+
h('span', null, 'Check at hours:'),
|
|
6581
|
+
h('input', { className: 'input', style: { width: 150 },
|
|
6582
|
+
value: (form.goalCheckHours || [14, 17]).join(', '),
|
|
6583
|
+
placeholder: '14, 17',
|
|
6584
|
+
onChange: function(e) {
|
|
6585
|
+
var hrs = e.target.value.split(',').map(function(s) { return parseInt(s.trim()); }).filter(function(n) { return !isNaN(n) && n >= 0 && n <= 23; });
|
|
6586
|
+
set('goalCheckHours', hrs.length > 0 ? hrs : [14, 17]);
|
|
6587
|
+
}
|
|
6588
|
+
}),
|
|
6589
|
+
h('span', { style: { fontSize: 11, color: 'var(--text-muted)' } }, '(24h format, comma-separated)')
|
|
6590
|
+
)
|
|
6591
|
+
),
|
|
6592
|
+
|
|
6593
|
+
// Knowledge Contribution
|
|
6594
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6595
|
+
h('div', { style: rowStyle },
|
|
6596
|
+
h(Toggle, { field: 'knowledgeContribEnabled', value: form.knowledgeContribEnabled, label: 'Weekly Knowledge Contribution', desc: 'Agent reviews learnings and contributes to role-based knowledge base' })
|
|
6597
|
+
),
|
|
6598
|
+
form.knowledgeContribEnabled && h('div', { style: configRow },
|
|
6599
|
+
h('span', null, 'Contribute on'),
|
|
6600
|
+
h(DaySelect, { value: form.knowledgeContribDay, field: 'knowledgeContribDay' }),
|
|
6601
|
+
h('span', null, 'at'),
|
|
6602
|
+
h('select', { className: 'input', style: { width: 80 }, value: form.knowledgeContribHour, onChange: function(e) { set('knowledgeContribHour', parseInt(e.target.value)); } },
|
|
6603
|
+
Array.from({length: 24}, function(_, i) {
|
|
6604
|
+
var label = i === 0 ? '12 AM' : i < 12 ? i + ' AM' : i === 12 ? '12 PM' : (i - 12) + ' PM';
|
|
6605
|
+
return h('option', { key: i, value: i }, label);
|
|
6606
|
+
})
|
|
6607
|
+
)
|
|
6608
|
+
)
|
|
6609
|
+
),
|
|
6610
|
+
|
|
6611
|
+
// Smart Escalation
|
|
6612
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6613
|
+
h('div', { style: rowStyle },
|
|
6614
|
+
h(Toggle, { field: 'escalationEnabled', value: form.escalationEnabled, label: 'Smart Answer Escalation', desc: 'Search memory → Drive → escalate to manager when unsure' })
|
|
6615
|
+
)
|
|
6616
|
+
),
|
|
6617
|
+
|
|
6618
|
+
// Guardrail Enforcement
|
|
6619
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6620
|
+
h('div', { style: rowStyle },
|
|
6621
|
+
h(Toggle, { field: 'guardrailEnforcementEnabled', value: form.guardrailEnforcementEnabled, label: 'Runtime Guardrail Enforcement', desc: 'Evaluate guardrail rules on inbound emails and tool calls' })
|
|
6622
|
+
)
|
|
6623
|
+
),
|
|
6624
|
+
|
|
6625
|
+
// Drive Access Requests
|
|
6626
|
+
h('div', { className: 'card', style: Object.assign({}, cardStyle, { opacity: form.enabled ? 1 : 0.5 }) },
|
|
6627
|
+
h('div', { style: rowStyle },
|
|
6628
|
+
h(Toggle, { field: 'driveAccessRequestEnabled', value: form.driveAccessRequestEnabled, label: 'Drive Access Requests', desc: 'When agent cannot access a file, it requests access from manager instead of failing silently' })
|
|
6629
|
+
)
|
|
6630
|
+
)
|
|
6631
|
+
);
|
|
6632
|
+
}
|
|
6633
|
+
|
|
6413
6634
|
function AgentDetailPage(props) {
|
|
6414
6635
|
var agentId = props.agentId;
|
|
6415
6636
|
var onBack = props.onBack;
|
|
@@ -6430,8 +6651,8 @@ function AgentDetailPage(props) {
|
|
|
6430
6651
|
var _agents = useState([]);
|
|
6431
6652
|
var agents = _agents[0]; var setAgents = _agents[1];
|
|
6432
6653
|
|
|
6433
|
-
var TABS = ['overview', 'personal', 'email', 'configuration', 'manager', 'tools', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'budget', 'tool-security', 'deployment'];
|
|
6434
|
-
var TAB_LABELS = { 'tool-security': 'Tool Security', 'manager': 'Manager & Catch-Up', 'email': 'Email', 'tools': 'Tools' };
|
|
6654
|
+
var TABS = ['overview', 'personal', 'email', 'configuration', 'manager', 'tools', 'skills', 'permissions', 'activity', 'communication', 'workforce', 'memory', 'guardrails', 'autonomy', 'budget', 'tool-security', 'deployment'];
|
|
6655
|
+
var TAB_LABELS = { 'tool-security': 'Tool Security', 'manager': 'Manager & Catch-Up', 'email': 'Email', 'tools': 'Tools', 'autonomy': 'Autonomy' };
|
|
6435
6656
|
|
|
6436
6657
|
var load = function() {
|
|
6437
6658
|
setLoading(true);
|
|
@@ -6563,6 +6784,7 @@ function AgentDetailPage(props) {
|
|
|
6563
6784
|
tab === 'workforce' && h(WorkforceSection, { agentId: agentId }),
|
|
6564
6785
|
tab === 'memory' && h(MemorySection, { agentId: agentId }),
|
|
6565
6786
|
tab === 'guardrails' && h(GuardrailsSection, { agentId: agentId, agents: agents }),
|
|
6787
|
+
tab === 'autonomy' && h(AutonomySection, { agentId: agentId, engineAgent: engineAgent, reload: load }),
|
|
6566
6788
|
tab === 'budget' && h(BudgetSection, { agentId: agentId }),
|
|
6567
6789
|
tab === 'tool-security' && h(ToolSecuritySection, { agentId: agentId }),
|
|
6568
6790
|
tab === 'deployment' && h(DeploymentSection, { agentId: agentId, engineAgent: engineAgent, agent: agent, reload: load, onBack: onBack })
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
provision,
|
|
9
9
|
runSetupWizard
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-RNHBMPPK.js";
|
|
11
11
|
import {
|
|
12
12
|
ActionJournal,
|
|
13
13
|
ActivityTracker,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
executeTool,
|
|
55
55
|
runAgentLoop,
|
|
56
56
|
toolsToDefinitions
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-OZ7OBEUD.js";
|
|
58
58
|
import "./chunk-AQH4DFYV.js";
|
|
59
59
|
import {
|
|
60
60
|
ValidationError,
|
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
requireRole,
|
|
70
70
|
securityHeaders,
|
|
71
71
|
validate
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-2ALM5WEM.js";
|
|
73
73
|
import "./chunk-3SMTCIR4.js";
|
|
74
74
|
import {
|
|
75
75
|
CircuitBreaker,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentRuntime,
|
|
3
|
+
EmailChannel,
|
|
4
|
+
FollowUpScheduler,
|
|
5
|
+
SessionManager,
|
|
6
|
+
SubAgentManager,
|
|
7
|
+
ToolRegistry,
|
|
8
|
+
callLLM,
|
|
9
|
+
createAgentRuntime,
|
|
10
|
+
createNoopHooks,
|
|
11
|
+
createRuntimeHooks,
|
|
12
|
+
estimateMessageTokens,
|
|
13
|
+
estimateTokens,
|
|
14
|
+
executeTool,
|
|
15
|
+
runAgentLoop,
|
|
16
|
+
toolsToDefinitions
|
|
17
|
+
} from "./chunk-OZ7OBEUD.js";
|
|
18
|
+
import "./chunk-AQH4DFYV.js";
|
|
19
|
+
import "./chunk-JLSQOQ5L.js";
|
|
20
|
+
import {
|
|
21
|
+
PROVIDER_REGISTRY,
|
|
22
|
+
listAllProviders,
|
|
23
|
+
resolveApiKeyForProvider,
|
|
24
|
+
resolveProvider
|
|
25
|
+
} from "./chunk-67KZYSLU.js";
|
|
26
|
+
import "./chunk-NRF3YRF7.js";
|
|
27
|
+
import "./chunk-TYW5XTOW.js";
|
|
28
|
+
import "./chunk-KFQGP6VL.js";
|
|
29
|
+
export {
|
|
30
|
+
AgentRuntime,
|
|
31
|
+
EmailChannel,
|
|
32
|
+
FollowUpScheduler,
|
|
33
|
+
PROVIDER_REGISTRY,
|
|
34
|
+
SessionManager,
|
|
35
|
+
SubAgentManager,
|
|
36
|
+
ToolRegistry,
|
|
37
|
+
callLLM,
|
|
38
|
+
createAgentRuntime,
|
|
39
|
+
createNoopHooks,
|
|
40
|
+
createRuntimeHooks,
|
|
41
|
+
estimateMessageTokens,
|
|
42
|
+
estimateTokens,
|
|
43
|
+
executeTool,
|
|
44
|
+
listAllProviders,
|
|
45
|
+
resolveApiKeyForProvider,
|
|
46
|
+
resolveProvider,
|
|
47
|
+
runAgentLoop,
|
|
48
|
+
toolsToDefinitions
|
|
49
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createServer
|
|
3
|
+
} from "./chunk-2ALM5WEM.js";
|
|
4
|
+
import "./chunk-3SMTCIR4.js";
|
|
5
|
+
import "./chunk-JLSQOQ5L.js";
|
|
6
|
+
import "./chunk-RO537U6H.js";
|
|
7
|
+
import "./chunk-DRXMYYKN.js";
|
|
8
|
+
import "./chunk-67KZYSLU.js";
|
|
9
|
+
import "./chunk-KFQGP6VL.js";
|
|
10
|
+
export {
|
|
11
|
+
createServer
|
|
12
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
promptCompanyInfo,
|
|
3
|
+
promptDatabase,
|
|
4
|
+
promptDeployment,
|
|
5
|
+
promptDomain,
|
|
6
|
+
promptRegistration,
|
|
7
|
+
provision,
|
|
8
|
+
runSetupWizard
|
|
9
|
+
} from "./chunk-RNHBMPPK.js";
|
|
10
|
+
import "./chunk-MHIFVS5L.js";
|
|
11
|
+
import "./chunk-KFQGP6VL.js";
|
|
12
|
+
export {
|
|
13
|
+
promptCompanyInfo,
|
|
14
|
+
promptDatabase,
|
|
15
|
+
promptDeployment,
|
|
16
|
+
promptDomain,
|
|
17
|
+
promptRegistration,
|
|
18
|
+
provision,
|
|
19
|
+
runSetupWizard
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -11,6 +11,17 @@ import type { GoogleToolsConfig } from './index.js';
|
|
|
11
11
|
const BASE = 'https://www.googleapis.com/drive/v3';
|
|
12
12
|
const UPLOAD_BASE = 'https://www.googleapis.com/upload/drive/v3';
|
|
13
13
|
|
|
14
|
+
class DriveAccessError extends Error {
|
|
15
|
+
status: number;
|
|
16
|
+
fileId?: string;
|
|
17
|
+
constructor(message: string, status: number, fileId?: string) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'DriveAccessError';
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.fileId = fileId;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
14
25
|
async function gapi(token: string, path: string, opts?: { method?: string; body?: any; query?: Record<string, string>; base?: string; rawBody?: BodyInit; headers?: Record<string, string> }): Promise<any> {
|
|
15
26
|
const method = opts?.method || 'GET';
|
|
16
27
|
const base = opts?.base || BASE;
|
|
@@ -22,7 +33,15 @@ async function gapi(token: string, path: string, opts?: { method?: string; body?
|
|
|
22
33
|
method, headers,
|
|
23
34
|
body: opts?.rawBody || (opts?.body ? JSON.stringify(opts.body) : undefined),
|
|
24
35
|
});
|
|
25
|
-
if (!res.ok) {
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
const err = await res.text();
|
|
38
|
+
if (res.status === 403 || res.status === 404) {
|
|
39
|
+
// Extract fileId from path if available
|
|
40
|
+
const fileIdMatch = path.match(/\/files\/([^/]+)/);
|
|
41
|
+
throw new DriveAccessError(`Google Drive API ${res.status}: ${err}`, res.status, fileIdMatch?.[1]);
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Google Drive API ${res.status}: ${err}`);
|
|
44
|
+
}
|
|
26
45
|
if (res.status === 204) return {};
|
|
27
46
|
return res.json();
|
|
28
47
|
}
|
|
@@ -84,7 +103,7 @@ export function createGoogleDriveTools(config: GoogleToolsConfig, _options?: Too
|
|
|
84
103
|
},
|
|
85
104
|
{
|
|
86
105
|
name: 'google_drive_get',
|
|
87
|
-
description: 'Get metadata and content of a file. For Google Docs/Sheets/Slides, exports as text. For other files, returns metadata only.',
|
|
106
|
+
description: 'Get metadata and content of a file. For Google Docs/Sheets/Slides, exports as text. For other files, returns metadata only. If you get ACCESS_DENIED, use google_drive_request_access to ask the file owner for access.',
|
|
88
107
|
category: 'utility' as const,
|
|
89
108
|
parameters: {
|
|
90
109
|
type: 'object' as const,
|
|
@@ -129,6 +148,57 @@ export function createGoogleDriveTools(config: GoogleToolsConfig, _options?: Too
|
|
|
129
148
|
}
|
|
130
149
|
}
|
|
131
150
|
return jsonResult(result);
|
|
151
|
+
} catch (e: any) {
|
|
152
|
+
if (e instanceof DriveAccessError && (e.status === 403 || e.status === 404)) {
|
|
153
|
+
return jsonResult({
|
|
154
|
+
error: 'ACCESS_DENIED',
|
|
155
|
+
fileId: params.fileId,
|
|
156
|
+
message: `You do not have access to this file (${e.status}). Use google_drive_request_access to request access from the file owner or your manager.`,
|
|
157
|
+
suggestion: `Call google_drive_request_access with fileId="${params.fileId}" and a reason for needing access.`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return errorResult(e.message);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'google_drive_request_access',
|
|
166
|
+
description: 'Request access to a file you cannot read. Sends an email to your manager (or file owner) asking for access. Use this when google_drive_get returns ACCESS_DENIED.',
|
|
167
|
+
category: 'utility' as const,
|
|
168
|
+
parameters: {
|
|
169
|
+
type: 'object' as const,
|
|
170
|
+
properties: {
|
|
171
|
+
fileId: { type: 'string', description: 'File ID to request access to (required)' },
|
|
172
|
+
reason: { type: 'string', description: 'Why you need access to this file (required)' },
|
|
173
|
+
requesterContext: { type: 'string', description: 'Who asked you to look at this file / what question you are trying to answer' },
|
|
174
|
+
},
|
|
175
|
+
required: ['fileId', 'reason'],
|
|
176
|
+
},
|
|
177
|
+
async execute(_id: string, params: any) {
|
|
178
|
+
try {
|
|
179
|
+
const token = await tp.getAccessToken();
|
|
180
|
+
// Try to get basic file metadata (may fail for 404 but works for some 403)
|
|
181
|
+
let fileName = params.fileId;
|
|
182
|
+
let fileOwner = '';
|
|
183
|
+
let fileLink = `https://drive.google.com/file/d/${params.fileId}/view`;
|
|
184
|
+
try {
|
|
185
|
+
const meta = await gapi(token, `/files/${params.fileId}`, { query: { fields: 'id,name,owners,webViewLink', supportsAllDrives: 'true' } });
|
|
186
|
+
if (meta.name) fileName = meta.name;
|
|
187
|
+
if (meta.owners?.[0]?.emailAddress) fileOwner = meta.owners[0].emailAddress;
|
|
188
|
+
if (meta.webViewLink) fileLink = meta.webViewLink;
|
|
189
|
+
} catch { /* may not have metadata access either */ }
|
|
190
|
+
|
|
191
|
+
// Store the access request in memory for tracking
|
|
192
|
+
return jsonResult({
|
|
193
|
+
accessRequested: true,
|
|
194
|
+
fileId: params.fileId,
|
|
195
|
+
fileName,
|
|
196
|
+
fileOwner: fileOwner || 'unknown',
|
|
197
|
+
fileLink,
|
|
198
|
+
reason: params.reason,
|
|
199
|
+
requesterContext: params.requesterContext || '',
|
|
200
|
+
instruction: `Access request recorded. Email your manager to request access to "${fileName}" (${fileLink}). Include why you need it: ${params.reason}. Wait for the manager to grant access before trying to read the file again. Store this in memory so you can follow up.`,
|
|
201
|
+
});
|
|
132
202
|
} catch (e: any) { return errorResult(e.message); }
|
|
133
203
|
},
|
|
134
204
|
},
|
package/src/cli-agent.ts
CHANGED
|
@@ -498,6 +498,72 @@ Available tools: gmail_send (to, subject, body) or agenticmail_send (to, subject
|
|
|
498
498
|
|
|
499
499
|
// 14. Start calendar polling loop (checks for upcoming meetings to auto-join)
|
|
500
500
|
startCalendarPolling(AGENT_ID, config, runtime, engineDb, memoryManager);
|
|
501
|
+
|
|
502
|
+
// 15. Start agent autonomy system (clock-in/out, catchup emails, goals, knowledge)
|
|
503
|
+
try {
|
|
504
|
+
const { AgentAutonomyManager } = await import('./engine/agent-autonomy.js');
|
|
505
|
+
const orgRows2 = await engineDb.query<any>(`SELECT org_id FROM managed_agents WHERE id = $1`, [AGENT_ID]);
|
|
506
|
+
const autoOrgId = orgRows2?.[0]?.org_id || orgId;
|
|
507
|
+
const managerEmail2 = (config as any).managerEmail || ((config as any).manager?.type === 'external' ? (config as any).manager.email : null);
|
|
508
|
+
|
|
509
|
+
// Parse schedule from work_schedules table
|
|
510
|
+
let schedule: { start: string; end: string; days: number[] } | undefined;
|
|
511
|
+
try {
|
|
512
|
+
const schedRows = await engineDb.query<any>(
|
|
513
|
+
`SELECT config FROM work_schedules WHERE agent_id = $1 ORDER BY created_at DESC LIMIT 1`,
|
|
514
|
+
[AGENT_ID]
|
|
515
|
+
);
|
|
516
|
+
if (schedRows && schedRows.length > 0) {
|
|
517
|
+
const schedConfig = typeof schedRows[0].config === 'string' ? JSON.parse(schedRows[0].config) : schedRows[0].config;
|
|
518
|
+
if (schedConfig?.standardHours) {
|
|
519
|
+
schedule = {
|
|
520
|
+
start: schedConfig.standardHours.start,
|
|
521
|
+
end: schedConfig.standardHours.end,
|
|
522
|
+
days: schedConfig.workDays || [0, 1, 2, 3, 4, 5, 6],
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
} catch {}
|
|
527
|
+
|
|
528
|
+
const autonomy = new AgentAutonomyManager({
|
|
529
|
+
agentId: AGENT_ID,
|
|
530
|
+
orgId: autoOrgId,
|
|
531
|
+
agentName: config.displayName || config.name,
|
|
532
|
+
role: config.identity?.role || 'AI Agent',
|
|
533
|
+
managerEmail: managerEmail2,
|
|
534
|
+
timezone: config.timezone || 'America/New_York',
|
|
535
|
+
schedule,
|
|
536
|
+
runtime,
|
|
537
|
+
engineDb,
|
|
538
|
+
memoryManager,
|
|
539
|
+
lifecycle,
|
|
540
|
+
settings: (config as any).autonomy || {},
|
|
541
|
+
});
|
|
542
|
+
await autonomy.start();
|
|
543
|
+
console.log('[autonomy] ✅ Agent autonomy system started');
|
|
544
|
+
|
|
545
|
+
// Store autonomy ref for shutdown
|
|
546
|
+
const origShutdown = process.listeners('SIGTERM');
|
|
547
|
+
process.on('SIGTERM', () => autonomy.stop());
|
|
548
|
+
process.on('SIGINT', () => autonomy.stop());
|
|
549
|
+
} catch (autoErr: any) {
|
|
550
|
+
console.warn(`[autonomy] Failed to start: ${autoErr.message}`);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// 16. Start guardrail enforcement (if enabled in autonomy settings)
|
|
554
|
+
const autoSettings = (config as any).autonomy || {};
|
|
555
|
+
if (autoSettings.guardrailEnforcementEnabled !== false) {
|
|
556
|
+
try {
|
|
557
|
+
const { GuardrailEnforcer } = await import('./engine/agent-autonomy.js');
|
|
558
|
+
const enforcer = new GuardrailEnforcer(engineDb);
|
|
559
|
+
(global as any).__guardrailEnforcer = enforcer;
|
|
560
|
+
console.log('[guardrails] ✅ Runtime guardrail enforcer active');
|
|
561
|
+
} catch (gErr: any) {
|
|
562
|
+
console.warn(`[guardrails] Failed to start enforcer: ${gErr.message}`);
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
console.log('[guardrails] Disabled via autonomy settings');
|
|
566
|
+
}
|
|
501
567
|
}, 3000);
|
|
502
568
|
}
|
|
503
569
|
|
|
@@ -858,10 +924,55 @@ For meetings you organize or are invited to:
|
|
|
858
924
|
|
|
859
925
|
When you receive an email containing a meeting link (meet.google.com, zoom.us, teams.microsoft.com):
|
|
860
926
|
- Extract the link and attempt to join immediately if the meeting is now
|
|
861
|
-
- If the meeting is in the future, store it in memory and note the time
|
|
927
|
+
- If the meeting is in the future, store it in memory and note the time
|
|
928
|
+
|
|
929
|
+
== SMART ANSWER WORKFLOW (MANDATORY) ==
|
|
930
|
+
When you receive a question or request you're not 100% confident about, follow this escalation chain:
|
|
931
|
+
|
|
932
|
+
STEP 1: Search your own memory
|
|
933
|
+
- memory(action: "search", query: "relevant keywords")
|
|
934
|
+
- Check for similar past questions, corrections, and learned patterns
|
|
935
|
+
|
|
936
|
+
STEP 2: Search organization Drive (shared knowledge)
|
|
937
|
+
- google_drive_list with query parameter to search shared docs (e.g. "fullText contains 'search terms'")
|
|
938
|
+
- Read relevant documents with google_drive_get to find the answer
|
|
939
|
+
- Check Google Sheets for data tables, Google Docs for procedures
|
|
940
|
+
|
|
941
|
+
STEP 3: If still unsure — ESCALATE to manager
|
|
942
|
+
${managerEmail ? `- Send an email to ${managerEmail} with:` : '- Email your manager with:'}
|
|
943
|
+
Subject: "Need Guidance: [Brief topic]"
|
|
944
|
+
Body must include:
|
|
945
|
+
a) The original question/request (who asked, what they need)
|
|
946
|
+
b) What you found in your search (memory + Drive results)
|
|
947
|
+
c) Your proposed answer (what you THINK the answer should be)
|
|
948
|
+
d) What specifically you're unsure about
|
|
949
|
+
e) Ask for approval or correction before responding
|
|
950
|
+
|
|
951
|
+
NEVER guess or fabricate an answer when unsure. It's better to escalate than to be wrong.
|
|
952
|
+
After receiving manager feedback, store the correct answer in memory as a "correction" or "org_knowledge" entry.`;
|
|
862
953
|
|
|
863
954
|
|
|
864
955
|
|
|
956
|
+
// Guardrail check: scan inbound email for security rules
|
|
957
|
+
const enforcer = (global as any).__guardrailEnforcer;
|
|
958
|
+
if (enforcer) {
|
|
959
|
+
try {
|
|
960
|
+
const orgRows3 = await engineDb.query<any>(`SELECT org_id FROM managed_agents WHERE id = $1`, [agentId]);
|
|
961
|
+
const gOrgId = orgRows3?.[0]?.org_id || '';
|
|
962
|
+
const check = await enforcer.evaluate({
|
|
963
|
+
agentId, orgId: gOrgId, type: 'email_send' as const,
|
|
964
|
+
content: emailText, metadata: { from: senderEmail, subject: fullMsg.subject },
|
|
965
|
+
});
|
|
966
|
+
if (!check.allowed) {
|
|
967
|
+
console.warn(`[email-poll] ⚠️ Guardrail blocked email from ${senderEmail}: ${check.reason} (action: ${check.action})`);
|
|
968
|
+
continue; // Skip this email
|
|
969
|
+
}
|
|
970
|
+
} catch (gErr: any) {
|
|
971
|
+
console.warn(`[email-poll] Guardrail check error: ${gErr.message}`);
|
|
972
|
+
// Continue anyway — don't block on guardrail failures
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
865
976
|
const session = await runtime.spawnSession({
|
|
866
977
|
agentId,
|
|
867
978
|
message: emailText,
|