@agenticmail/enterprise 0.5.83 → 0.5.85
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/browser-tool-KJMHSNK3.js +3997 -0
- package/dist/chunk-4DXQQPEC.js +15441 -0
- package/dist/chunk-AQH4DFYV.js +142 -0
- package/dist/chunk-CETB63LZ.js +15813 -0
- package/dist/chunk-LOA5LNXR.js +898 -0
- package/dist/chunk-PHZS6OIO.js +2191 -0
- package/dist/chunk-QISZRTVR.js +2154 -0
- package/dist/chunk-SEGTMIPI.js +2191 -0
- package/dist/chunk-TGOSFAYW.js +194 -0
- package/dist/chunk-ZTOVB5OQ.js +898 -0
- package/dist/cli.js +1 -1
- package/dist/environment-L6BN6KGK.js +11 -0
- package/dist/index.js +5 -3
- package/dist/pw-ai-IRORDXFW.js +2212 -0
- package/dist/routes-4NHH2DJW.js +6849 -0
- package/dist/routes-VIK7WDVW.js +6859 -0
- package/dist/runtime-DAVEFGHR.js +47 -0
- package/dist/runtime-NEO2ZB6O.js +49 -0
- package/dist/server-F6GBGLJY.js +12 -0
- package/dist/server-ZIB4HUUC.js +12 -0
- package/dist/setup-NKJBKCEG.js +20 -0
- package/dist/setup-YD3LJ6DT.js +20 -0
- package/package.json +1 -1
- package/scripts/vm-setup.sh +309 -0
- package/src/agent-tools/index.ts +70 -3
- package/src/agent-tools/tools/google/index.ts +4 -1
- package/src/agent-tools/tools/google/meetings.ts +468 -0
- package/src/agent-tools/tools/meeting-lifecycle.ts +437 -0
- package/src/engine/agent-routes.ts +19 -0
- package/src/runtime/agent-loop.ts +1 -1
- package/src/runtime/environment.ts +290 -0
- package/src/runtime/index.ts +3 -3
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// src/runtime/environment.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
var _cachedCapabilities = null;
|
|
5
|
+
function commandExists(cmd) {
|
|
6
|
+
try {
|
|
7
|
+
execSync(`which ${cmd} 2>/dev/null`, { encoding: "utf-8", timeout: 3e3 });
|
|
8
|
+
return true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function envSet(key) {
|
|
14
|
+
return !!process.env[key];
|
|
15
|
+
}
|
|
16
|
+
function detectDeploymentType() {
|
|
17
|
+
if (envSet("FLY_APP_NAME") || envSet("FLY_MACHINE_ID")) return "container";
|
|
18
|
+
if (envSet("RAILWAY_ENVIRONMENT") || envSet("RAILWAY_SERVICE_ID")) return "container";
|
|
19
|
+
if (envSet("RENDER_SERVICE_ID") || envSet("RENDER")) return "container";
|
|
20
|
+
if (existsSync("/.dockerenv") || existsSync("/run/.containerenv")) return "container";
|
|
21
|
+
if (envSet("KUBERNETES_SERVICE_HOST")) return "container";
|
|
22
|
+
if (envSet("ECS_CONTAINER_METADATA_URI")) return "container";
|
|
23
|
+
if (envSet("SSH_CONNECTION") || envSet("SSH_CLIENT")) return "vm";
|
|
24
|
+
if (process.platform === "linux" && existsSync("/run/systemd/system") && !existsSync("/.dockerenv")) return "vm";
|
|
25
|
+
if (process.platform === "darwin" || process.platform === "win32") return "local";
|
|
26
|
+
if (process.platform === "linux" && (envSet("DISPLAY") || envSet("WAYLAND_DISPLAY"))) return "vm";
|
|
27
|
+
return "unknown";
|
|
28
|
+
}
|
|
29
|
+
function findBrowser() {
|
|
30
|
+
const envPath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH || process.env.CHROME_PATH;
|
|
31
|
+
if (envPath && existsSync(envPath)) return envPath;
|
|
32
|
+
const candidates = [
|
|
33
|
+
// Linux
|
|
34
|
+
"/usr/bin/chromium",
|
|
35
|
+
"/usr/bin/chromium-browser",
|
|
36
|
+
"/usr/bin/google-chrome",
|
|
37
|
+
"/usr/bin/google-chrome-stable",
|
|
38
|
+
// macOS
|
|
39
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
40
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
41
|
+
// Snap
|
|
42
|
+
"/snap/bin/chromium"
|
|
43
|
+
];
|
|
44
|
+
for (const p of candidates) {
|
|
45
|
+
if (existsSync(p)) return p;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const path = execSync("which chromium || which chromium-browser || which google-chrome 2>/dev/null", {
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
timeout: 3e3
|
|
51
|
+
}).trim();
|
|
52
|
+
if (path) return path;
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
function hasDisplayServer() {
|
|
58
|
+
if (process.platform === "darwin" || process.platform === "win32") return true;
|
|
59
|
+
if (envSet("DISPLAY") || envSet("WAYLAND_DISPLAY")) return true;
|
|
60
|
+
if (commandExists("Xvfb") || commandExists("xvfb-run")) return true;
|
|
61
|
+
try {
|
|
62
|
+
execSync("pgrep -x Xvfb", { encoding: "utf-8", timeout: 2e3 });
|
|
63
|
+
return true;
|
|
64
|
+
} catch {
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function hasAudioSystem() {
|
|
69
|
+
if (process.platform === "darwin") return true;
|
|
70
|
+
if (commandExists("pulseaudio") || commandExists("pactl")) {
|
|
71
|
+
try {
|
|
72
|
+
execSync("pactl info 2>/dev/null", { encoding: "utf-8", timeout: 3e3 });
|
|
73
|
+
return true;
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (commandExists("pw-cli")) {
|
|
78
|
+
try {
|
|
79
|
+
execSync("pw-cli info 2>/dev/null", { encoding: "utf-8", timeout: 3e3 });
|
|
80
|
+
return true;
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function hasVCam() {
|
|
87
|
+
if (process.platform === "darwin") return false;
|
|
88
|
+
try {
|
|
89
|
+
execSync("ls /dev/video* 2>/dev/null", { encoding: "utf-8", timeout: 2e3 });
|
|
90
|
+
return true;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function detectCapabilities() {
|
|
96
|
+
if (_cachedCapabilities) return _cachedCapabilities;
|
|
97
|
+
const deployment = detectDeploymentType();
|
|
98
|
+
const browserPath = findBrowser();
|
|
99
|
+
const hasBrowser = !!browserPath;
|
|
100
|
+
const hasDisplay = hasDisplayServer();
|
|
101
|
+
const hasAudio = hasAudioSystem();
|
|
102
|
+
const hasVirtualCamera = hasVCam();
|
|
103
|
+
const hasFfmpeg = commandExists("ffmpeg");
|
|
104
|
+
const hasPersistentDisk = deployment !== "container" || envSet("FLY_VOLUME_NAME") || envSet("RAILWAY_VOLUME_MOUNT_PATH");
|
|
105
|
+
let hasGpu = false;
|
|
106
|
+
try {
|
|
107
|
+
if (commandExists("nvidia-smi")) {
|
|
108
|
+
execSync("nvidia-smi", { timeout: 3e3 });
|
|
109
|
+
hasGpu = true;
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
const caps = {
|
|
114
|
+
deployment,
|
|
115
|
+
hasBrowser,
|
|
116
|
+
browserPath,
|
|
117
|
+
hasDisplay,
|
|
118
|
+
hasAudio,
|
|
119
|
+
hasVirtualCamera,
|
|
120
|
+
canRunHeadedBrowser: hasBrowser && hasDisplay,
|
|
121
|
+
canJoinMeetings: hasBrowser && hasDisplay && hasAudio,
|
|
122
|
+
canRecordMeetings: hasBrowser && hasDisplay && hasAudio && hasFfmpeg,
|
|
123
|
+
hasFfmpeg,
|
|
124
|
+
hasPersistentDisk: !!hasPersistentDisk,
|
|
125
|
+
hasGpu,
|
|
126
|
+
platform: {
|
|
127
|
+
os: process.platform,
|
|
128
|
+
arch: process.arch,
|
|
129
|
+
isDocker: existsSync("/.dockerenv") || existsSync("/run/.containerenv"),
|
|
130
|
+
isFlyio: envSet("FLY_APP_NAME"),
|
|
131
|
+
isRailway: envSet("RAILWAY_ENVIRONMENT"),
|
|
132
|
+
isRender: envSet("RENDER"),
|
|
133
|
+
isAWS: envSet("AWS_REGION") || envSet("ECS_CONTAINER_METADATA_URI"),
|
|
134
|
+
isGCP: envSet("GOOGLE_CLOUD_PROJECT") || envSet("GCP_PROJECT"),
|
|
135
|
+
isHetzner: false
|
|
136
|
+
// No standard env var
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
_cachedCapabilities = caps;
|
|
140
|
+
return caps;
|
|
141
|
+
}
|
|
142
|
+
function resetCapabilitiesCache() {
|
|
143
|
+
_cachedCapabilities = null;
|
|
144
|
+
}
|
|
145
|
+
function getCapabilitySummary(caps) {
|
|
146
|
+
const c = caps || detectCapabilities();
|
|
147
|
+
const available = [];
|
|
148
|
+
const unavailable = [];
|
|
149
|
+
const recommendations = [];
|
|
150
|
+
if (c.hasBrowser) available.push("Browser (headless)");
|
|
151
|
+
else unavailable.push("Browser \u2014 no Chromium/Chrome found");
|
|
152
|
+
if (c.canRunHeadedBrowser) available.push("Browser (headed/visible)");
|
|
153
|
+
else if (c.hasBrowser) unavailable.push("Headed browser \u2014 no display server (install Xvfb)");
|
|
154
|
+
if (c.canJoinMeetings) available.push("Video meetings (Google Meet, Zoom, Teams)");
|
|
155
|
+
else unavailable.push("Video meetings \u2014 requires display + browser + audio");
|
|
156
|
+
if (c.canRecordMeetings) available.push("Meeting recording");
|
|
157
|
+
else if (c.canJoinMeetings) unavailable.push("Meeting recording \u2014 install ffmpeg");
|
|
158
|
+
if (c.hasAudio) available.push("Audio subsystem");
|
|
159
|
+
else unavailable.push("Audio \u2014 no PulseAudio/PipeWire");
|
|
160
|
+
if (c.hasVirtualCamera) available.push("Virtual camera");
|
|
161
|
+
else unavailable.push("Virtual camera \u2014 no v4l2loopback");
|
|
162
|
+
if (c.hasFfmpeg) available.push("FFmpeg (video/audio processing)");
|
|
163
|
+
else unavailable.push("FFmpeg \u2014 install for recording/transcoding");
|
|
164
|
+
if (c.hasPersistentDisk) available.push("Persistent storage");
|
|
165
|
+
else unavailable.push("Persistent storage \u2014 ephemeral container filesystem");
|
|
166
|
+
if (c.deployment === "container" && !c.canJoinMeetings) {
|
|
167
|
+
recommendations.push(
|
|
168
|
+
"This is a container deployment. For video meetings, deploy on a VM instead.",
|
|
169
|
+
"Recommended: Hetzner CPX31 ($15/mo) or GCP e2-standard-2 ($50/mo) with the VM setup script.",
|
|
170
|
+
"Container deployments work great for API-only tasks: email, calendar, docs, drive, sheets."
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
if (c.deployment === "vm" && !c.hasDisplay) {
|
|
174
|
+
recommendations.push("Install Xvfb for virtual display: apt install xvfb");
|
|
175
|
+
}
|
|
176
|
+
if (c.deployment === "vm" && !c.hasAudio) {
|
|
177
|
+
recommendations.push("Install PulseAudio for audio: apt install pulseaudio");
|
|
178
|
+
}
|
|
179
|
+
if (c.deployment === "vm" && !c.hasBrowser) {
|
|
180
|
+
recommendations.push("Install Chromium: apt install chromium-browser");
|
|
181
|
+
}
|
|
182
|
+
let deployLabel = c.deployment;
|
|
183
|
+
if (c.platform.isFlyio) deployLabel = "Fly.io (container)";
|
|
184
|
+
else if (c.platform.isRailway) deployLabel = "Railway (container)";
|
|
185
|
+
else if (c.platform.isRender) deployLabel = "Render (container)";
|
|
186
|
+
else if (c.deployment === "local") deployLabel = `Local (${c.platform.os})`;
|
|
187
|
+
return { deployment: deployLabel, available, unavailable, recommendations };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export {
|
|
191
|
+
detectCapabilities,
|
|
192
|
+
resetCapabilitiesCache,
|
|
193
|
+
getCapabilitySummary
|
|
194
|
+
};
|