@agenticmail/enterprise 0.5.319 → 0.5.321
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/CHANGELOG.md +68 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/README.md +118 -38
- package/SECURITY.md +42 -0
- package/dist/agent-heartbeat-3FWNHZFX.js +510 -0
- package/dist/agent-heartbeat-4RWHZR7H.js +510 -0
- package/dist/agent-heartbeat-6ZGB5ILY.js +510 -0
- package/dist/agent-heartbeat-BIVHLKFM.js +510 -0
- package/dist/agent-heartbeat-HRKVFK2T.js +510 -0
- package/dist/agent-heartbeat-JC5GWVXD.js +510 -0
- package/dist/agent-heartbeat-K6A4HMHB.js +510 -0
- package/dist/agent-heartbeat-LCDXWFVB.js +510 -0
- package/dist/agent-heartbeat-P7HZCZAQ.js +510 -0
- package/dist/agent-heartbeat-PUIRSNIO.js +510 -0
- package/dist/agent-heartbeat-SN5ILQ6Y.js +510 -0
- package/dist/agent-heartbeat-TW5YTDYC.js +510 -0
- package/dist/agent-heartbeat-Z2QQXROL.js +510 -0
- package/dist/agent-notify-OEQBCZLN.js +43 -0
- package/dist/{agent-tools-263HM5QU.js → agent-tools-3W7XLUYA.js} +1 -1
- package/dist/agent-tools-4QK7LLNP.js +9 -0
- package/dist/agent-tools-54VZGT6L.js +9 -0
- package/dist/{agent-tools-AT4D276V.js → agent-tools-AYYDPO27.js} +7 -7
- package/dist/{agent-tools-MSTAPX2I.js → agent-tools-F2X47FKF.js} +7 -7
- package/dist/{agent-tools-FA26SY5O.js → agent-tools-O6W3QAZL.js} +11 -6
- package/dist/agent-tools-OAWVZBMW.js +9 -0
- package/dist/agent-tools-QCCU74PN.js +13949 -0
- package/dist/chunk-2LHUARN6.js +4929 -0
- package/dist/chunk-2WVCNCYC.js +5087 -0
- package/dist/{chunk-6PWDS7KY.js → chunk-3FM6YQUK.js} +20 -20
- package/dist/chunk-3UAFHUEC.js +212 -0
- package/dist/{chunk-WJO57PMO.js → chunk-46GOWZT4.js} +20 -20
- package/dist/{chunk-BNRE7TSX.js → chunk-5KYJAUZV.js} +3 -3
- package/dist/chunk-6C5PKREN.js +467 -0
- package/dist/{chunk-447MTPZF.js → chunk-6ZMLNEHB.js} +3 -3
- package/dist/chunk-BPZQT5N5.js +25652 -0
- package/dist/chunk-BQM7MBPS.js +1380 -0
- package/dist/{chunk-ZRFKGPIU.js → chunk-C52OQNNY.js} +20 -20
- package/dist/chunk-C7HGQF4Y.js +25652 -0
- package/dist/chunk-CAHNZGGK.js +25656 -0
- package/dist/{chunk-FL3CH3ET.js → chunk-CK7R6UHE.js} +51 -27
- package/dist/chunk-D36RPWB7.js +25652 -0
- package/dist/{chunk-36NM2B4C.js → chunk-DJK2UPFH.js} +63 -93
- package/dist/chunk-DM7FTF7W.js +4929 -0
- package/dist/chunk-DMD24UFZ.js +5101 -0
- package/dist/{chunk-36XNMIHA.js → chunk-DXZGPUAF.js} +20 -20
- package/dist/chunk-F46WB5IL.js +5087 -0
- package/dist/chunk-F5QG5SQH.js +5087 -0
- package/dist/{chunk-JGEVQZDR.js → chunk-FLQ5FLHW.js} +13 -16
- package/dist/chunk-H7GP733U.js +5087 -0
- package/dist/{chunk-OZSQLOV6.js → chunk-HHBXWB5U.js} +415 -19
- package/dist/{chunk-D24JY75H.js → chunk-IMXS4N6W.js} +3 -3
- package/dist/{chunk-6PVBV6ZP.js → chunk-JNMDD7JY.js} +3 -3
- package/dist/chunk-JTV5LA47.js +1519 -0
- package/dist/chunk-KV6G7NZX.js +1519 -0
- package/dist/chunk-MU5MEBIK.js +1519 -0
- package/dist/chunk-NLT5MC7X.js +465 -0
- package/dist/{chunk-GTFZZUXX.js → chunk-NVLYIM4J.js} +51 -27
- package/dist/{chunk-6G5SXLXC.js → chunk-NZY2BIZH.js} +63 -93
- package/dist/chunk-O42L6G67.js +1519 -0
- package/dist/chunk-OCNERGGM.js +4891 -0
- package/dist/chunk-OJSNHONE.js +1519 -0
- package/dist/{chunk-2TAZJWJN.js → chunk-OWL3QVH7.js} +18 -0
- package/dist/{chunk-P3HVY2HS.js → chunk-OWTLNV4Q.js} +382 -7
- package/dist/chunk-PCNYEP6T.js +4891 -0
- package/dist/{chunk-YL3Z5KPR.js → chunk-PI4AQ4Z6.js} +438 -15
- package/dist/chunk-PN3EGTCA.js +194 -0
- package/dist/chunk-Q37UKNRC.js +1519 -0
- package/dist/chunk-QXTC6J7H.js +5087 -0
- package/dist/{chunk-SPBQVNDI.js → chunk-RKERL5LZ.js} +25 -21
- package/dist/chunk-RVBK2IOX.js +25652 -0
- package/dist/chunk-SAKODCZ5.js +4891 -0
- package/dist/{chunk-XV4TU65E.js → chunk-SALGFC5L.js} +51 -27
- package/dist/chunk-STGWZ2MS.js +1519 -0
- package/dist/chunk-UY3ZVQDP.js +25652 -0
- package/dist/chunk-V6OSD62M.js +5087 -0
- package/dist/chunk-VP6YAHX4.js +1519 -0
- package/dist/chunk-WDYJOEAI.js +5087 -0
- package/dist/chunk-WEAFQNOS.js +195 -0
- package/dist/chunk-XKUSAZGP.js +5087 -0
- package/dist/chunk-Z6K5FKAB.js +548 -0
- package/dist/chunk-ZGE3XAXY.js +1519 -0
- package/dist/chunk-ZGYVXYQQ.js +3296 -0
- package/dist/cli-agent-7TB2BWS6.js +2370 -0
- package/dist/cli-agent-AKXFFST2.js +2370 -0
- package/dist/cli-agent-DZTKLITB.js +2357 -0
- package/dist/cli-agent-FOF7PFEP.js +2357 -0
- package/dist/cli-agent-H74M2ZYN.js +2357 -0
- package/dist/cli-agent-HORWVPHB.js +2370 -0
- package/dist/cli-agent-HSZT6SKF.js +2423 -0
- package/dist/cli-agent-JLUQ4ZU6.js +2424 -0
- package/dist/cli-agent-MVCDH4HV.js +2370 -0
- package/dist/cli-agent-NZXOEPJ2.js +2357 -0
- package/dist/cli-agent-PADN3QRC.js +2357 -0
- package/dist/cli-agent-QAYEX3BE.js +2441 -0
- package/dist/cli-agent-QT64DT5J.js +2370 -0
- package/dist/cli-agent-TFL2M6UK.js +2424 -0
- package/dist/cli-agent-UIKXATTD.js +2357 -0
- package/dist/cli-agent-UJN6FYTO.js +2370 -0
- package/dist/cli-agent-VIQAYVY4.js +2357 -0
- package/dist/cli-agent-WNWFVOFM.js +2370 -0
- package/dist/cli-agent-XBQX67VJ.js +2423 -0
- package/dist/cli-agent-ZLSC6FF4.js +2357 -0
- package/dist/cli-serve-2IL5DTEY.js +153 -0
- package/dist/cli-serve-47N5UKKW.js +153 -0
- package/dist/cli-serve-4XGZFUV2.js +140 -0
- package/dist/cli-serve-6OT3UEAN.js +140 -0
- package/dist/cli-serve-7L6EY5UH.js +153 -0
- package/dist/cli-serve-BDGOOOKQ.js +260 -0
- package/dist/cli-serve-BFNIW2LF.js +153 -0
- package/dist/cli-serve-C7MN6U5Q.js +153 -0
- package/dist/cli-serve-CR3OY3IM.js +153 -0
- package/dist/cli-serve-DAJFRWQ7.js +153 -0
- package/dist/cli-serve-FW6FHFW4.js +153 -0
- package/dist/cli-serve-GEEOQS77.js +153 -0
- package/dist/cli-serve-H562I3ZK.js +153 -0
- package/dist/cli-serve-HDQZF4C4.js +153 -0
- package/dist/cli-serve-LICAOMEB.js +140 -0
- package/dist/cli-serve-LLGYLWFS.js +153 -0
- package/dist/cli-serve-N3OISDNB.js +153 -0
- package/dist/cli-serve-TIZ27EVR.js +153 -0
- package/dist/cli-serve-TUNI2RCN.js +153 -0
- package/dist/cli-serve-WNOZMAWD.js +153 -0
- package/dist/cli-validate-Z726VJCN.js +150 -0
- package/dist/cli.js +4 -4
- package/dist/connection-manager-KAWEUWUR.js +9 -0
- package/dist/dashboard/app.js +9 -3
- package/dist/dashboard/components/knowledge-link.js +15 -0
- package/dist/dashboard/components/settings-help.js +4 -2
- package/dist/dashboard/docs/agent-deployment.html +33 -1
- package/dist/dashboard/docs/settings-network.html +321 -0
- package/dist/dashboard/docs/settings-security.html +347 -0
- package/dist/dashboard/docs/settings-tool-security.html +176 -0
- package/dist/dashboard/docs/settings.html +36 -16
- package/dist/dashboard/pages/agent-detail/deployment.js +39 -6
- package/dist/dashboard/pages/agent-detail/tools.js +10 -0
- package/dist/dashboard/pages/database-access.js +4 -3
- package/dist/dashboard/pages/settings.js +174 -37
- package/dist/dashboard/pages/task-pipeline.js +400 -843
- package/dist/db-adapter-2T56ORSD.js +7 -0
- package/dist/db-adapter-IRHOUMVC.js +7 -0
- package/dist/index.js +41 -41
- package/dist/microsoft-VREAZ7M2.js +3955 -0
- package/dist/routes-3MMLQTB6.js +90 -0
- package/dist/routes-4ZUIJ4HE.js +90 -0
- package/dist/routes-5MXHKKH4.js +90 -0
- package/dist/routes-64NJFK3B.js +90 -0
- package/dist/routes-6AKQ2LBV.js +90 -0
- package/dist/routes-CRRBUDO4.js +90 -0
- package/dist/routes-DIAF3MC3.js +90 -0
- package/dist/routes-KMUNU6CY.js +90 -0
- package/dist/routes-LRRLXIZR.js +90 -0
- package/dist/routes-N647AJYG.js +90 -0
- package/dist/routes-SSSELAAR.js +90 -0
- package/dist/routes-STERVGKJ.js +90 -0
- package/dist/routes-ZEZZACZP.js +90 -0
- package/dist/runtime-5EQN4GFM.js +45 -0
- package/dist/runtime-5LP7PUD4.js +45 -0
- package/dist/runtime-6BULDBR3.js +45 -0
- package/dist/runtime-6YEENDN3.js +45 -0
- package/dist/runtime-7LQFRG3B.js +45 -0
- package/dist/runtime-AMXJU2MB.js +45 -0
- package/dist/runtime-D6WSE7FG.js +45 -0
- package/dist/runtime-EYVN7NFJ.js +45 -0
- package/dist/runtime-F6RPWQVW.js +45 -0
- package/dist/runtime-FYMJURFC.js +45 -0
- package/dist/runtime-JRNBL4O4.js +45 -0
- package/dist/runtime-OM2NIBMI.js +45 -0
- package/dist/runtime-QWPVD7CY.js +45 -0
- package/dist/runtime-YLIIPTE4.js +45 -0
- package/dist/runtime-YU6P22CG.js +45 -0
- package/dist/screen-unlock-4RPZBHOI.js +118 -0
- package/dist/server-AMCSXINC.js +28 -0
- package/dist/server-CU6LVQS4.js +28 -0
- package/dist/server-DFYGH2CV.js +28 -0
- package/dist/server-EELWOC3X.js +28 -0
- package/dist/server-EN5E2OWQ.js +28 -0
- package/dist/server-GW2HYJYI.js +28 -0
- package/dist/server-J25NCRWJ.js +28 -0
- package/dist/server-JDGNOTFV.js +28 -0
- package/dist/server-NE5HD5DJ.js +28 -0
- package/dist/server-NQOT7W77.js +28 -0
- package/dist/server-PWE5PQTR.js +28 -0
- package/dist/server-Q2Q32H2B.js +28 -0
- package/dist/server-Q77ME7TL.js +28 -0
- package/dist/server-WLLH4WST.js +28 -0
- package/dist/server-WTUJ2O3F.js +28 -0
- package/dist/server-X4CJTHHF.js +28 -0
- package/dist/server-XK3ILCJC.js +28 -0
- package/dist/server-ZRD3NDJE.js +28 -0
- package/dist/setup-44VBAO4J.js +20 -0
- package/dist/setup-4ONNQBWB.js +20 -0
- package/dist/setup-4OSBXSCL.js +20 -0
- package/dist/setup-4QFGRBLZ.js +20 -0
- package/dist/setup-6766SGAR.js +20 -0
- package/dist/setup-AYY24DKM.js +20 -0
- package/dist/setup-B34N4HPU.js +20 -0
- package/dist/setup-E2YLC2EY.js +20 -0
- package/dist/setup-ER6NXTY5.js +20 -0
- package/dist/setup-H2AGCBW5.js +20 -0
- package/dist/setup-ICOZRKCX.js +20 -0
- package/dist/setup-JFTJH7UF.js +20 -0
- package/dist/setup-PRFNI6YW.js +20 -0
- package/dist/setup-RAHBMYHE.js +20 -0
- package/dist/setup-TXPR5UQX.js +20 -0
- package/dist/setup-XCJMELVU.js +20 -0
- package/dist/setup-XIYEIFVK.js +20 -0
- package/dist/setup-Z4PZSHBI.js +20 -0
- package/dist/skills-FR7I5V7H.js +16 -0
- package/dist/skills-HCVBA6PK.js +16 -0
- package/dist/system-prompts-TM7OA32C.js +913 -0
- package/dist/task-queue-O7IVZYUO.js +9 -0
- package/dist/transport-encryption-2T7PIXKG.js +25 -0
- package/logs/cloudflared-error.log +61 -0
- package/logs/cloudflared-out.log +0 -0
- package/logs/enterprise-error.log +0 -0
- package/logs/enterprise-out.log +3 -0
- package/logs/fola-error.log +0 -0
- package/logs/fola-out.log +0 -0
- package/logs/john-error.log +8 -0
- package/logs/john-out.log +0 -0
- package/package.json +31 -3
- package/src/agent-tools/tool-resolver.ts +50 -61
- package/src/agent-tools/tools/enterprise-database.ts +5 -5
- package/src/agent-tools/tools/local/dependency-manager.ts +2 -2
- package/src/agent-tools/tools/microsoft/graph-api.ts +137 -26
- package/src/agent-tools/tools/microsoft/outlook-mail.ts +392 -100
- package/src/agent-tools/tools/microsoft/teams.ts +267 -48
- package/src/auth/routes.ts +4 -4
- package/src/cli-agent.ts +108 -8
- package/src/cli-serve.ts +140 -0
- package/src/dashboard/app.js +9 -3
- package/src/dashboard/components/knowledge-link.js +15 -0
- package/src/dashboard/components/settings-help.js +4 -2
- package/src/dashboard/docs/agent-deployment.html +33 -1
- package/src/dashboard/docs/settings-network.html +321 -0
- package/src/dashboard/docs/settings-security.html +347 -0
- package/src/dashboard/docs/settings-tool-security.html +176 -0
- package/src/dashboard/docs/settings.html +36 -16
- package/src/dashboard/pages/agent-detail/deployment.js +39 -6
- package/src/dashboard/pages/agent-detail/tools.js +10 -0
- package/src/dashboard/pages/database-access.js +4 -3
- package/src/dashboard/pages/settings.js +174 -37
- package/src/dashboard/pages/task-pipeline.js +400 -843
- package/src/database-access/agent-tools.ts +78 -63
- package/src/database-access/connection-manager.ts +13 -2
- package/src/database-access/routes.ts +13 -1
- package/src/db/adapter.ts +1 -0
- package/src/engine/agent-memory.ts +2 -1
- package/src/engine/agent-notify.ts +50 -0
- package/src/engine/agent-routes.ts +257 -4
- package/src/engine/db-adapter.ts +16 -0
- package/src/engine/lifecycle.ts +4 -0
- package/src/engine/routes.ts +4 -3
- package/src/engine/screen-unlock.ts +136 -0
- package/src/engine/skills/database-access.ts +78 -0
- package/src/engine/skills/index.ts +3 -2
- package/src/engine/skills.ts +2 -0
- package/src/engine/task-queue-routes.ts +18 -0
- package/src/engine/task-queue.ts +15 -2
- package/src/middleware/transport-encryption.ts +1 -4
- package/src/runtime/agent-loop.ts +4 -0
- package/src/runtime/index.ts +15 -6
- package/src/server.ts +14 -1
- package/src/system-prompts/google/index.ts +1 -2
- package/src/system-prompts/index.ts +1 -1
- package/src/system-prompts/microsoft/contacts.ts +34 -0
- package/src/system-prompts/microsoft/excel.ts +52 -0
- package/src/system-prompts/microsoft/index.ts +31 -0
- package/src/system-prompts/microsoft/onedrive.ts +41 -0
- package/src/system-prompts/microsoft/onenote.ts +36 -0
- package/src/system-prompts/microsoft/outlook-calendar.ts +37 -0
- package/src/system-prompts/microsoft/outlook-mail.ts +46 -0
- package/src/system-prompts/microsoft/planner.ts +37 -0
- package/src/system-prompts/microsoft/powerbi.ts +38 -0
- package/src/system-prompts/microsoft/powerpoint.ts +35 -0
- package/src/system-prompts/microsoft/sharepoint.ts +44 -0
- package/src/system-prompts/microsoft/teams.ts +49 -0
- package/src/system-prompts/microsoft/todo.ts +37 -0
- package/src/types/hono-env.ts +4 -0
- package/.github/CODEOWNERS +0 -23
- package/.github/workflows/publish-community-skills.yml +0 -121
- package/.github/workflows/validate-community-skills.yml +0 -172
- package/agriculture_southwest_nigeria_research.txt +0 -10
- package/boa_credit_cards_research.txt +0 -10
- package/customer_support_research_feb2026.txt +0 -10
- package/dist/agent-tools-LRA7PPXG.js +0 -13922
- package/dist/agent-tools-VAU5DOQB.js +0 -13910
- package/dist/agent-tools-VWV7OWXU.js +0 -13922
- package/dist/chunk-2Z7MWTCX.js +0 -4977
- package/dist/chunk-3T4XU3VV.js +0 -5010
- package/dist/chunk-445QM4NX.js +0 -5061
- package/dist/chunk-5TW3Y7DJ.js +0 -1519
- package/dist/chunk-6I7VY3LT.js +0 -5060
- package/dist/chunk-6W5EK3UP.js +0 -4977
- package/dist/chunk-AQMSHJQT.js +0 -5069
- package/dist/chunk-ASSQW7HX.js +0 -5051
- package/dist/chunk-CIN27FGC.js +0 -5037
- package/dist/chunk-CMXY3NUB.js +0 -4977
- package/dist/chunk-DRLMRUDP.js +0 -5052
- package/dist/chunk-EHI7Z446.js +0 -1519
- package/dist/chunk-FEAILFAQ.js +0 -1519
- package/dist/chunk-GA3PYBZL.js +0 -1519
- package/dist/chunk-GWX63G5J.js +0 -1519
- package/dist/chunk-HHMZ4UY6.js +0 -1519
- package/dist/chunk-HVQMNF7E.js +0 -4921
- package/dist/chunk-HXM7F3YN.js +0 -1519
- package/dist/chunk-K6NGOUXG.js +0 -5060
- package/dist/chunk-KPG5WINJ.js +0 -4977
- package/dist/chunk-LBCUBYDL.js +0 -1519
- package/dist/chunk-LIRQSWLR.js +0 -5014
- package/dist/chunk-LRCKO5KE.js +0 -1519
- package/dist/chunk-M7XL3DJD.js +0 -5069
- package/dist/chunk-MHJULEIQ.js +0 -1519
- package/dist/chunk-MJGGW6MC.js +0 -106
- package/dist/chunk-MMYBDHDB.js +0 -4921
- package/dist/chunk-MQT5FXKD.js +0 -1519
- package/dist/chunk-OIMPEQF5.js +0 -4977
- package/dist/chunk-OOU7JUYE.js +0 -542
- package/dist/chunk-OW4GLBHP.js +0 -1519
- package/dist/chunk-Q4K4MMLU.js +0 -4977
- package/dist/chunk-RUK4CRPF.js +0 -1519
- package/dist/chunk-T7H65XQY.js +0 -1519
- package/dist/chunk-TQVFWG57.js +0 -5064
- package/dist/chunk-UEPK3IMC.js +0 -1519
- package/dist/chunk-VUWTXJH6.js +0 -1519
- package/dist/chunk-WCPGGSAD.js +0 -1519
- package/dist/chunk-WO63NZOJ.js +0 -1519
- package/dist/chunk-YPJDRVUM.js +0 -5064
- package/dist/chunk-ZROMH5DL.js +0 -4921
- package/src/dashboard/docs/_template.txt +0 -92
package/src/cli-agent.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* AGENTICMAIL_AGENT_ID — Agent UUID from the enterprise DB
|
|
11
11
|
*
|
|
12
12
|
* Optional env vars:
|
|
13
|
-
* PORT — Health check HTTP port (default:
|
|
13
|
+
* PORT — Health check HTTP port (default: 4100)
|
|
14
14
|
* AGENTICMAIL_MODEL — Override model (e.g. "anthropic/claude-sonnet-4-20250514")
|
|
15
15
|
* AGENTICMAIL_THINKING — Thinking level (e.g. "low", "medium", "high")
|
|
16
16
|
* ANTHROPIC_API_KEY — Anthropic API key
|
|
@@ -26,6 +26,30 @@ import { beforeSpawn } from './engine/task-queue-before-spawn.js';
|
|
|
26
26
|
import { afterSpawn, markInProgress } from './engine/task-queue-after-spawn.js';
|
|
27
27
|
import { TaskPoller } from './engine/task-poller.js';
|
|
28
28
|
|
|
29
|
+
// ─── Production Log Level Filter ─────────────────────────
|
|
30
|
+
// Set LOG_LEVEL=warn to suppress info/debug console.log noise.
|
|
31
|
+
// Levels: debug < info < warn < error (default: info)
|
|
32
|
+
const _LOG_LEVEL = (process.env.LOG_LEVEL || 'info').toLowerCase();
|
|
33
|
+
const _LOG_LEVELS: Record<string, number> = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
34
|
+
const _LOG_THRESHOLD = _LOG_LEVELS[_LOG_LEVEL] ?? 1;
|
|
35
|
+
const _origLog = console.log.bind(console);
|
|
36
|
+
const _origWarn = console.warn.bind(console);
|
|
37
|
+
if (_LOG_THRESHOLD > 1) {
|
|
38
|
+
// Suppress console.log (info level) — keep warn and error
|
|
39
|
+
console.log = function(...args: any[]) {
|
|
40
|
+
// Always allow critical prefixes through even at warn level
|
|
41
|
+
const first = typeof args[0] === 'string' ? args[0] : '';
|
|
42
|
+
if (first.includes('[error]') || first.includes('[fatal]') || first.includes('ERROR') || first.includes('FATAL')) {
|
|
43
|
+
_origLog(...args);
|
|
44
|
+
}
|
|
45
|
+
// Suppress everything else
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (_LOG_THRESHOLD > 2) {
|
|
49
|
+
// Suppress console.warn too — only errors
|
|
50
|
+
console.warn = function() {};
|
|
51
|
+
}
|
|
52
|
+
|
|
29
53
|
// ════════════════════════════════════════════════════════════
|
|
30
54
|
// SYSTEM DEPENDENCY AUTO-INSTALLER
|
|
31
55
|
// ════════════════════════════════════════════════════════════
|
|
@@ -375,7 +399,7 @@ export async function runAgent(_args: string[]) {
|
|
|
375
399
|
const DATABASE_URL = process.env.DATABASE_URL;
|
|
376
400
|
const JWT_SECRET = process.env.JWT_SECRET;
|
|
377
401
|
const AGENT_ID = process.env.AGENTICMAIL_AGENT_ID;
|
|
378
|
-
const PORT = parseInt(process.env.PORT || '
|
|
402
|
+
const PORT = parseInt(process.env.PORT || '4100', 10);
|
|
379
403
|
|
|
380
404
|
if (!DATABASE_URL) { console.error('ERROR: DATABASE_URL is required'); process.exit(1); }
|
|
381
405
|
if (!JWT_SECRET) { console.error('ERROR: JWT_SECRET is required'); process.exit(1); }
|
|
@@ -650,6 +674,9 @@ export async function runAgent(_args: string[]) {
|
|
|
650
674
|
// ─── Real-Time Status Reporting ─────────────────────────
|
|
651
675
|
// Report status to the enterprise server (separate process)
|
|
652
676
|
const ENTERPRISE_URL = process.env.ENTERPRISE_URL || 'http://localhost:3100';
|
|
677
|
+
|
|
678
|
+
// Notify enterprise SSE subscribers when tasks change (standalone agent → enterprise webhook)
|
|
679
|
+
taskQueue.webhookUrl = `${ENTERPRISE_URL}/api/engine/task-pipeline/webhook`;
|
|
653
680
|
const _reportStatus = (update: any) => {
|
|
654
681
|
fetch(`${ENTERPRISE_URL}/api/engine/agent-status/${AGENT_ID}`, {
|
|
655
682
|
method: 'POST',
|
|
@@ -739,7 +766,7 @@ export async function runAgent(_args: string[]) {
|
|
|
739
766
|
const session = await runtime.spawnSession({
|
|
740
767
|
agentId,
|
|
741
768
|
message: `[System — Task Recovery] You have a stuck task to complete:\n\nTask: ${task.title}\nID: ${task.id}\nCategory: ${task.category}\nPriority: ${task.priority}\nDescription: ${task.description}\n\nPlease complete this task now.`,
|
|
742
|
-
model: task.model || undefined,
|
|
769
|
+
model: (task.model || undefined) as any,
|
|
743
770
|
});
|
|
744
771
|
if (session?.id) {
|
|
745
772
|
sessionRouter.register({
|
|
@@ -892,6 +919,79 @@ export async function runAgent(_args: string[]) {
|
|
|
892
919
|
|
|
893
920
|
app.get('/ready', (c) => c.json({ ready: true, agentId: AGENT_ID }));
|
|
894
921
|
|
|
922
|
+
// General config reload endpoint — called by enterprise server when ANY config changes
|
|
923
|
+
// Supports: db-access, permissions, config, guardrails, budget, all
|
|
924
|
+
app.post('/reload-db-access', async (c) => c.redirect('/reload?scope=db-access', 307));
|
|
925
|
+
app.post('/reload', async (c) => {
|
|
926
|
+
const scope = c.req.query('scope') || 'all';
|
|
927
|
+
const reloaded: string[] = [];
|
|
928
|
+
|
|
929
|
+
try {
|
|
930
|
+
// 1. Database connections
|
|
931
|
+
if (scope === 'all' || scope === 'db-access') {
|
|
932
|
+
const dbManager = (runtime as any).config?.databaseManager;
|
|
933
|
+
if (dbManager && engineDb) {
|
|
934
|
+
await dbManager.setDb(engineDb);
|
|
935
|
+
reloaded.push('db-access');
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// 2. Permission profiles
|
|
940
|
+
if (scope === 'all' || scope === 'permissions') {
|
|
941
|
+
try {
|
|
942
|
+
const { permissionEngine } = await import('./engine/routes.js');
|
|
943
|
+
await permissionEngine.setDb(engineDb);
|
|
944
|
+
reloaded.push('permissions');
|
|
945
|
+
} catch { /* non-fatal */ }
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// 3. Agent config (re-read from managed_agents table)
|
|
949
|
+
if (scope === 'all' || scope === 'config') {
|
|
950
|
+
try {
|
|
951
|
+
const row = await engineDb.get<any>('SELECT * FROM managed_agents WHERE id = $1', [agentId]);
|
|
952
|
+
if (row) {
|
|
953
|
+
const config = typeof row.config === 'string' ? JSON.parse(row.config) : row.config;
|
|
954
|
+
const managed = routes.lifecycle.getAgent(agentId);
|
|
955
|
+
if (managed) {
|
|
956
|
+
Object.assign(managed.config, config);
|
|
957
|
+
managed.updatedAt = row.updated_at;
|
|
958
|
+
if (row.display_name) { managed.name = row.display_name; managed.displayName = row.display_name; }
|
|
959
|
+
reloaded.push('config');
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
} catch { /* non-fatal */ }
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// 4. Budget config
|
|
966
|
+
if (scope === 'all' || scope === 'budget') {
|
|
967
|
+
try {
|
|
968
|
+
const row = await engineDb.get<any>('SELECT budget_config FROM managed_agents WHERE id = $1', [agentId]);
|
|
969
|
+
if (row?.budget_config) {
|
|
970
|
+
const managed = routes.lifecycle.getAgent(agentId);
|
|
971
|
+
if (managed) {
|
|
972
|
+
managed.budgetConfig = typeof row.budget_config === 'string' ? JSON.parse(row.budget_config) : row.budget_config;
|
|
973
|
+
reloaded.push('budget');
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
} catch { /* non-fatal */ }
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// 5. Guardrails
|
|
980
|
+
if (scope === 'all' || scope === 'guardrails') {
|
|
981
|
+
try {
|
|
982
|
+
const { guardrails } = await import('./engine/routes.js');
|
|
983
|
+
await (guardrails as any).loadFromDb?.();
|
|
984
|
+
reloaded.push('guardrails');
|
|
985
|
+
} catch { /* non-fatal */ }
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
console.log(`[agent] Config reloaded: ${reloaded.join(', ') || 'nothing to reload'} (scope: ${scope})`);
|
|
989
|
+
return c.json({ ok: true, reloaded, scope });
|
|
990
|
+
} catch (e: any) {
|
|
991
|
+
return c.json({ ok: false, error: e.message, reloaded }, 500);
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
|
|
895
995
|
// Mount runtime API if available
|
|
896
996
|
if (runtimeApp) {
|
|
897
997
|
app.route('/api/runtime', runtimeApp);
|
|
@@ -1105,7 +1205,7 @@ export async function runAgent(_args: string[]) {
|
|
|
1105
1205
|
|
|
1106
1206
|
if (isMessagingSource) {
|
|
1107
1207
|
// Build messaging-specific system prompt
|
|
1108
|
-
const { buildScheduleInfo } = await import('./system-prompts/
|
|
1208
|
+
const { buildScheduleInfo } = await import('./system-prompts/index.js');
|
|
1109
1209
|
const sendToolName = ctx.source === 'whatsapp' ? 'whatsapp_send'
|
|
1110
1210
|
: 'telegram_send';
|
|
1111
1211
|
const platformName = ctx.source === 'whatsapp' ? 'WhatsApp'
|
|
@@ -1140,7 +1240,7 @@ export async function runAgent(_args: string[]) {
|
|
|
1140
1240
|
`- "${sendToolName}" is ALREADY LOADED — do NOT call request_tools, do NOT search for tools, do NOT use grep. Just call ${sendToolName} directly.`,
|
|
1141
1241
|
`- NEVER use google_chat_send_message — this is ${platformName}.`,
|
|
1142
1242
|
`- Keep messages concise and conversational — this is a chat, not an email.`,
|
|
1143
|
-
`- No
|
|
1243
|
+
`- ABSOLUTELY NO MARKDOWN. No **, no ##, no *, no bullet lists, no code blocks. Plain text ONLY. Write like a human texting — short paragraphs separated by line breaks. This is non-negotiable.`,
|
|
1144
1244
|
`- For simple greetings/questions, reply in ONE tool call. Do not overthink.`,
|
|
1145
1245
|
'',
|
|
1146
1246
|
`DEPENDENCY & TOOL MANAGEMENT:`,
|
|
@@ -1172,7 +1272,7 @@ export async function runAgent(_args: string[]) {
|
|
|
1172
1272
|
if (dp.sudoPassword) {
|
|
1173
1273
|
lines.push(`- You HAVE ${elevatedLabel} access. The system password is pre-configured — install_dependency handles it automatically. You do NOT need to ask the user for it.`);
|
|
1174
1274
|
} else {
|
|
1175
|
-
lines.push(`- You HAVE ${elevatedLabel} access. ${
|
|
1275
|
+
lines.push(`- You HAVE ${elevatedLabel} access. ${process.platform === 'win32' ? 'Elevated commands should work if the agent process is running as admin.' : 'No password set — works if NOPASSWD is configured or credentials are cached.'}`);
|
|
1176
1276
|
}
|
|
1177
1277
|
} else {
|
|
1178
1278
|
lines.push('- You do NOT have elevated/admin access. Commands requiring admin privileges (sudo on Mac/Linux, admin on Windows) will fail.');
|
|
@@ -1199,7 +1299,7 @@ export async function runAgent(_args: string[]) {
|
|
|
1199
1299
|
].filter(Boolean).join('\n');
|
|
1200
1300
|
|
|
1201
1301
|
} else {
|
|
1202
|
-
const { buildGoogleChatPrompt, buildScheduleInfo } = await import('./system-prompts/
|
|
1302
|
+
const { buildGoogleChatPrompt, buildScheduleInfo } = await import('./system-prompts/index.js');
|
|
1203
1303
|
systemPrompt = buildGoogleChatPrompt({
|
|
1204
1304
|
agent: { name: agentName, role: identity?.role || 'professional', personality: identity?.personality },
|
|
1205
1305
|
schedule: buildScheduleInfo(agentSchedule, agentTimezone),
|
|
@@ -2143,7 +2243,7 @@ async function startCalendarPolling(
|
|
|
2143
2243
|
const identity = config.identity || {};
|
|
2144
2244
|
|
|
2145
2245
|
try {
|
|
2146
|
-
const { buildMeetJoinPrompt, buildScheduleInfo } = await import('./system-prompts/
|
|
2246
|
+
const { buildMeetJoinPrompt, buildScheduleInfo } = await import('./system-prompts/index.js');
|
|
2147
2247
|
|
|
2148
2248
|
const managerEmail = (config as any)?.manager?.email || '';
|
|
2149
2249
|
const agentEmail = config?.identity?.email || (config as any)?.email || '';
|
package/src/cli-serve.ts
CHANGED
|
@@ -138,6 +138,29 @@ export async function runServe(_args: string[]) {
|
|
|
138
138
|
await server.start();
|
|
139
139
|
console.log(`AgenticMail Enterprise server running on :${PORT}`);
|
|
140
140
|
|
|
141
|
+
// Start prevent-sleep if configured
|
|
142
|
+
try {
|
|
143
|
+
const { startPreventSleep } = await import('./engine/screen-unlock.js');
|
|
144
|
+
const adminDb = (server as any).getAdminDb?.() || (server as any).adminDb;
|
|
145
|
+
if (adminDb) {
|
|
146
|
+
const settings = await adminDb.getSettings?.().catch(() => null);
|
|
147
|
+
const screenAccess = settings?.securityConfig?.screenAccess;
|
|
148
|
+
if (screenAccess?.enabled && screenAccess?.preventSleep) {
|
|
149
|
+
startPreventSleep();
|
|
150
|
+
console.log('[startup] Prevent-sleep enabled — system will stay awake while agents are active');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} catch {}
|
|
154
|
+
|
|
155
|
+
// ─── Auto-configure system persistence ──────────────────
|
|
156
|
+
// Ensures the server auto-starts on reboot, crash-recovers with backoff,
|
|
157
|
+
// and log rotation is in place. Runs once — idempotent.
|
|
158
|
+
try {
|
|
159
|
+
await setupSystemPersistence();
|
|
160
|
+
} catch (e: any) {
|
|
161
|
+
console.warn('[startup] System persistence setup skipped: ' + e.message);
|
|
162
|
+
}
|
|
163
|
+
|
|
141
164
|
// Auto-start cloudflared if tunnel token is present
|
|
142
165
|
const tunnelToken = process.env.CLOUDFLARED_TOKEN;
|
|
143
166
|
if (tunnelToken) {
|
|
@@ -172,3 +195,120 @@ export async function runServe(_args: string[]) {
|
|
|
172
195
|
}
|
|
173
196
|
}
|
|
174
197
|
}
|
|
198
|
+
|
|
199
|
+
// ─── System Persistence ─────────────────────────────────
|
|
200
|
+
// Automatically sets up PM2 startup, log rotation, and process saving.
|
|
201
|
+
// Idempotent — safe to run on every boot.
|
|
202
|
+
|
|
203
|
+
async function setupSystemPersistence(): Promise<void> {
|
|
204
|
+
const { execSync, spawnSync } = await import('child_process');
|
|
205
|
+
const { existsSync: exists, writeFileSync, mkdirSync } = await import('fs');
|
|
206
|
+
const { join: pathJoin } = await import('path');
|
|
207
|
+
const platform = process.platform;
|
|
208
|
+
|
|
209
|
+
// Only works if running under PM2
|
|
210
|
+
if (!process.env.PM2_HOME && !process.env.pm_id) {
|
|
211
|
+
// Not running under PM2 — skip (user is running directly via node/npx)
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const markerDir = pathJoin(homedir(), '.agenticmail');
|
|
216
|
+
const markerFile = pathJoin(markerDir, '.persistence-configured');
|
|
217
|
+
|
|
218
|
+
// Check if already configured (avoid running pm2 commands every boot)
|
|
219
|
+
if (exists(markerFile)) {
|
|
220
|
+
// Already configured — just save current process list silently
|
|
221
|
+
try { execSync('pm2 save --silent', { timeout: 10000, stdio: 'ignore' }); } catch {}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log('[startup] Configuring system persistence (one-time setup)...');
|
|
226
|
+
|
|
227
|
+
// 1. Set up PM2 startup — auto-start on boot
|
|
228
|
+
// pm2 startup outputs the command needed (may require sudo on Linux)
|
|
229
|
+
try {
|
|
230
|
+
if (platform === 'darwin') {
|
|
231
|
+
// macOS: launchd — pm2 startup creates plist and loads it
|
|
232
|
+
const result = spawnSync('pm2', ['startup', 'launchd', '--silent'], {
|
|
233
|
+
timeout: 15000, stdio: 'pipe', encoding: 'utf-8',
|
|
234
|
+
});
|
|
235
|
+
// If it outputs a sudo command, try running it
|
|
236
|
+
const output = (result.stdout || '') + (result.stderr || '');
|
|
237
|
+
const sudoMatch = output.match(/sudo\s+env\s+.*pm2\s+startup.*/);
|
|
238
|
+
if (sudoMatch) {
|
|
239
|
+
// Can't run sudo without password — log the command for the user
|
|
240
|
+
console.log('[startup] PM2 startup requires sudo. Run this once:');
|
|
241
|
+
console.log(' ' + sudoMatch[0]);
|
|
242
|
+
} else {
|
|
243
|
+
console.log('[startup] PM2 startup configured (launchd)');
|
|
244
|
+
}
|
|
245
|
+
// Try loading the plist if it exists
|
|
246
|
+
const plistPath = pathJoin(homedir(), 'Library', 'LaunchAgents', `pm2.${process.env.USER || 'user'}.plist`);
|
|
247
|
+
if (exists(plistPath)) {
|
|
248
|
+
try { execSync(`launchctl load -w "${plistPath}"`, { timeout: 5000, stdio: 'ignore' }); } catch {}
|
|
249
|
+
}
|
|
250
|
+
} else if (platform === 'linux') {
|
|
251
|
+
// Linux: systemd (Debian/Ubuntu/RHEL/Pi)
|
|
252
|
+
const result = spawnSync('pm2', ['startup', 'systemd', '--silent'], {
|
|
253
|
+
timeout: 15000, stdio: 'pipe', encoding: 'utf-8',
|
|
254
|
+
});
|
|
255
|
+
const output = (result.stdout || '') + (result.stderr || '');
|
|
256
|
+
const sudoMatch = output.match(/sudo\s+env\s+.*pm2\s+startup.*/);
|
|
257
|
+
if (sudoMatch) {
|
|
258
|
+
// Try running it — if we have sudo access
|
|
259
|
+
try {
|
|
260
|
+
execSync(sudoMatch[0], { timeout: 15000, stdio: 'ignore' });
|
|
261
|
+
console.log('[startup] PM2 startup configured (systemd)');
|
|
262
|
+
} catch {
|
|
263
|
+
console.log('[startup] PM2 startup requires root. Run this once:');
|
|
264
|
+
console.log(' ' + sudoMatch[0]);
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
console.log('[startup] PM2 startup configured (systemd)');
|
|
268
|
+
}
|
|
269
|
+
} else if (platform === 'win32') {
|
|
270
|
+
// Windows: use pm2-windows-startup
|
|
271
|
+
try {
|
|
272
|
+
execSync('npm list -g pm2-windows-startup', { timeout: 10000, stdio: 'ignore' });
|
|
273
|
+
} catch {
|
|
274
|
+
console.log('[startup] Installing pm2-windows-startup...');
|
|
275
|
+
try {
|
|
276
|
+
execSync('npm install -g pm2-windows-startup', { timeout: 60000, stdio: 'ignore' });
|
|
277
|
+
execSync('pm2-startup install', { timeout: 15000, stdio: 'ignore' });
|
|
278
|
+
console.log('[startup] PM2 startup configured (Windows Service)');
|
|
279
|
+
} catch (e: any) {
|
|
280
|
+
console.warn('[startup] Could not install pm2-windows-startup: ' + e.message);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
} catch (e: any) {
|
|
285
|
+
console.warn('[startup] PM2 startup setup: ' + e.message);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 2. Install log rotation (if not already present)
|
|
289
|
+
try {
|
|
290
|
+
const moduleList = execSync('pm2 ls --silent 2>/dev/null || true', { timeout: 10000, encoding: 'utf-8' });
|
|
291
|
+
if (!moduleList.includes('pm2-logrotate')) {
|
|
292
|
+
console.log('[startup] Installing pm2-logrotate...');
|
|
293
|
+
execSync('pm2 install pm2-logrotate --silent', { timeout: 60000, stdio: 'ignore' });
|
|
294
|
+
// Configure: 10MB max, keep 5 rotated files, compress
|
|
295
|
+
execSync('pm2 set pm2-logrotate:max_size 10M --silent', { timeout: 5000, stdio: 'ignore' });
|
|
296
|
+
execSync('pm2 set pm2-logrotate:retain 5 --silent', { timeout: 5000, stdio: 'ignore' });
|
|
297
|
+
execSync('pm2 set pm2-logrotate:compress true --silent', { timeout: 5000, stdio: 'ignore' });
|
|
298
|
+
console.log('[startup] Log rotation configured (10MB, 5 files)');
|
|
299
|
+
}
|
|
300
|
+
} catch {}
|
|
301
|
+
|
|
302
|
+
// 3. Save current process list for resurrection on reboot
|
|
303
|
+
try {
|
|
304
|
+
execSync('pm2 save --silent', { timeout: 10000, stdio: 'ignore' });
|
|
305
|
+
console.log('[startup] Process list saved');
|
|
306
|
+
} catch {}
|
|
307
|
+
|
|
308
|
+
// 4. Write marker file so we don't repeat this setup
|
|
309
|
+
try {
|
|
310
|
+
if (!exists(markerDir)) mkdirSync(markerDir, { recursive: true });
|
|
311
|
+
writeFileSync(markerFile, new Date().toISOString() + '\n' + `platform=${platform}\n`, { mode: 0o600 });
|
|
312
|
+
console.log('[startup] System persistence configured successfully');
|
|
313
|
+
} catch {}
|
|
314
|
+
}
|
package/src/dashboard/app.js
CHANGED
|
@@ -156,7 +156,8 @@ function App() {
|
|
|
156
156
|
const [selectedOrgId, setSelectedOrgId] = useState('');
|
|
157
157
|
const [selectedOrg, setSelectedOrg] = useState(null);
|
|
158
158
|
const [orgVersion, setOrgVersion] = useState(0);
|
|
159
|
-
const
|
|
159
|
+
const [companyName, setCompanyName] = useState((window.__EM_BRANDING__ && window.__EM_BRANDING__.companyName) || '');
|
|
160
|
+
const onOrgChange = useCallback((id, org) => { setSelectedOrgId(id); setSelectedOrg(org); setOrgVersion(v => v + 1); if (org && org.name) setCompanyName(org.name); }, []);
|
|
160
161
|
|
|
161
162
|
// Check if already authenticated via cookie on mount, and check setup state
|
|
162
163
|
useEffect(() => {
|
|
@@ -189,6 +190,11 @@ function App() {
|
|
|
189
190
|
if (window.__transportEncryption) await window.__transportEncryption.waitForReady();
|
|
190
191
|
}
|
|
191
192
|
} catch {}
|
|
193
|
+
// Fetch company name for sidebar
|
|
194
|
+
try {
|
|
195
|
+
var s = await apiCall('/settings');
|
|
196
|
+
if (s && s.name) setCompanyName(s.name);
|
|
197
|
+
} catch {}
|
|
192
198
|
setAuthed(true);
|
|
193
199
|
setAuthChecked(true);
|
|
194
200
|
}).catch(() => setAuthChecked(true));
|
|
@@ -457,7 +463,7 @@ function App() {
|
|
|
457
463
|
const PageComponent = canAccessPage ? (pages[page] || DashboardPage) : null;
|
|
458
464
|
const sidebarClass = 'sidebar' + (sidebarPinned ? ' expanded' : sidebarHovered ? ' hover-expanded' : '') + (mobileMenuOpen ? ' mobile-open' : '');
|
|
459
465
|
|
|
460
|
-
return h(AppContext.Provider, { value: { toast, toasts, user, theme, setPage, permissions, impersonating, startImpersonation, stopImpersonation, selectedOrgId, selectedOrg, onOrgChange } },
|
|
466
|
+
return h(AppContext.Provider, { value: { toast, toasts, user, theme, setPage, permissions, impersonating, startImpersonation, stopImpersonation, selectedOrgId, selectedOrg, onOrgChange, companyName, setCompanyName } },
|
|
461
467
|
h('div', { className: 'app-layout' },
|
|
462
468
|
// Mobile hamburger
|
|
463
469
|
h('button', { className: 'mobile-hamburger', onClick: () => setMobileMenuOpen(true) },
|
|
@@ -473,7 +479,7 @@ function App() {
|
|
|
473
479
|
h('div', { className: sidebarClass, onMouseEnter: onSidebarEnter, onMouseLeave: onSidebarLeave },
|
|
474
480
|
h('div', { className: 'sidebar-brand' },
|
|
475
481
|
h('img', { src: (window.__EM_BRANDING__ && window.__EM_BRANDING__.logo) || '/dashboard/assets/logo.png', alt: 'AgenticMail', style: { width: 28, height: 28, objectFit: 'contain' } }),
|
|
476
|
-
h('div', { className: 'sidebar-brand-text' }, h('h2', null,
|
|
482
|
+
h('div', { className: 'sidebar-brand-text' }, h('h2', null, companyName || 'AgenticMail'), h('span', null, 'Enterprise')),
|
|
477
483
|
h('button', { className: 'sidebar-toggle' + (sidebarPinned ? ' pinned' : ''), onClick: toggleSidebarPin, title: sidebarPinned ? 'Unpin sidebar' : 'Pin sidebar' }, sidebarPinned ? I.chevronLeft() : I.panelLeft())
|
|
478
484
|
),
|
|
479
485
|
h('div', { className: 'sidebar-nav' },
|
|
@@ -62,3 +62,18 @@ export var AGENT_TAB_DOCS = {
|
|
|
62
62
|
deployment: 'agent-deployment',
|
|
63
63
|
'memory-transfer': 'memory-transfer',
|
|
64
64
|
};
|
|
65
|
+
|
|
66
|
+
/** Map of settings tab IDs to doc filenames */
|
|
67
|
+
export var SETTINGS_TAB_DOCS = {
|
|
68
|
+
general: 'settings',
|
|
69
|
+
models: 'settings',
|
|
70
|
+
'api-keys': 'settings',
|
|
71
|
+
authentication: 'settings',
|
|
72
|
+
platform: 'settings',
|
|
73
|
+
email: 'settings',
|
|
74
|
+
deployments: 'settings',
|
|
75
|
+
'security-system': 'settings-security',
|
|
76
|
+
'tool-security': 'settings-tool-security',
|
|
77
|
+
network: 'settings-network',
|
|
78
|
+
integrations: 'settings',
|
|
79
|
+
};
|
|
@@ -138,7 +138,8 @@ export var SETTINGS_HELP = {
|
|
|
138
138
|
h('li', null, h('strong', null, 'Rate Limiting'), ' \u2014 Limits how many times each tool can be called per minute per agent. Prevents any single agent from overwhelming the system. Adjust limits per tool type in the table.'),
|
|
139
139
|
h('li', null, h('strong', null, 'Circuit Breaker'), ' \u2014 Automatically pauses a tool that keeps failing (after 5 consecutive errors). Waits 30 seconds before retrying. Prevents error cascading when an external service is down.'),
|
|
140
140
|
h('li', null, h('strong', null, 'Telemetry'), ' \u2014 Collects performance metrics: call duration, success rates, and output sizes. Useful for identifying slow tools or agents using resources inefficiently.')
|
|
141
|
-
)
|
|
141
|
+
),
|
|
142
|
+
h('p', { style: { marginTop: 12 } }, h('a', { href: '/docs/settings-tool-security', style: { fontSize: 12 } }, 'View full Tool Security documentation \u2192'))
|
|
142
143
|
);
|
|
143
144
|
}
|
|
144
145
|
},
|
|
@@ -163,7 +164,8 @@ export var SETTINGS_HELP = {
|
|
|
163
164
|
h('li', null, h('strong', null, 'Rate Limiting'), ' \u2014 Limits API requests per IP per minute. Protects against abuse and denial-of-service. "Skip Paths" excludes health-check endpoints.'),
|
|
164
165
|
h('li', null, h('strong', null, 'HTTPS Enforcement'), ' \u2014 Forces all connections to use encrypted HTTPS. Highly recommended for production.'),
|
|
165
166
|
h('li', null, h('strong', null, 'Security Headers'), ' \u2014 Browser security policies: HSTS forces HTTPS, X-Frame-Options prevents clickjacking, Content-Type-Options prevents MIME sniffing. The defaults are recommended for most deployments.')
|
|
166
|
-
)
|
|
167
|
+
),
|
|
168
|
+
h('p', { style: { marginTop: 12 } }, h('a', { href: '/docs/settings-network', style: { fontSize: 12 } }, 'View full Network & Firewall documentation \u2192'))
|
|
167
169
|
);
|
|
168
170
|
}
|
|
169
171
|
},
|
|
@@ -162,12 +162,39 @@
|
|
|
162
162
|
<h3 id="local">Local (In-Process)</h3>
|
|
163
163
|
<p>For development and single-server deployments:</p>
|
|
164
164
|
<ul>
|
|
165
|
-
<li><strong>Port</strong> — HTTP port the agent listens on.</li>
|
|
165
|
+
<li><strong>Port</strong> — HTTP port the agent listens on. Validated in real-time (see below).</li>
|
|
166
166
|
<li><strong>Host</strong> — Hostname or IP (default: localhost).</li>
|
|
167
167
|
<li><strong>Process Manager</strong> — PM2 (with install detection), systemd, Manual, or In-Process (embedded).</li>
|
|
168
168
|
<li><strong>Process Name</strong> — PM2/systemd service name for lifecycle management.</li>
|
|
169
169
|
<li><strong>Working Directory</strong> — Auto-detected or manually specified.</li>
|
|
170
170
|
</ul>
|
|
171
|
+
|
|
172
|
+
<h4>Port Validation</h4>
|
|
173
|
+
<p>When you enter a port number, the system automatically checks whether it's available before allowing you to save:</p>
|
|
174
|
+
<div class="card">
|
|
175
|
+
<table>
|
|
176
|
+
<thead><tr><th>Indicator</th><th>Meaning</th></tr></thead>
|
|
177
|
+
<tbody>
|
|
178
|
+
<tr><td><strong style="color:var(--success)">Green border + checkmark</strong></td><td>Port is available — you can save and deploy.</td></tr>
|
|
179
|
+
<tr><td><strong style="color:var(--danger)">Red border + error</strong></td><td>Port is already in use — save is blocked. The error shows which process is using it (e.g., "Port 3100 is in use by node (PID 12345)").</td></tr>
|
|
180
|
+
</tbody>
|
|
181
|
+
</table>
|
|
182
|
+
</div>
|
|
183
|
+
<ul>
|
|
184
|
+
<li><strong>Debounced</strong> — Validation triggers 500ms after you stop typing, preventing excessive API calls.</li>
|
|
185
|
+
<li><strong>Bind test</strong> — Uses <code>net.createServer()</code> to attempt binding the port. This is the most reliable availability check.</li>
|
|
186
|
+
<li><strong>Process identification</strong> — If the port is in use, the system runs <code>lsof</code> (macOS/Linux) or <code>netstat</code> (Windows) to identify the process name and PID.</li>
|
|
187
|
+
<li><strong>Save blocked</strong> — You cannot save deployment configuration while a port conflict exists.</li>
|
|
188
|
+
</ul>
|
|
189
|
+
|
|
190
|
+
<div class="card">
|
|
191
|
+
<h3>API Reference</h3>
|
|
192
|
+
<pre><code>POST /system/check-port
|
|
193
|
+
Body: { "port": 4100 }
|
|
194
|
+
Response (available): { "available": true, "port": 3102 }
|
|
195
|
+
Response (in use): { "available": false, "port": 3102, "process": "node (PID 12345)" }</code></pre>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
171
198
|
<div class="tip">
|
|
172
199
|
<strong>Tip:</strong> PM2 availability is auto-detected. If PM2 isn't installed, the dashboard offers a one-click "Install PM2" button.
|
|
173
200
|
</div>
|
|
@@ -268,6 +295,11 @@ Response: { "agentId": "...", "assigned": ["kb-1", "kb-2"], "count": 2 }</code><
|
|
|
268
295
|
<p>The agent process may have crashed. Check logs on the deployment platform. Common causes: missing environment variables, incorrect model configuration, or insufficient memory.</p>
|
|
269
296
|
</div>
|
|
270
297
|
|
|
298
|
+
<div class="card">
|
|
299
|
+
<h3>Port is in use — can't save</h3>
|
|
300
|
+
<p>The port validation detected another process using the port. Either change the port number or stop the conflicting process. The error message shows the process name and PID — you can stop it with <code>kill <PID></code> or choose a different port. Common conflicts: another agent already running on that port, or a development server.</p>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
271
303
|
<div class="card">
|
|
272
304
|
<h3>Delete confirmation name doesn't match</h3>
|
|
273
305
|
<p>The typed name must match exactly (case-insensitive) with the agent's display name. Check the agent name shown in the header.</p>
|