tesseract-agent 0.9.6 → 0.9.7
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-bundle/cli.js +126 -35
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -22752,13 +22752,13 @@ Add it to an EDL as an audio track (duckUnderSpeech:true under speech).`);
|
|
|
22752
22752
|
return text6(`Speech generated: ${res.file.path}
|
|
22753
22753
|
Overlay it in render_edl as an audio track (mute the original speaker's segments to replace their voice).`);
|
|
22754
22754
|
}),
|
|
22755
|
-
tool7("list_avatars", "List the HeyGen avatars available
|
|
22755
|
+
tool7("list_avatars", "List the HeyGen avatars available for virtual-presenter videos, with their avatar ids. Works on the free bundled tier when signed in, or on the user's own HeyGen key if they set one. Pair an avatar_id with a HeyGen voice for generate_avatar_video.", {}, async () => {
|
|
22756
22756
|
const res = await deps.listAvatars();
|
|
22757
22757
|
if (!res.ok)
|
|
22758
22758
|
return text6(`Could not list avatars: ${res.error ?? "unknown error"}`, true);
|
|
22759
22759
|
return jsonText(res.avatars ?? []);
|
|
22760
22760
|
}),
|
|
22761
|
-
tool7("generate_avatar_video", "Generate a talking-presenter (avatar) video from a script (HeyGen \u2014
|
|
22761
|
+
tool7("generate_avatar_video", "Generate a talking-presenter (avatar) video from a script (HeyGen). Runs on the free bundled tier when signed in, or on the user's own HeyGen key if they set one \u2014 they never need to be asked for a key up front. Draft the script yourself; pick an avatar via list_avatars and a HeyGen voice_id. Takes 1\u20135 minutes; the finished video is displayed in the chat. Use for news-desk reads, explainers, spokesperson clips. ONLY use avatars/likenesses you are authorized to use.", {
|
|
22762
22762
|
script: external_exports.string().describe("What the presenter says."),
|
|
22763
22763
|
avatar_id: external_exports.string().optional().describe("HeyGen avatar id (from list_avatars). Provide this OR talking_photo_id."),
|
|
22764
22764
|
talking_photo_id: external_exports.string().optional().describe("HeyGen talking-photo id (alternative to avatar_id)."),
|
|
@@ -24266,6 +24266,13 @@ ${JSON.stringify(r, null, 2)}`
|
|
|
24266
24266
|
// ── image (image-generation/edit providers) ──
|
|
24267
24267
|
{ id: "image.list_providers", domain: "image", title: "List image providers", description: "Image providers with configured/default/model status.", input: external_exports.object({}), mutation: "read", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "list" } },
|
|
24268
24268
|
{ id: "image.set_provider_key", domain: "image", title: "Set image provider key", description: "Set (blank clears) an image provider's API key.", input: external_exports.object({ provider_id: IMAGE_PROVIDER, api_key: external_exports.string().describe("API key (secret); blank clears.") }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "setKey" } },
|
|
24269
|
+
// Avatar videos are the one media provider whose key lives outside the image pool
|
|
24270
|
+
// (HeyGen, its own vendor) — but it is set in the SAME Settings panel, so it belongs
|
|
24271
|
+
// to the same domain rather than earning a domain of its own. `has_` returns a
|
|
24272
|
+
// boolean, never the key: writing a secret in is a capability, reading one out is
|
|
24273
|
+
// not (the same line `auth:token` sits on the wrong side of).
|
|
24274
|
+
{ id: "image.set_avatar_key", domain: "image", title: "Set avatar-video (HeyGen) key", description: "Set (blank clears) the HeyGen API key used for avatar/presenter videos. Without one, avatar videos fall back to the free Tesseract proxy tier for signed-in users.", input: external_exports.object({ api_key: external_exports.string().describe("HeyGen API key (secret); blank clears.") }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "heygen", verb: "setKey" } },
|
|
24275
|
+
{ id: "image.has_avatar_key", domain: "image", title: "Avatar-video key configured?", description: "Whether a personal HeyGen key is set. Never returns the key itself.", input: external_exports.object({}), mutation: "read", availability: "host", binding: { kind: "ipc", channel: "heygen", verb: "hasKey" } },
|
|
24269
24276
|
{ id: "image.remove_provider_key", domain: "image", title: "Remove image provider key", description: "Remove all credentials for an image provider.", input: external_exports.object({ provider_id: IMAGE_PROVIDER }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "removeKey" } },
|
|
24270
24277
|
{ id: "image.set_default_provider", domain: "image", title: "Set default image provider", description: "Set the default image provider.", input: external_exports.object({ provider_id: IMAGE_PROVIDER }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "setDefault" } },
|
|
24271
24278
|
{ id: "image.set_provider_model", domain: "image", title: "Set image provider model", description: "Set the model for an image provider.", input: external_exports.object({ provider_id: IMAGE_PROVIDER, model: external_exports.string() }), mutation: "write", availability: "host", binding: { kind: "ipc", channel: "imageEdit", verb: "setModel" } },
|
|
@@ -66328,16 +66335,17 @@ async function listVoicesElevenLabs(cfg2, opts) {
|
|
|
66328
66335
|
}
|
|
66329
66336
|
|
|
66330
66337
|
// ../../packages/video-core/dist/heygen.js
|
|
66331
|
-
var
|
|
66338
|
+
var HEYGEN_DIRECT_BASE_URL = "https://api.heygen.com";
|
|
66332
66339
|
var DEFAULT_DIM = { width: 1280, height: 720 };
|
|
66333
66340
|
var HG_REQUEST_TIMEOUT_MS = 6e4;
|
|
66334
66341
|
var HG_DOWNLOAD_TIMEOUT_MS = 18e4;
|
|
66335
|
-
async function hgFetch(path6,
|
|
66342
|
+
async function hgFetch(path6, cfg2, init, signal) {
|
|
66343
|
+
const base = (cfg2.baseUrl || HEYGEN_DIRECT_BASE_URL).replace(/\/+$/, "");
|
|
66336
66344
|
let res;
|
|
66337
66345
|
try {
|
|
66338
|
-
res = await fetch(`${
|
|
66346
|
+
res = await fetch(`${base}${path6}`, {
|
|
66339
66347
|
method: init.method,
|
|
66340
|
-
headers: { "X-Api-Key": apiKey, ...init.body != null ? { "Content-Type": "application/json" } : {} },
|
|
66348
|
+
headers: { "X-Api-Key": cfg2.apiKey, ...init.body != null ? { "Content-Type": "application/json" } : {} },
|
|
66341
66349
|
...init.body != null ? { body: JSON.stringify(init.body) } : {},
|
|
66342
66350
|
signal: signal ?? AbortSignal.timeout(HG_REQUEST_TIMEOUT_MS)
|
|
66343
66351
|
});
|
|
@@ -66354,7 +66362,7 @@ async function hgFetch(path6, apiKey, init, signal) {
|
|
|
66354
66362
|
return json2;
|
|
66355
66363
|
}
|
|
66356
66364
|
async function listAvatarsHeyGen(cfg2, signal) {
|
|
66357
|
-
const j = await hgFetch("/v2/avatars", cfg2
|
|
66365
|
+
const j = await hgFetch("/v2/avatars", cfg2, { method: "GET" }, signal);
|
|
66358
66366
|
return (j.data?.avatars ?? []).map((a) => ({ avatarId: a.avatar_id, name: a.avatar_name ?? a.avatar_id }));
|
|
66359
66367
|
}
|
|
66360
66368
|
async function submitAvatarVideoHeyGen(spec, cfg2, signal) {
|
|
@@ -66371,14 +66379,14 @@ async function submitAvatarVideoHeyGen(spec, cfg2, signal) {
|
|
|
66371
66379
|
],
|
|
66372
66380
|
dimension: { width: spec.width ?? DEFAULT_DIM.width, height: spec.height ?? DEFAULT_DIM.height }
|
|
66373
66381
|
};
|
|
66374
|
-
const j = await hgFetch("/v2/video/generate", cfg2
|
|
66382
|
+
const j = await hgFetch("/v2/video/generate", cfg2, { method: "POST", body }, signal);
|
|
66375
66383
|
const id = j.data?.video_id;
|
|
66376
66384
|
if (!id)
|
|
66377
66385
|
throw new Error("HeyGen returned no video_id.");
|
|
66378
66386
|
return id;
|
|
66379
66387
|
}
|
|
66380
66388
|
async function pollAvatarVideoHeyGen(videoId, cfg2, signal) {
|
|
66381
|
-
const j = await hgFetch(`/v1/video_status.get?video_id=${encodeURIComponent(videoId)}`, cfg2
|
|
66389
|
+
const j = await hgFetch(`/v1/video_status.get?video_id=${encodeURIComponent(videoId)}`, cfg2, { method: "GET" }, signal);
|
|
66382
66390
|
const d = j.data ?? {};
|
|
66383
66391
|
const error51 = typeof d.error === "string" ? d.error : d.error?.message;
|
|
66384
66392
|
return { status: d.status ?? "processing", videoUrl: d.video_url, error: error51 };
|
|
@@ -67662,13 +67670,13 @@ ${inputs.prompt}` : "");
|
|
|
67662
67670
|
|
|
67663
67671
|
// ../../packages/host-core/dist/video-transcribe.js
|
|
67664
67672
|
var DEFAULT_MODEL5 = "gemini-3.5-flash";
|
|
67665
|
-
var
|
|
67673
|
+
var BASE_URL2 = "https://generativelanguage.googleapis.com/v1beta";
|
|
67666
67674
|
var CHUNK_PROMPT = `Transcribe this audio VERBATIM with speaker diarization.
|
|
67667
67675
|
Return ONLY a JSON array; each element: {"start": <seconds from the START OF THIS AUDIO, number>, "end": <seconds, number>, "speaker": "<S1|S2|S3\u2026, stable within this audio>", "text": "<utterance>"}.
|
|
67668
67676
|
Rules: keep the original language(s); split on speaker changes and natural sentence boundaries (segments \u2264 15s); timecodes must be accurate to the second; no commentary, no markdown.`;
|
|
67669
67677
|
var REQUEST_TIMEOUT_MS3 = 18e4;
|
|
67670
67678
|
async function geminiJson(opts) {
|
|
67671
|
-
const res = await fetch(`${
|
|
67679
|
+
const res = await fetch(`${BASE_URL2}/models/${encodeURIComponent(opts.model)}:generateContent`, {
|
|
67672
67680
|
method: "POST",
|
|
67673
67681
|
headers: { "Content-Type": "application/json", "x-goog-api-key": opts.apiKey },
|
|
67674
67682
|
body: JSON.stringify({
|
|
@@ -67774,14 +67782,14 @@ ${compact2}`;
|
|
|
67774
67782
|
|
|
67775
67783
|
// ../../packages/host-core/dist/video-vision.js
|
|
67776
67784
|
import { readFileSync as readFileSync19 } from "node:fs";
|
|
67777
|
-
var
|
|
67785
|
+
var BASE_URL3 = "https://generativelanguage.googleapis.com/v1beta";
|
|
67778
67786
|
var MODEL = "gemini-3.5-flash";
|
|
67779
67787
|
var TIMEOUT_MS = 6e4;
|
|
67780
67788
|
async function reviewFrameGemini(framePath, intent, apiKey) {
|
|
67781
67789
|
try {
|
|
67782
67790
|
const b642 = readFileSync19(framePath).toString("base64");
|
|
67783
67791
|
const prompt = `This is a frame from an AI-generated video clip meant to show: "${intent}". Judge ONLY for obvious defects: melted/warped faces or hands, garbled text, broken anatomy, severe artifacts. Reply with STRICT JSON: {"acceptable": <true|false>, "note": "<\u226412 words, only if not acceptable>"}.`;
|
|
67784
|
-
const res = await fetch(`${
|
|
67792
|
+
const res = await fetch(`${BASE_URL3}/models/${MODEL}:generateContent`, {
|
|
67785
67793
|
method: "POST",
|
|
67786
67794
|
headers: { "Content-Type": "application/json", "x-goog-api-key": apiKey },
|
|
67787
67795
|
body: JSON.stringify({
|
|
@@ -67809,9 +67817,19 @@ function googleKey() {
|
|
|
67809
67817
|
function elevenLabsKey() {
|
|
67810
67818
|
return readDaemonAgentSettings().voiceKeys?.elevenlabs?.trim() || null;
|
|
67811
67819
|
}
|
|
67812
|
-
function
|
|
67813
|
-
|
|
67820
|
+
function resolveAvatarCreds(snap, keyFile, envKey2) {
|
|
67821
|
+
const fromSnapshot = (snap.heygen?.baseUrl ? void 0 : snap.heygen?.apiKey?.trim()) || snap.heygenApiKey?.trim();
|
|
67822
|
+
const personal = fromSnapshot || keyFile?.trim() || envKey2?.trim();
|
|
67823
|
+
if (personal)
|
|
67824
|
+
return { apiKey: personal };
|
|
67825
|
+
if (snap.heygen?.baseUrl && snap.heygen.apiKey)
|
|
67826
|
+
return { apiKey: snap.heygen.apiKey, baseUrl: snap.heygen.baseUrl };
|
|
67827
|
+
return null;
|
|
67828
|
+
}
|
|
67829
|
+
function heygenCreds() {
|
|
67830
|
+
return resolveAvatarCreds(readDaemonAgentSettings(), readDaemonKeyFile("heygen.key"), process.env.HEYGEN_API_KEY ?? null);
|
|
67814
67831
|
}
|
|
67832
|
+
var NO_AVATAR_CREDS = "Avatar videos need either a HeyGen API key (add it in Settings, or set HEYGEN_API_KEY) or a signed-in Tesseract account for the free tier.";
|
|
67815
67833
|
function readDaemonKeyFile(name) {
|
|
67816
67834
|
try {
|
|
67817
67835
|
const home = tesseractHome();
|
|
@@ -67984,21 +68002,21 @@ function createDaemonVideoEditRunner() {
|
|
|
67984
68002
|
}
|
|
67985
68003
|
},
|
|
67986
68004
|
async listAvatars() {
|
|
67987
|
-
const
|
|
67988
|
-
if (!
|
|
67989
|
-
return { ok: false, error:
|
|
68005
|
+
const creds3 = heygenCreds();
|
|
68006
|
+
if (!creds3)
|
|
68007
|
+
return { ok: false, error: NO_AVATAR_CREDS };
|
|
67990
68008
|
try {
|
|
67991
|
-
return { ok: true, avatars: await listAvatarsHeyGen(
|
|
68009
|
+
return { ok: true, avatars: await listAvatarsHeyGen(creds3) };
|
|
67992
68010
|
} catch (e) {
|
|
67993
68011
|
return { ok: false, error: err(e) };
|
|
67994
68012
|
}
|
|
67995
68013
|
},
|
|
67996
68014
|
async generateAvatarVideo(req, outDir, onProgress) {
|
|
67997
|
-
const
|
|
67998
|
-
if (!
|
|
67999
|
-
return { ok: false, error:
|
|
68015
|
+
const creds3 = heygenCreds();
|
|
68016
|
+
if (!creds3)
|
|
68017
|
+
return { ok: false, error: NO_AVATAR_CREDS };
|
|
68000
68018
|
try {
|
|
68001
|
-
const videoId = await submitAvatarVideoHeyGen({ avatarId: req.avatarId, talkingPhotoId: req.talkingPhotoId, text: req.text, voiceId: req.voiceId, width: req.width, height: req.height, background: req.background },
|
|
68019
|
+
const videoId = await submitAvatarVideoHeyGen({ avatarId: req.avatarId, talkingPhotoId: req.talkingPhotoId, text: req.text, voiceId: req.voiceId, width: req.width, height: req.height, background: req.background }, creds3);
|
|
68002
68020
|
onProgress?.("Avatar video submitted \u2014 rendering\u2026");
|
|
68003
68021
|
const started = Date.now();
|
|
68004
68022
|
for (; ; ) {
|
|
@@ -68007,7 +68025,7 @@ function createDaemonVideoEditRunner() {
|
|
|
68007
68025
|
await new Promise((r) => setTimeout(r, HEYGEN_POLL_MS));
|
|
68008
68026
|
let poll;
|
|
68009
68027
|
try {
|
|
68010
|
-
poll = await pollAvatarVideoHeyGen(videoId,
|
|
68028
|
+
poll = await pollAvatarVideoHeyGen(videoId, creds3);
|
|
68011
68029
|
} catch {
|
|
68012
68030
|
onProgress?.(`Rendering avatar video\u2026 (${Math.round((Date.now() - started) / 1e3)}s)`);
|
|
68013
68031
|
continue;
|
|
@@ -81930,25 +81948,38 @@ async function runDaemon(opts = {}) {
|
|
|
81930
81948
|
}
|
|
81931
81949
|
async function takeoverMachine() {
|
|
81932
81950
|
const rivals = /* @__PURE__ */ new Set();
|
|
81951
|
+
let lockPid = 0, statusPid = 0;
|
|
81952
|
+
const otherPids = [];
|
|
81933
81953
|
try {
|
|
81934
|
-
|
|
81935
|
-
if (
|
|
81936
|
-
rivals.add(
|
|
81954
|
+
lockPid = Number(readFileSync30(pidfile(), "utf-8").trim());
|
|
81955
|
+
if (lockPid > 0)
|
|
81956
|
+
rivals.add(lockPid);
|
|
81937
81957
|
} catch {
|
|
81938
81958
|
}
|
|
81939
81959
|
try {
|
|
81940
|
-
|
|
81941
|
-
if (
|
|
81942
|
-
rivals.add(
|
|
81960
|
+
statusPid = Number(JSON.parse(readFileSync30(statusFile(), "utf-8")).pid ?? 0);
|
|
81961
|
+
if (statusPid > 0)
|
|
81962
|
+
rivals.add(statusPid);
|
|
81943
81963
|
} catch {
|
|
81944
81964
|
}
|
|
81945
|
-
for (const p of otherDaemonPids())
|
|
81965
|
+
for (const p of otherDaemonPids()) {
|
|
81966
|
+
otherPids.push(p);
|
|
81946
81967
|
rivals.add(p);
|
|
81968
|
+
}
|
|
81969
|
+
try {
|
|
81970
|
+
log9(`takeover: me=${process.pid} lockPid=${lockPid || "-"} statusPid=${statusPid || "-"} otherDaemonPids=[${otherPids.join(",") || "-"}]`);
|
|
81971
|
+
} catch {
|
|
81972
|
+
}
|
|
81947
81973
|
rivals.delete(process.pid);
|
|
81948
81974
|
const live = [...rivals].filter(isAlive2);
|
|
81949
81975
|
if (live.length) {
|
|
81950
81976
|
for (const pid of live) {
|
|
81951
|
-
|
|
81977
|
+
let cmd = "";
|
|
81978
|
+
try {
|
|
81979
|
+
cmd = execFileSync4("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: 2e3 }).trim().slice(0, 200);
|
|
81980
|
+
} catch {
|
|
81981
|
+
}
|
|
81982
|
+
log9(`takeover: killing rival daemon pid=${pid} (latest-wins single-instance) cmd=[${cmd}]`);
|
|
81952
81983
|
try {
|
|
81953
81984
|
process.kill(pid, "SIGTERM");
|
|
81954
81985
|
} catch {
|
|
@@ -82007,9 +82038,30 @@ async function runDaemon(opts = {}) {
|
|
|
82007
82038
|
const creds3 = readCredentials();
|
|
82008
82039
|
const deviceId2 = creds3?.deviceId;
|
|
82009
82040
|
const daemonStartedAt = Date.now();
|
|
82041
|
+
try {
|
|
82042
|
+
const pp = process;
|
|
82043
|
+
log9(`LAUNCH-CTX pid=${pp.pid} ppid=${pp.ppid} exec=${pp.execPath}`);
|
|
82044
|
+
log9(`LAUNCH-CTX argv=${JSON.stringify(pp.argv)}`);
|
|
82045
|
+
log9(`LAUNCH-CTX env: GUI=${process.env.CCB_DAEMON_GUI ?? "-"} FORCE_GUI=${process.env.CCB_FORCE_DAEMON_GUI ?? "-"} RUN_AS_NODE=${process.env.ELECTRON_RUN_AS_NODE ?? "-"} UNMANAGED=${process.env.CCB_DAEMON_UNMANAGED ?? "-"} ACTIVE_LINK=${process.env.CCB_ACTIVE_LINK ?? "-"} RDESK=${process.env.CCB_RDESK_ROLE ?? "-"}`);
|
|
82046
|
+
} catch {
|
|
82047
|
+
}
|
|
82048
|
+
const snapshotProcs = (tag) => {
|
|
82049
|
+
try {
|
|
82050
|
+
const raw = execFileSync4("ps", ["-axww", "-o", "pid=,ppid=,pcpu=,etime=,command="], { encoding: "utf8", timeout: 3e3 });
|
|
82051
|
+
const rows = raw.split("\n").filter((l) => /[Tt]esseract|host-daemon/.test(l) && !/\bgrep\b|ps -axww/.test(l));
|
|
82052
|
+
log9(`PROC-SNAPSHOT [${tag}] me=${process.pid} ppid=${process.ppid} \u2014 ${rows.length} tesseract proc(s):`);
|
|
82053
|
+
for (const r of rows.slice(0, 40))
|
|
82054
|
+
log9(` PROC ${r.trim().slice(0, 240)}`);
|
|
82055
|
+
} catch (e) {
|
|
82056
|
+
try {
|
|
82057
|
+
log9(`PROC-SNAPSHOT [${tag}] ps failed: ${e.message}`);
|
|
82058
|
+
} catch {
|
|
82059
|
+
}
|
|
82060
|
+
}
|
|
82061
|
+
};
|
|
82010
82062
|
process.on("exit", (code) => {
|
|
82011
82063
|
try {
|
|
82012
|
-
log9(`PROCESS EXIT code=${code} uptimeMs=${Date.now() - daemonStartedAt}`);
|
|
82064
|
+
log9(`PROCESS EXIT code=${code} uptimeMs=${Date.now() - daemonStartedAt} ppid=${process.ppid}`);
|
|
82013
82065
|
} catch {
|
|
82014
82066
|
}
|
|
82015
82067
|
});
|
|
@@ -82017,6 +82069,8 @@ async function runDaemon(opts = {}) {
|
|
|
82017
82069
|
try {
|
|
82018
82070
|
log9(`SHUTDOWN reason=${reason} code=${code} uptimeMs=${Date.now() - daemonStartedAt} ppid=${process.ppid} pid=${process.pid}`);
|
|
82019
82071
|
log9(`SHUTDOWN caller: ${(new Error("shutdown").stack ?? "").split("\n").slice(2, 7).map((l) => l.trim()).join(" <- ")}`);
|
|
82072
|
+
if (reason.startsWith("signal"))
|
|
82073
|
+
snapshotProcs(reason);
|
|
82020
82074
|
} catch {
|
|
82021
82075
|
}
|
|
82022
82076
|
if (timer) {
|
|
@@ -82047,6 +82101,16 @@ async function runDaemon(opts = {}) {
|
|
|
82047
82101
|
}
|
|
82048
82102
|
process.on("SIGTERM", () => shutdown(0, "signal:SIGTERM"));
|
|
82049
82103
|
process.on("SIGINT", () => shutdown(0, "signal:SIGINT"));
|
|
82104
|
+
try {
|
|
82105
|
+
process.on("SIGHUP", () => {
|
|
82106
|
+
try {
|
|
82107
|
+
log9("SIGHUP received \u2014 IGNORED (kept alive)");
|
|
82108
|
+
snapshotProcs("SIGHUP");
|
|
82109
|
+
} catch {
|
|
82110
|
+
}
|
|
82111
|
+
});
|
|
82112
|
+
} catch {
|
|
82113
|
+
}
|
|
82050
82114
|
process.on("uncaughtException", (e) => {
|
|
82051
82115
|
try {
|
|
82052
82116
|
log9(`UNCAUGHT (kept alive): ${e instanceof Error ? e.stack ?? e.message : String(e)}`);
|
|
@@ -82067,6 +82131,7 @@ async function runDaemon(opts = {}) {
|
|
|
82067
82131
|
eapp.on("before-quit", (e) => {
|
|
82068
82132
|
try {
|
|
82069
82133
|
log9("APP before-quit \u2014 PREVENTED (daemon never self-quits via Electron)");
|
|
82134
|
+
snapshotProcs("before-quit");
|
|
82070
82135
|
} catch {
|
|
82071
82136
|
}
|
|
82072
82137
|
try {
|
|
@@ -82074,15 +82139,41 @@ async function runDaemon(opts = {}) {
|
|
|
82074
82139
|
} catch {
|
|
82075
82140
|
}
|
|
82076
82141
|
});
|
|
82142
|
+
eapp.on("will-quit", (e) => {
|
|
82143
|
+
try {
|
|
82144
|
+
log9(`APP will-quit \u2014 PREVENTED (uptime ${Date.now() - daemonStartedAt}ms)`);
|
|
82145
|
+
e?.preventDefault?.();
|
|
82146
|
+
} catch {
|
|
82147
|
+
}
|
|
82148
|
+
});
|
|
82149
|
+
eapp.on("quit", (_e, code) => {
|
|
82150
|
+
try {
|
|
82151
|
+
log9(`APP quit event code=${JSON.stringify(code)} (uptime ${Date.now() - daemonStartedAt}ms)`);
|
|
82152
|
+
} catch {
|
|
82153
|
+
}
|
|
82154
|
+
});
|
|
82155
|
+
eapp.on("window-all-closed", () => {
|
|
82156
|
+
try {
|
|
82157
|
+
log9("APP window-all-closed (kept alive \u2014 no auto-quit)");
|
|
82158
|
+
} catch {
|
|
82159
|
+
}
|
|
82160
|
+
});
|
|
82077
82161
|
eapp.on("render-process-gone", (_e, d) => {
|
|
82078
82162
|
try {
|
|
82079
|
-
log9(`render-process-gone (kept alive): ${JSON.stringify(d)}`);
|
|
82163
|
+
log9(`render-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(d)}`);
|
|
82164
|
+
snapshotProcs("render-gone");
|
|
82080
82165
|
} catch {
|
|
82081
82166
|
}
|
|
82082
82167
|
});
|
|
82083
82168
|
eapp.on("child-process-gone", (_e, d) => {
|
|
82084
82169
|
try {
|
|
82085
|
-
log9(`child-process-gone (kept alive): ${JSON.stringify(d)}`);
|
|
82170
|
+
log9(`child-process-gone (kept alive) uptime=${Date.now() - daemonStartedAt}ms: ${JSON.stringify(d)}`);
|
|
82171
|
+
} catch {
|
|
82172
|
+
}
|
|
82173
|
+
});
|
|
82174
|
+
eapp.on("gpu-process-crashed", (_e, killed) => {
|
|
82175
|
+
try {
|
|
82176
|
+
log9(`gpu-process-crashed killed=${JSON.stringify(killed)} uptime=${Date.now() - daemonStartedAt}ms`);
|
|
82086
82177
|
} catch {
|
|
82087
82178
|
}
|
|
82088
82179
|
});
|