@askexenow/exe-os 0.9.7 → 0.9.9

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.
Files changed (101) hide show
  1. package/dist/bin/backfill-conversations.js +953 -105
  2. package/dist/bin/backfill-responses.js +952 -104
  3. package/dist/bin/backfill-vectors.js +956 -108
  4. package/dist/bin/cleanup-stale-review-tasks.js +802 -58
  5. package/dist/bin/cli.js +2292 -1070
  6. package/dist/bin/exe-agent-config.js +157 -101
  7. package/dist/bin/exe-agent.js +55 -29
  8. package/dist/bin/exe-assign.js +940 -92
  9. package/dist/bin/exe-boot.js +1424 -442
  10. package/dist/bin/exe-call.js +240 -141
  11. package/dist/bin/exe-cloud.js +198 -70
  12. package/dist/bin/exe-dispatch.js +951 -192
  13. package/dist/bin/exe-doctor.js +791 -51
  14. package/dist/bin/exe-export-behaviors.js +790 -42
  15. package/dist/bin/exe-forget.js +771 -31
  16. package/dist/bin/exe-gateway.js +1592 -521
  17. package/dist/bin/exe-heartbeat.js +850 -109
  18. package/dist/bin/exe-kill.js +783 -35
  19. package/dist/bin/exe-launch-agent.js +1030 -107
  20. package/dist/bin/exe-link.js +916 -110
  21. package/dist/bin/exe-new-employee.js +526 -217
  22. package/dist/bin/exe-pending-messages.js +1046 -62
  23. package/dist/bin/exe-pending-notifications.js +1318 -111
  24. package/dist/bin/exe-pending-reviews.js +1040 -72
  25. package/dist/bin/exe-rename.js +772 -59
  26. package/dist/bin/exe-review.js +772 -32
  27. package/dist/bin/exe-search.js +982 -128
  28. package/dist/bin/exe-session-cleanup.js +1180 -306
  29. package/dist/bin/exe-settings.js +185 -105
  30. package/dist/bin/exe-start-codex.js +886 -132
  31. package/dist/bin/exe-start-opencode.js +873 -119
  32. package/dist/bin/exe-status.js +803 -59
  33. package/dist/bin/exe-team.js +772 -32
  34. package/dist/bin/git-sweep.js +1046 -223
  35. package/dist/bin/graph-backfill.js +779 -31
  36. package/dist/bin/graph-export.js +785 -37
  37. package/dist/bin/install.js +632 -200
  38. package/dist/bin/scan-tasks.js +1055 -232
  39. package/dist/bin/setup.js +1419 -320
  40. package/dist/bin/shard-migrate.js +783 -35
  41. package/dist/bin/update.js +138 -49
  42. package/dist/bin/wiki-sync.js +782 -34
  43. package/dist/gateway/index.js +1444 -449
  44. package/dist/hooks/bug-report-worker.js +1141 -269
  45. package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
  46. package/dist/hooks/commit-complete.js +1044 -221
  47. package/dist/hooks/error-recall.js +989 -135
  48. package/dist/hooks/exe-heartbeat-hook.js +99 -75
  49. package/dist/hooks/ingest-worker.js +4176 -3226
  50. package/dist/hooks/ingest.js +920 -168
  51. package/dist/hooks/instructions-loaded.js +874 -70
  52. package/dist/hooks/notification.js +860 -56
  53. package/dist/hooks/post-compact.js +881 -73
  54. package/dist/hooks/pre-compact.js +1050 -227
  55. package/dist/hooks/pre-tool-use.js +1084 -159
  56. package/dist/hooks/prompt-ingest-worker.js +1089 -164
  57. package/dist/hooks/prompt-submit.js +1469 -515
  58. package/dist/hooks/response-ingest-worker.js +1104 -179
  59. package/dist/hooks/session-end.js +1085 -251
  60. package/dist/hooks/session-start.js +1241 -231
  61. package/dist/hooks/stop.js +935 -109
  62. package/dist/hooks/subagent-stop.js +881 -73
  63. package/dist/hooks/summary-worker.js +1323 -307
  64. package/dist/index.js +1449 -452
  65. package/dist/lib/agent-config.js +28 -6
  66. package/dist/lib/cloud-sync.js +909 -115
  67. package/dist/lib/config.js +30 -10
  68. package/dist/lib/consolidation.js +42 -9
  69. package/dist/lib/database.js +739 -33
  70. package/dist/lib/db-daemon-client.js +73 -19
  71. package/dist/lib/db.js +2359 -0
  72. package/dist/lib/device-registry.js +760 -47
  73. package/dist/lib/embedder.js +201 -73
  74. package/dist/lib/employee-templates.js +30 -4
  75. package/dist/lib/employees.js +290 -86
  76. package/dist/lib/exe-daemon-client.js +187 -83
  77. package/dist/lib/exe-daemon.js +1696 -616
  78. package/dist/lib/hybrid-search.js +982 -128
  79. package/dist/lib/identity.js +43 -13
  80. package/dist/lib/license.js +133 -48
  81. package/dist/lib/messaging.js +167 -80
  82. package/dist/lib/reminders.js +35 -5
  83. package/dist/lib/schedules.js +772 -32
  84. package/dist/lib/skill-learning.js +54 -7
  85. package/dist/lib/store.js +779 -31
  86. package/dist/lib/task-router.js +94 -73
  87. package/dist/lib/tasks.js +298 -225
  88. package/dist/lib/tmux-routing.js +246 -172
  89. package/dist/lib/token-spend.js +52 -14
  90. package/dist/mcp/server.js +2893 -850
  91. package/dist/mcp/tools/complete-reminder.js +35 -5
  92. package/dist/mcp/tools/create-reminder.js +35 -5
  93. package/dist/mcp/tools/create-task.js +507 -323
  94. package/dist/mcp/tools/deactivate-behavior.js +40 -10
  95. package/dist/mcp/tools/list-reminders.js +35 -5
  96. package/dist/mcp/tools/list-tasks.js +277 -104
  97. package/dist/mcp/tools/send-message.js +129 -56
  98. package/dist/mcp/tools/update-task.js +1864 -188
  99. package/dist/runtime/index.js +1083 -259
  100. package/dist/tui/App.js +1501 -434
  101. package/package.json +3 -2
@@ -3,21 +3,42 @@ import net from "net";
3
3
  import os2 from "os";
4
4
  import { spawn } from "child_process";
5
5
  import { randomUUID } from "crypto";
6
- import { existsSync as existsSync2, unlinkSync, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
7
- import path2 from "path";
6
+ import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
7
+ import path3 from "path";
8
8
  import { fileURLToPath } from "url";
9
9
 
10
10
  // src/lib/config.ts
11
- import { readFile, writeFile, mkdir, chmod } from "fs/promises";
12
- import { readFileSync, existsSync, renameSync } from "fs";
11
+ import { readFile, writeFile } from "fs/promises";
12
+ import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
13
13
  import path from "path";
14
14
  import os from "os";
15
+
16
+ // src/lib/secure-files.ts
17
+ import { chmodSync, existsSync, mkdirSync } from "fs";
18
+ import { chmod, mkdir } from "fs/promises";
19
+ var PRIVATE_DIR_MODE = 448;
20
+ var PRIVATE_FILE_MODE = 384;
21
+ function ensurePrivateDirSync(dirPath) {
22
+ mkdirSync(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
23
+ try {
24
+ chmodSync(dirPath, PRIVATE_DIR_MODE);
25
+ } catch {
26
+ }
27
+ }
28
+ function enforcePrivateFileSync(filePath) {
29
+ try {
30
+ if (existsSync(filePath)) chmodSync(filePath, PRIVATE_FILE_MODE);
31
+ } catch {
32
+ }
33
+ }
34
+
35
+ // src/lib/config.ts
15
36
  function resolveDataDir() {
16
37
  if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
17
38
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
18
39
  const newDir = path.join(os.homedir(), ".exe-os");
19
40
  const legacyDir = path.join(os.homedir(), ".exe-mem");
20
- if (!existsSync(newDir) && existsSync(legacyDir)) {
41
+ if (!existsSync2(newDir) && existsSync2(legacyDir)) {
21
42
  try {
22
43
  renameSync(legacyDir, newDir);
23
44
  process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
@@ -92,18 +113,52 @@ var DEFAULT_CONFIG = {
92
113
  }
93
114
  };
94
115
 
116
+ // src/lib/daemon-auth.ts
117
+ import crypto from "crypto";
118
+ import path2 from "path";
119
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
120
+ var DAEMON_TOKEN_PATH = path2.join(EXE_AI_DIR, "exed.token");
121
+ function normalizeToken(token) {
122
+ if (!token) return null;
123
+ const trimmed = token.trim();
124
+ return trimmed.length > 0 ? trimmed : null;
125
+ }
126
+ function readDaemonToken() {
127
+ try {
128
+ if (!existsSync3(DAEMON_TOKEN_PATH)) return null;
129
+ return normalizeToken(readFileSync2(DAEMON_TOKEN_PATH, "utf8"));
130
+ } catch {
131
+ return null;
132
+ }
133
+ }
134
+ function ensureDaemonToken(seed) {
135
+ const existing = readDaemonToken();
136
+ if (existing) return existing;
137
+ const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
138
+ ensurePrivateDirSync(EXE_AI_DIR);
139
+ writeFileSync(DAEMON_TOKEN_PATH, `${token}
140
+ `, "utf8");
141
+ enforcePrivateFileSync(DAEMON_TOKEN_PATH);
142
+ return token;
143
+ }
144
+
95
145
  // src/lib/exe-daemon-client.ts
96
- var SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path2.join(EXE_AI_DIR, "exed.sock");
97
- var PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path2.join(EXE_AI_DIR, "exed.pid");
98
- var SPAWN_LOCK_PATH = path2.join(EXE_AI_DIR, "exed-spawn.lock");
146
+ var SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path3.join(EXE_AI_DIR, "exed.sock");
147
+ var PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path3.join(EXE_AI_DIR, "exed.pid");
148
+ var SPAWN_LOCK_PATH = path3.join(EXE_AI_DIR, "exed-spawn.lock");
99
149
  var SPAWN_LOCK_STALE_MS = 3e4;
100
150
  var CONNECT_TIMEOUT_MS = 15e3;
101
151
  var REQUEST_TIMEOUT_MS = 3e4;
152
+ var DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
102
153
  var _socket = null;
103
154
  var _connected = false;
104
155
  var _buffer = "";
105
156
  var _requestCount = 0;
157
+ var _consecutiveFailures = 0;
106
158
  var HEALTH_CHECK_INTERVAL = 100;
159
+ var MAX_RETRIES_BEFORE_RESTART = 3;
160
+ var RETRY_DELAYS_MS = [1e3, 3e3, 5e3];
161
+ var MIN_DAEMON_AGE_MS = 3e4;
107
162
  var _pending = /* @__PURE__ */ new Map();
108
163
  var MAX_BUFFER = 1e7;
109
164
  function handleData(chunk) {
@@ -132,9 +187,9 @@ function handleData(chunk) {
132
187
  }
133
188
  }
134
189
  function cleanupStaleFiles() {
135
- if (existsSync2(PID_PATH)) {
190
+ if (existsSync4(PID_PATH)) {
136
191
  try {
137
- const pid = parseInt(readFileSync2(PID_PATH, "utf8").trim(), 10);
192
+ const pid = parseInt(readFileSync3(PID_PATH, "utf8").trim(), 10);
138
193
  if (pid > 0) {
139
194
  try {
140
195
  process.kill(pid, 0);
@@ -155,11 +210,11 @@ function cleanupStaleFiles() {
155
210
  }
156
211
  }
157
212
  function findPackageRoot() {
158
- let dir = path2.dirname(fileURLToPath(import.meta.url));
159
- const { root } = path2.parse(dir);
213
+ let dir = path3.dirname(fileURLToPath(import.meta.url));
214
+ const { root } = path3.parse(dir);
160
215
  while (dir !== root) {
161
- if (existsSync2(path2.join(dir, "package.json"))) return dir;
162
- dir = path2.dirname(dir);
216
+ if (existsSync4(path3.join(dir, "package.json"))) return dir;
217
+ dir = path3.dirname(dir);
163
218
  }
164
219
  return null;
165
220
  }
@@ -185,16 +240,17 @@ function spawnDaemon() {
185
240
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
186
241
  return;
187
242
  }
188
- const daemonPath = path2.join(pkgRoot, "dist", "lib", "exe-daemon.js");
189
- if (!existsSync2(daemonPath)) {
243
+ const daemonPath = path3.join(pkgRoot, "dist", "lib", "exe-daemon.js");
244
+ if (!existsSync4(daemonPath)) {
190
245
  process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
191
246
  `);
192
247
  return;
193
248
  }
194
249
  const resolvedPath = daemonPath;
250
+ const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
195
251
  process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
196
252
  `);
197
- const logPath = path2.join(path2.dirname(SOCKET_PATH), "exed.log");
253
+ const logPath = path3.join(path3.dirname(SOCKET_PATH), "exed.log");
198
254
  let stderrFd = "ignore";
199
255
  try {
200
256
  stderrFd = openSync(logPath, "a");
@@ -212,7 +268,8 @@ function spawnDaemon() {
212
268
  TMUX_PANE: void 0,
213
269
  // Prevents resolveExeSession() from scoping to one session
214
270
  EXE_DAEMON_SOCK: SOCKET_PATH,
215
- EXE_DAEMON_PID: PID_PATH
271
+ EXE_DAEMON_PID: PID_PATH,
272
+ [DAEMON_TOKEN_ENV]: daemonToken
216
273
  }
217
274
  });
218
275
  child.unref();
@@ -322,13 +379,14 @@ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
322
379
  return;
323
380
  }
324
381
  const id = randomUUID();
382
+ const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
325
383
  const timer = setTimeout(() => {
326
384
  _pending.delete(id);
327
385
  resolve({ error: "Request timeout" });
328
386
  }, timeoutMs);
329
387
  _pending.set(id, { resolve, timer });
330
388
  try {
331
- _socket.write(JSON.stringify({ id, ...payload }) + "\n");
389
+ _socket.write(JSON.stringify({ id, token, ...payload }) + "\n");
332
390
  } catch {
333
391
  clearTimeout(timer);
334
392
  _pending.delete(id);
@@ -345,98 +403,132 @@ async function pingDaemon() {
345
403
  return null;
346
404
  }
347
405
  function killAndRespawnDaemon() {
348
- process.stderr.write("[exed-client] Killing daemon for restart...\n");
349
- if (existsSync2(PID_PATH)) {
350
- try {
351
- const pid = parseInt(readFileSync2(PID_PATH, "utf8").trim(), 10);
352
- if (pid > 0) {
353
- try {
354
- process.kill(pid, "SIGKILL");
355
- } catch {
406
+ if (!acquireSpawnLock()) {
407
+ process.stderr.write("[exed-client] Another process is already restarting daemon \u2014 skipping\n");
408
+ if (_socket) {
409
+ _socket.destroy();
410
+ _socket = null;
411
+ }
412
+ _connected = false;
413
+ _buffer = "";
414
+ return;
415
+ }
416
+ try {
417
+ process.stderr.write("[exed-client] Killing daemon for restart...\n");
418
+ if (existsSync4(PID_PATH)) {
419
+ try {
420
+ const pid = parseInt(readFileSync3(PID_PATH, "utf8").trim(), 10);
421
+ if (pid > 0) {
422
+ try {
423
+ process.kill(pid, "SIGKILL");
424
+ } catch {
425
+ }
356
426
  }
427
+ } catch {
357
428
  }
429
+ }
430
+ if (_socket) {
431
+ _socket.destroy();
432
+ _socket = null;
433
+ }
434
+ _connected = false;
435
+ _buffer = "";
436
+ try {
437
+ unlinkSync(PID_PATH);
358
438
  } catch {
359
439
  }
440
+ try {
441
+ unlinkSync(SOCKET_PATH);
442
+ } catch {
443
+ }
444
+ spawnDaemon();
445
+ } finally {
446
+ releaseSpawnLock();
360
447
  }
361
- if (_socket) {
362
- _socket.destroy();
363
- _socket = null;
364
- }
365
- _connected = false;
366
- _buffer = "";
448
+ }
449
+ function isDaemonTooYoung() {
367
450
  try {
368
- unlinkSync(PID_PATH);
451
+ const stat = statSync(PID_PATH);
452
+ return Date.now() - stat.mtimeMs < MIN_DAEMON_AGE_MS;
369
453
  } catch {
454
+ return false;
370
455
  }
371
- try {
372
- unlinkSync(SOCKET_PATH);
373
- } catch {
456
+ }
457
+ async function retryThenRestart(doRequest, label) {
458
+ const result = await doRequest();
459
+ if (!result.error) {
460
+ _consecutiveFailures = 0;
461
+ return result;
374
462
  }
375
- spawnDaemon();
463
+ _consecutiveFailures++;
464
+ for (let i = 0; i < MAX_RETRIES_BEFORE_RESTART; i++) {
465
+ const delayMs = RETRY_DELAYS_MS[i] ?? 5e3;
466
+ process.stderr.write(`[exed-client] ${label} failed (${result.error}), retry ${i + 1}/${MAX_RETRIES_BEFORE_RESTART} in ${delayMs}ms
467
+ `);
468
+ await new Promise((r) => setTimeout(r, delayMs));
469
+ if (!_connected) {
470
+ if (!await connectToSocket()) continue;
471
+ }
472
+ const retry = await doRequest();
473
+ if (!retry.error) {
474
+ _consecutiveFailures = 0;
475
+ return retry;
476
+ }
477
+ _consecutiveFailures++;
478
+ }
479
+ if (isDaemonTooYoung()) {
480
+ process.stderr.write(`[exed-client] ${label}: daemon too young (< ${MIN_DAEMON_AGE_MS / 1e3}s) \u2014 skipping restart
481
+ `);
482
+ return { error: result.error };
483
+ }
484
+ process.stderr.write(`[exed-client] ${label}: ${_consecutiveFailures} consecutive failures \u2014 restarting daemon
485
+ `);
486
+ killAndRespawnDaemon();
487
+ const start = Date.now();
488
+ let delay = 200;
489
+ while (Date.now() - start < CONNECT_TIMEOUT_MS) {
490
+ await new Promise((r) => setTimeout(r, delay));
491
+ if (await connectToSocket()) break;
492
+ delay = Math.min(delay * 2, 3e3);
493
+ }
494
+ if (!_connected) return { error: "Daemon restart failed" };
495
+ const final = await doRequest();
496
+ if (!final.error) _consecutiveFailures = 0;
497
+ return final;
376
498
  }
377
499
  async function embedViaClient(text, priority = "high") {
378
500
  if (!_connected && !await connectEmbedDaemon()) return null;
379
501
  _requestCount++;
380
502
  if (_requestCount % HEALTH_CHECK_INTERVAL === 0) {
381
503
  const health = await pingDaemon();
382
- if (!health) {
504
+ if (!health && !isDaemonTooYoung()) {
383
505
  process.stderr.write(`[exed-client] Periodic health check failed at request ${_requestCount} \u2014 restarting daemon
384
506
  `);
385
507
  killAndRespawnDaemon();
386
508
  const start = Date.now();
387
- let delay = 200;
509
+ let d = 200;
388
510
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
389
- await new Promise((r) => setTimeout(r, delay));
511
+ await new Promise((r) => setTimeout(r, d));
390
512
  if (await connectToSocket()) break;
391
- delay = Math.min(delay * 2, 3e3);
513
+ d = Math.min(d * 2, 3e3);
392
514
  }
393
515
  if (!_connected) return null;
394
516
  }
395
517
  }
396
- const result = await sendRequest([text], priority);
397
- if (!result.error && result.vectors?.[0]) return result.vectors[0];
398
- if (result.error) {
399
- process.stderr.write(`[exed-client] Embed failed (${result.error}) \u2014 attempting restart
400
- `);
401
- killAndRespawnDaemon();
402
- const start = Date.now();
403
- let delay = 200;
404
- while (Date.now() - start < CONNECT_TIMEOUT_MS) {
405
- await new Promise((r) => setTimeout(r, delay));
406
- if (await connectToSocket()) break;
407
- delay = Math.min(delay * 2, 3e3);
408
- }
409
- if (!_connected) return null;
410
- const retry = await sendRequest([text], priority);
411
- if (!retry.error && retry.vectors?.[0]) return retry.vectors[0];
412
- process.stderr.write(`[exed-client] Embed retry also failed: ${retry.error ?? "no vector"}
413
- `);
414
- }
415
- return null;
518
+ const result = await retryThenRestart(
519
+ () => sendRequest([text], priority),
520
+ "Embed"
521
+ );
522
+ return !result.error && result.vectors?.[0] ? result.vectors[0] : null;
416
523
  }
417
524
  async function embedBatchViaClient(texts, priority = "high") {
418
525
  if (!_connected && !await connectEmbedDaemon()) return null;
419
526
  _requestCount++;
420
- const result = await sendRequest(texts, priority);
421
- if (!result.error && result.vectors) return result.vectors;
422
- if (result.error) {
423
- process.stderr.write(`[exed-client] Batch embed failed (${result.error}) \u2014 attempting restart
424
- `);
425
- killAndRespawnDaemon();
426
- const start = Date.now();
427
- let delay = 200;
428
- while (Date.now() - start < CONNECT_TIMEOUT_MS) {
429
- await new Promise((r) => setTimeout(r, delay));
430
- if (await connectToSocket()) break;
431
- delay = Math.min(delay * 2, 3e3);
432
- }
433
- if (!_connected) return null;
434
- const retry = await sendRequest(texts, priority);
435
- if (!retry.error && retry.vectors) return retry.vectors;
436
- process.stderr.write(`[exed-client] Batch retry also failed: ${retry.error ?? "no vectors"}
437
- `);
438
- }
439
- return null;
527
+ const result = await retryThenRestart(
528
+ () => sendRequest(texts, priority),
529
+ "Batch embed"
530
+ );
531
+ return !result.error && result.vectors ? result.vectors : null;
440
532
  }
441
533
  function disconnectClient() {
442
534
  if (_socket) {
@@ -454,6 +546,17 @@ function disconnectClient() {
454
546
  function isClientConnected() {
455
547
  return _connected;
456
548
  }
549
+ function sendIngestRequest(payload) {
550
+ if (!_socket || !_connected) return false;
551
+ try {
552
+ const id = randomUUID();
553
+ const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
554
+ _socket.write(JSON.stringify({ id, token, type: "ingest", ...payload }) + "\n");
555
+ return true;
556
+ } catch {
557
+ return false;
558
+ }
559
+ }
457
560
  export {
458
561
  connectEmbedDaemon,
459
562
  disconnectClient,
@@ -461,5 +564,6 @@ export {
461
564
  embedViaClient,
462
565
  isClientConnected,
463
566
  pingDaemon,
464
- sendDaemonRequest
567
+ sendDaemonRequest,
568
+ sendIngestRequest
465
569
  };