@askexenow/exe-os 0.8.89 → 0.8.91
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/bin/backfill-conversations.js +10 -0
- package/dist/bin/backfill-responses.js +10 -0
- package/dist/bin/backfill-vectors.js +10 -0
- package/dist/bin/cli.js +75 -30
- package/dist/bin/exe-assign.js +13 -3
- package/dist/bin/exe-boot.js +34 -24
- package/dist/bin/exe-gateway.js +36 -26
- package/dist/bin/exe-link.js +10 -0
- package/dist/bin/exe-rename.js +10 -0
- package/dist/bin/exe-search.js +10 -0
- package/dist/bin/exe-session-cleanup.js +30 -20
- package/dist/bin/git-sweep.js +25 -15
- package/dist/bin/scan-tasks.js +27 -17
- package/dist/bin/setup.js +52 -7
- package/dist/gateway/index.js +34 -24
- package/dist/hooks/commit-complete.js +25 -15
- package/dist/hooks/error-recall.js +10 -0
- package/dist/hooks/ingest-worker.js +30 -20
- package/dist/hooks/instructions-loaded.js +15 -5
- package/dist/hooks/notification.js +13 -3
- package/dist/hooks/post-compact.js +17 -7
- package/dist/hooks/pre-compact.js +25 -15
- package/dist/hooks/pre-tool-use.js +20 -10
- package/dist/hooks/prompt-ingest-worker.js +10 -0
- package/dist/hooks/prompt-submit.js +20 -10
- package/dist/hooks/response-ingest-worker.js +10 -0
- package/dist/hooks/session-end.js +26 -16
- package/dist/hooks/session-start.js +19 -9
- package/dist/hooks/stop.js +17 -7
- package/dist/hooks/subagent-stop.js +17 -7
- package/dist/hooks/summary-worker.js +23 -13
- package/dist/index.js +29 -19
- package/dist/lib/cloud-sync.js +13 -3
- package/dist/lib/database.js +10 -0
- package/dist/lib/db-daemon-client.js +10 -0
- package/dist/lib/device-registry.js +12 -2
- package/dist/lib/embedder.js +10 -0
- package/dist/lib/exe-daemon-client.js +10 -0
- package/dist/lib/exe-daemon.js +31 -21
- package/dist/lib/hybrid-search.js +10 -0
- package/dist/mcp/server.js +38 -28
- package/dist/runtime/index.js +25 -15
- package/dist/tui/App.js +27 -17
- package/package.json +1 -1
package/dist/bin/exe-gateway.js
CHANGED
|
@@ -1835,6 +1835,7 @@ var init_memory = __esm({
|
|
|
1835
1835
|
|
|
1836
1836
|
// src/lib/exe-daemon-client.ts
|
|
1837
1837
|
import net from "net";
|
|
1838
|
+
import os3 from "os";
|
|
1838
1839
|
import { spawn } from "child_process";
|
|
1839
1840
|
import { randomUUID } from "crypto";
|
|
1840
1841
|
import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
|
|
@@ -1898,6 +1899,15 @@ function findPackageRoot() {
|
|
|
1898
1899
|
return null;
|
|
1899
1900
|
}
|
|
1900
1901
|
function spawnDaemon() {
|
|
1902
|
+
const freeGB = os3.freemem() / (1024 * 1024 * 1024);
|
|
1903
|
+
const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
|
|
1904
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
1905
|
+
process.stderr.write(
|
|
1906
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
1907
|
+
`
|
|
1908
|
+
);
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1901
1911
|
const pkgRoot = findPackageRoot();
|
|
1902
1912
|
if (!pkgRoot) {
|
|
1903
1913
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
@@ -2236,9 +2246,9 @@ var init_embedder = __esm({
|
|
|
2236
2246
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2237
2247
|
import { existsSync as existsSync4 } from "fs";
|
|
2238
2248
|
import path4 from "path";
|
|
2239
|
-
import
|
|
2249
|
+
import os4 from "os";
|
|
2240
2250
|
function getKeyDir() {
|
|
2241
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(
|
|
2251
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
|
|
2242
2252
|
}
|
|
2243
2253
|
function getKeyPath() {
|
|
2244
2254
|
return path4.join(getKeyDir(), "master.key");
|
|
@@ -2264,7 +2274,7 @@ async function getMasterKey() {
|
|
|
2264
2274
|
const keyPath = getKeyPath();
|
|
2265
2275
|
if (!existsSync4(keyPath)) {
|
|
2266
2276
|
process.stderr.write(
|
|
2267
|
-
`[keychain] Key not found at ${keyPath} (HOME=${
|
|
2277
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
2268
2278
|
`
|
|
2269
2279
|
);
|
|
2270
2280
|
return null;
|
|
@@ -5594,7 +5604,7 @@ __export(imessage_exports, {
|
|
|
5594
5604
|
});
|
|
5595
5605
|
import { execFile } from "child_process";
|
|
5596
5606
|
import { promisify } from "util";
|
|
5597
|
-
import
|
|
5607
|
+
import os5 from "os";
|
|
5598
5608
|
import path7 from "path";
|
|
5599
5609
|
var execFileAsync, POLL_INTERVAL_MS, MESSAGES_DB_PATH, IMessageAdapter;
|
|
5600
5610
|
var init_imessage = __esm({
|
|
@@ -5603,7 +5613,7 @@ var init_imessage = __esm({
|
|
|
5603
5613
|
execFileAsync = promisify(execFile);
|
|
5604
5614
|
POLL_INTERVAL_MS = 5e3;
|
|
5605
5615
|
MESSAGES_DB_PATH = path7.join(
|
|
5606
|
-
process.env.HOME ??
|
|
5616
|
+
process.env.HOME ?? os5.homedir(),
|
|
5607
5617
|
"Library/Messages/chat.db"
|
|
5608
5618
|
);
|
|
5609
5619
|
IMessageAdapter = class {
|
|
@@ -6069,7 +6079,7 @@ var init_whatsapp_accounts = __esm({
|
|
|
6069
6079
|
// src/lib/session-registry.ts
|
|
6070
6080
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync7 } from "fs";
|
|
6071
6081
|
import path8 from "path";
|
|
6072
|
-
import
|
|
6082
|
+
import os6 from "os";
|
|
6073
6083
|
function registerSession(entry) {
|
|
6074
6084
|
const dir = path8.dirname(REGISTRY_PATH);
|
|
6075
6085
|
if (!existsSync7(dir)) {
|
|
@@ -6096,7 +6106,7 @@ var REGISTRY_PATH;
|
|
|
6096
6106
|
var init_session_registry = __esm({
|
|
6097
6107
|
"src/lib/session-registry.ts"() {
|
|
6098
6108
|
"use strict";
|
|
6099
|
-
REGISTRY_PATH = path8.join(
|
|
6109
|
+
REGISTRY_PATH = path8.join(os6.homedir(), ".exe-os", "session-registry.json");
|
|
6100
6110
|
}
|
|
6101
6111
|
});
|
|
6102
6112
|
|
|
@@ -6369,7 +6379,7 @@ var init_agent_config = __esm({
|
|
|
6369
6379
|
// src/lib/intercom-queue.ts
|
|
6370
6380
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync as renameSync3, existsSync as existsSync9, mkdirSync as mkdirSync6 } from "fs";
|
|
6371
6381
|
import path10 from "path";
|
|
6372
|
-
import
|
|
6382
|
+
import os7 from "os";
|
|
6373
6383
|
function ensureDir() {
|
|
6374
6384
|
const dir = path10.dirname(QUEUE_PATH);
|
|
6375
6385
|
if (!existsSync9(dir)) mkdirSync6(dir, { recursive: true });
|
|
@@ -6409,9 +6419,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
6409
6419
|
var init_intercom_queue = __esm({
|
|
6410
6420
|
"src/lib/intercom-queue.ts"() {
|
|
6411
6421
|
"use strict";
|
|
6412
|
-
QUEUE_PATH = path10.join(
|
|
6422
|
+
QUEUE_PATH = path10.join(os7.homedir(), ".exe-os", "intercom-queue.json");
|
|
6413
6423
|
TTL_MS = 60 * 60 * 1e3;
|
|
6414
|
-
INTERCOM_LOG = path10.join(
|
|
6424
|
+
INTERCOM_LOG = path10.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
6415
6425
|
}
|
|
6416
6426
|
});
|
|
6417
6427
|
|
|
@@ -6496,7 +6506,7 @@ var init_plan_limits = __esm({
|
|
|
6496
6506
|
// src/lib/notifications.ts
|
|
6497
6507
|
import crypto3 from "crypto";
|
|
6498
6508
|
import path12 from "path";
|
|
6499
|
-
import
|
|
6509
|
+
import os8 from "os";
|
|
6500
6510
|
import {
|
|
6501
6511
|
readFileSync as readFileSync10,
|
|
6502
6512
|
readdirSync as readdirSync2,
|
|
@@ -6606,7 +6616,7 @@ var init_task_scope = __esm({
|
|
|
6606
6616
|
// src/lib/tasks-crud.ts
|
|
6607
6617
|
import crypto5 from "crypto";
|
|
6608
6618
|
import path13 from "path";
|
|
6609
|
-
import
|
|
6619
|
+
import os9 from "os";
|
|
6610
6620
|
import { execSync as execSync4 } from "child_process";
|
|
6611
6621
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
6612
6622
|
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
@@ -6821,7 +6831,7 @@ ${laneWarning}` : laneWarning;
|
|
|
6821
6831
|
});
|
|
6822
6832
|
if (input.baseDir) {
|
|
6823
6833
|
try {
|
|
6824
|
-
const EXE_OS_DIR = path13.join(
|
|
6834
|
+
const EXE_OS_DIR = path13.join(os9.homedir(), ".exe-os");
|
|
6825
6835
|
const mdPath = path13.join(EXE_OS_DIR, taskFile);
|
|
6826
6836
|
const mdDir = path13.dirname(mdPath);
|
|
6827
6837
|
if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
|
|
@@ -8467,7 +8477,7 @@ __export(tmux_routing_exports, {
|
|
|
8467
8477
|
import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
|
|
8468
8478
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, existsSync as existsSync14, appendFileSync } from "fs";
|
|
8469
8479
|
import path18 from "path";
|
|
8470
|
-
import
|
|
8480
|
+
import os10 from "os";
|
|
8471
8481
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8472
8482
|
import { unlinkSync as unlinkSync6 } from "fs";
|
|
8473
8483
|
function spawnLockPath(sessionName) {
|
|
@@ -8881,7 +8891,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8881
8891
|
const transport = getTransport();
|
|
8882
8892
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
8883
8893
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
8884
|
-
const logDir = path18.join(
|
|
8894
|
+
const logDir = path18.join(os10.homedir(), ".exe-os", "session-logs");
|
|
8885
8895
|
const logFile = path18.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
8886
8896
|
if (!existsSync14(logDir)) {
|
|
8887
8897
|
mkdirSync8(logDir, { recursive: true });
|
|
@@ -8897,7 +8907,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8897
8907
|
} catch {
|
|
8898
8908
|
}
|
|
8899
8909
|
try {
|
|
8900
|
-
const claudeJsonPath = path18.join(
|
|
8910
|
+
const claudeJsonPath = path18.join(os10.homedir(), ".claude.json");
|
|
8901
8911
|
let claudeJson = {};
|
|
8902
8912
|
try {
|
|
8903
8913
|
claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
|
|
@@ -8912,7 +8922,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8912
8922
|
} catch {
|
|
8913
8923
|
}
|
|
8914
8924
|
try {
|
|
8915
|
-
const settingsDir = path18.join(
|
|
8925
|
+
const settingsDir = path18.join(os10.homedir(), ".claude", "projects");
|
|
8916
8926
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
8917
8927
|
const projSettingsDir = path18.join(settingsDir, normalizedKey);
|
|
8918
8928
|
const settingsPath = path18.join(projSettingsDir, "settings.json");
|
|
@@ -8963,7 +8973,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8963
8973
|
let legacyFallbackWarned = false;
|
|
8964
8974
|
if (!useExeAgent && !useBinSymlink) {
|
|
8965
8975
|
const identityPath = path18.join(
|
|
8966
|
-
|
|
8976
|
+
os10.homedir(),
|
|
8967
8977
|
".exe-os",
|
|
8968
8978
|
"identity",
|
|
8969
8979
|
`${employeeName}.md`
|
|
@@ -8993,7 +9003,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8993
9003
|
}
|
|
8994
9004
|
let sessionContextFlag = "";
|
|
8995
9005
|
try {
|
|
8996
|
-
const ctxDir = path18.join(
|
|
9006
|
+
const ctxDir = path18.join(os10.homedir(), ".exe-os", "session-cache");
|
|
8997
9007
|
mkdirSync8(ctxDir, { recursive: true });
|
|
8998
9008
|
const ctxFile = path18.join(ctxDir, `session-context-${sessionName}.md`);
|
|
8999
9009
|
const ctxContent = [
|
|
@@ -9154,13 +9164,13 @@ var init_tmux_routing = __esm({
|
|
|
9154
9164
|
init_intercom_queue();
|
|
9155
9165
|
init_plan_limits();
|
|
9156
9166
|
init_employees();
|
|
9157
|
-
SPAWN_LOCK_DIR = path18.join(
|
|
9158
|
-
SESSION_CACHE = path18.join(
|
|
9167
|
+
SPAWN_LOCK_DIR = path18.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
9168
|
+
SESSION_CACHE = path18.join(os10.homedir(), ".exe-os", "session-cache");
|
|
9159
9169
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
9160
9170
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
9161
9171
|
VERIFY_PANE_LINES = 200;
|
|
9162
9172
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
9163
|
-
INTERCOM_LOG2 = path18.join(
|
|
9173
|
+
INTERCOM_LOG2 = path18.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
9164
9174
|
DEBOUNCE_FILE = path18.join(SESSION_CACHE, "intercom-debounce.json");
|
|
9165
9175
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
9166
9176
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
@@ -9422,7 +9432,7 @@ var init_messaging = __esm({
|
|
|
9422
9432
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync9 } from "fs";
|
|
9423
9433
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
9424
9434
|
import path19 from "path";
|
|
9425
|
-
import
|
|
9435
|
+
import os11 from "os";
|
|
9426
9436
|
function substituteTemplate(template, record) {
|
|
9427
9437
|
return template.replace(
|
|
9428
9438
|
/\{\{(\w+(?:\.\w+)*)\}\}/g,
|
|
@@ -9717,7 +9727,7 @@ var TRIGGERS_PATH, GRAPH_API_VERSION;
|
|
|
9717
9727
|
var init_trigger_engine = __esm({
|
|
9718
9728
|
"src/automation/trigger-engine.ts"() {
|
|
9719
9729
|
"use strict";
|
|
9720
|
-
TRIGGERS_PATH = path19.join(
|
|
9730
|
+
TRIGGERS_PATH = path19.join(os11.homedir(), ".exe-os", "triggers.json");
|
|
9721
9731
|
GRAPH_API_VERSION = "v21.0";
|
|
9722
9732
|
}
|
|
9723
9733
|
});
|
|
@@ -9782,7 +9792,7 @@ var init_crm_webhook = __esm({
|
|
|
9782
9792
|
// src/bin/exe-gateway.ts
|
|
9783
9793
|
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
|
|
9784
9794
|
import path20 from "path";
|
|
9785
|
-
import
|
|
9795
|
+
import os12 from "os";
|
|
9786
9796
|
|
|
9787
9797
|
// src/gateway/webhook-server.ts
|
|
9788
9798
|
import {
|
|
@@ -10748,7 +10758,7 @@ var BotRegistry = class {
|
|
|
10748
10758
|
|
|
10749
10759
|
// src/bin/exe-gateway.ts
|
|
10750
10760
|
init_employees();
|
|
10751
|
-
var CONFIG_DIR = path20.join(
|
|
10761
|
+
var CONFIG_DIR = path20.join(os12.homedir(), ".exe-os");
|
|
10752
10762
|
var CONFIG_PATH3 = path20.join(CONFIG_DIR, "gateway.json");
|
|
10753
10763
|
var DEFAULT_PORT = 3100;
|
|
10754
10764
|
function loadConfig2() {
|
package/dist/bin/exe-link.js
CHANGED
|
@@ -580,6 +580,7 @@ var init_employees = __esm({
|
|
|
580
580
|
|
|
581
581
|
// src/lib/exe-daemon-client.ts
|
|
582
582
|
import net from "net";
|
|
583
|
+
import os4 from "os";
|
|
583
584
|
import { spawn } from "child_process";
|
|
584
585
|
import { randomUUID } from "crypto";
|
|
585
586
|
import { existsSync as existsSync4, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
|
|
@@ -643,6 +644,15 @@ function findPackageRoot() {
|
|
|
643
644
|
return null;
|
|
644
645
|
}
|
|
645
646
|
function spawnDaemon() {
|
|
647
|
+
const freeGB = os4.freemem() / (1024 * 1024 * 1024);
|
|
648
|
+
const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
|
|
649
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
650
|
+
process.stderr.write(
|
|
651
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
652
|
+
`
|
|
653
|
+
);
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
646
656
|
const pkgRoot = findPackageRoot();
|
|
647
657
|
if (!pkgRoot) {
|
|
648
658
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
package/dist/bin/exe-rename.js
CHANGED
|
@@ -264,6 +264,7 @@ var init_db_retry = __esm({
|
|
|
264
264
|
|
|
265
265
|
// src/lib/exe-daemon-client.ts
|
|
266
266
|
import net from "net";
|
|
267
|
+
import os3 from "os";
|
|
267
268
|
import { spawn } from "child_process";
|
|
268
269
|
import { randomUUID } from "crypto";
|
|
269
270
|
import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
|
|
@@ -327,6 +328,15 @@ function findPackageRoot() {
|
|
|
327
328
|
return null;
|
|
328
329
|
}
|
|
329
330
|
function spawnDaemon() {
|
|
331
|
+
const freeGB = os3.freemem() / (1024 * 1024 * 1024);
|
|
332
|
+
const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
|
|
333
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
334
|
+
process.stderr.write(
|
|
335
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
336
|
+
`
|
|
337
|
+
);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
330
340
|
const pkgRoot = findPackageRoot();
|
|
331
341
|
if (!pkgRoot) {
|
|
332
342
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
package/dist/bin/exe-search.js
CHANGED
|
@@ -2661,6 +2661,7 @@ var init_reranker = __esm({
|
|
|
2661
2661
|
|
|
2662
2662
|
// src/lib/exe-daemon-client.ts
|
|
2663
2663
|
import net from "net";
|
|
2664
|
+
import os4 from "os";
|
|
2664
2665
|
import { spawn } from "child_process";
|
|
2665
2666
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2666
2667
|
import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
|
|
@@ -2724,6 +2725,15 @@ function findPackageRoot() {
|
|
|
2724
2725
|
return null;
|
|
2725
2726
|
}
|
|
2726
2727
|
function spawnDaemon() {
|
|
2728
|
+
const freeGB = os4.freemem() / (1024 * 1024 * 1024);
|
|
2729
|
+
const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
|
|
2730
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
2731
|
+
process.stderr.write(
|
|
2732
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
2733
|
+
`
|
|
2734
|
+
);
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2727
2737
|
const pkgRoot = findPackageRoot();
|
|
2728
2738
|
if (!pkgRoot) {
|
|
2729
2739
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
@@ -388,6 +388,7 @@ var init_employees = __esm({
|
|
|
388
388
|
|
|
389
389
|
// src/lib/exe-daemon-client.ts
|
|
390
390
|
import net from "net";
|
|
391
|
+
import os3 from "os";
|
|
391
392
|
import { spawn } from "child_process";
|
|
392
393
|
import { randomUUID } from "crypto";
|
|
393
394
|
import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
|
|
@@ -451,6 +452,15 @@ function findPackageRoot() {
|
|
|
451
452
|
return null;
|
|
452
453
|
}
|
|
453
454
|
function spawnDaemon() {
|
|
455
|
+
const freeGB = os3.freemem() / (1024 * 1024 * 1024);
|
|
456
|
+
const totalGB = os3.totalmem() / (1024 * 1024 * 1024);
|
|
457
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
458
|
+
process.stderr.write(
|
|
459
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
460
|
+
`
|
|
461
|
+
);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
454
464
|
const pkgRoot = findPackageRoot();
|
|
455
465
|
if (!pkgRoot) {
|
|
456
466
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
@@ -1936,9 +1946,9 @@ var init_database = __esm({
|
|
|
1936
1946
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
1937
1947
|
import { existsSync as existsSync4 } from "fs";
|
|
1938
1948
|
import path4 from "path";
|
|
1939
|
-
import
|
|
1949
|
+
import os4 from "os";
|
|
1940
1950
|
function getKeyDir() {
|
|
1941
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(
|
|
1951
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os4.homedir(), ".exe-os");
|
|
1942
1952
|
}
|
|
1943
1953
|
function getKeyPath() {
|
|
1944
1954
|
return path4.join(getKeyDir(), "master.key");
|
|
@@ -1964,7 +1974,7 @@ async function getMasterKey() {
|
|
|
1964
1974
|
const keyPath = getKeyPath();
|
|
1965
1975
|
if (!existsSync4(keyPath)) {
|
|
1966
1976
|
process.stderr.write(
|
|
1967
|
-
`[keychain] Key not found at ${keyPath} (HOME=${
|
|
1977
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os4.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
1968
1978
|
`
|
|
1969
1979
|
);
|
|
1970
1980
|
return null;
|
|
@@ -3041,7 +3051,7 @@ var init_store = __esm({
|
|
|
3041
3051
|
// src/lib/session-registry.ts
|
|
3042
3052
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync6 } from "fs";
|
|
3043
3053
|
import path6 from "path";
|
|
3044
|
-
import
|
|
3054
|
+
import os5 from "os";
|
|
3045
3055
|
function registerSession(entry) {
|
|
3046
3056
|
const dir = path6.dirname(REGISTRY_PATH);
|
|
3047
3057
|
if (!existsSync6(dir)) {
|
|
@@ -3068,7 +3078,7 @@ var REGISTRY_PATH;
|
|
|
3068
3078
|
var init_session_registry = __esm({
|
|
3069
3079
|
"src/lib/session-registry.ts"() {
|
|
3070
3080
|
"use strict";
|
|
3071
|
-
REGISTRY_PATH = path6.join(
|
|
3081
|
+
REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
|
|
3072
3082
|
}
|
|
3073
3083
|
});
|
|
3074
3084
|
|
|
@@ -3341,7 +3351,7 @@ var init_agent_config = __esm({
|
|
|
3341
3351
|
// src/lib/intercom-queue.ts
|
|
3342
3352
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
3343
3353
|
import path8 from "path";
|
|
3344
|
-
import
|
|
3354
|
+
import os6 from "os";
|
|
3345
3355
|
function ensureDir() {
|
|
3346
3356
|
const dir = path8.dirname(QUEUE_PATH);
|
|
3347
3357
|
if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
|
|
@@ -3381,9 +3391,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
3381
3391
|
var init_intercom_queue = __esm({
|
|
3382
3392
|
"src/lib/intercom-queue.ts"() {
|
|
3383
3393
|
"use strict";
|
|
3384
|
-
QUEUE_PATH = path8.join(
|
|
3394
|
+
QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
3385
3395
|
TTL_MS = 60 * 60 * 1e3;
|
|
3386
|
-
INTERCOM_LOG = path8.join(
|
|
3396
|
+
INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
3387
3397
|
}
|
|
3388
3398
|
});
|
|
3389
3399
|
|
|
@@ -3491,7 +3501,7 @@ var init_plan_limits = __esm({
|
|
|
3491
3501
|
// src/lib/notifications.ts
|
|
3492
3502
|
import crypto from "crypto";
|
|
3493
3503
|
import path11 from "path";
|
|
3494
|
-
import
|
|
3504
|
+
import os7 from "os";
|
|
3495
3505
|
import {
|
|
3496
3506
|
readFileSync as readFileSync9,
|
|
3497
3507
|
readdirSync as readdirSync2,
|
|
@@ -3593,7 +3603,7 @@ __export(tasks_crud_exports, {
|
|
|
3593
3603
|
});
|
|
3594
3604
|
import crypto3 from "crypto";
|
|
3595
3605
|
import path12 from "path";
|
|
3596
|
-
import
|
|
3606
|
+
import os8 from "os";
|
|
3597
3607
|
import { execSync as execSync4 } from "child_process";
|
|
3598
3608
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
3599
3609
|
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
@@ -3808,7 +3818,7 @@ ${laneWarning}` : laneWarning;
|
|
|
3808
3818
|
});
|
|
3809
3819
|
if (input.baseDir) {
|
|
3810
3820
|
try {
|
|
3811
|
-
const EXE_OS_DIR = path12.join(
|
|
3821
|
+
const EXE_OS_DIR = path12.join(os8.homedir(), ".exe-os");
|
|
3812
3822
|
const mdPath = path12.join(EXE_OS_DIR, taskFile);
|
|
3813
3823
|
const mdDir = path12.dirname(mdPath);
|
|
3814
3824
|
if (!existsSync12(mdDir)) await mkdir4(mdDir, { recursive: true });
|
|
@@ -5553,7 +5563,7 @@ __export(tmux_routing_exports, {
|
|
|
5553
5563
|
import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
|
|
5554
5564
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync14, appendFileSync } from "fs";
|
|
5555
5565
|
import path17 from "path";
|
|
5556
|
-
import
|
|
5566
|
+
import os9 from "os";
|
|
5557
5567
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5558
5568
|
import { unlinkSync as unlinkSync6 } from "fs";
|
|
5559
5569
|
function spawnLockPath(sessionName) {
|
|
@@ -5967,7 +5977,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
|
|
|
5967
5977
|
const transport = getTransport();
|
|
5968
5978
|
const sessionName = employeeSessionName(employeeName, exeSession2, opts?.instance);
|
|
5969
5979
|
const instanceLabel2 = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
5970
|
-
const logDir = path17.join(
|
|
5980
|
+
const logDir = path17.join(os9.homedir(), ".exe-os", "session-logs");
|
|
5971
5981
|
const logFile = path17.join(logDir, `${instanceLabel2}-${Date.now()}.log`);
|
|
5972
5982
|
if (!existsSync14(logDir)) {
|
|
5973
5983
|
mkdirSync7(logDir, { recursive: true });
|
|
@@ -5983,7 +5993,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
|
|
|
5983
5993
|
} catch {
|
|
5984
5994
|
}
|
|
5985
5995
|
try {
|
|
5986
|
-
const claudeJsonPath = path17.join(
|
|
5996
|
+
const claudeJsonPath = path17.join(os9.homedir(), ".claude.json");
|
|
5987
5997
|
let claudeJson = {};
|
|
5988
5998
|
try {
|
|
5989
5999
|
claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
|
|
@@ -5998,7 +6008,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
|
|
|
5998
6008
|
} catch {
|
|
5999
6009
|
}
|
|
6000
6010
|
try {
|
|
6001
|
-
const settingsDir = path17.join(
|
|
6011
|
+
const settingsDir = path17.join(os9.homedir(), ".claude", "projects");
|
|
6002
6012
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
6003
6013
|
const projSettingsDir = path17.join(settingsDir, normalizedKey);
|
|
6004
6014
|
const settingsPath = path17.join(projSettingsDir, "settings.json");
|
|
@@ -6049,7 +6059,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
|
|
|
6049
6059
|
let legacyFallbackWarned = false;
|
|
6050
6060
|
if (!useExeAgent && !useBinSymlink) {
|
|
6051
6061
|
const identityPath = path17.join(
|
|
6052
|
-
|
|
6062
|
+
os9.homedir(),
|
|
6053
6063
|
".exe-os",
|
|
6054
6064
|
"identity",
|
|
6055
6065
|
`${employeeName}.md`
|
|
@@ -6079,7 +6089,7 @@ function spawnEmployee(employeeName, exeSession2, projectDir, opts) {
|
|
|
6079
6089
|
}
|
|
6080
6090
|
let sessionContextFlag = "";
|
|
6081
6091
|
try {
|
|
6082
|
-
const ctxDir = path17.join(
|
|
6092
|
+
const ctxDir = path17.join(os9.homedir(), ".exe-os", "session-cache");
|
|
6083
6093
|
mkdirSync7(ctxDir, { recursive: true });
|
|
6084
6094
|
const ctxFile = path17.join(ctxDir, `session-context-${sessionName}.md`);
|
|
6085
6095
|
const ctxContent = [
|
|
@@ -6240,13 +6250,13 @@ var init_tmux_routing = __esm({
|
|
|
6240
6250
|
init_intercom_queue();
|
|
6241
6251
|
init_plan_limits();
|
|
6242
6252
|
init_employees();
|
|
6243
|
-
SPAWN_LOCK_DIR = path17.join(
|
|
6244
|
-
SESSION_CACHE = path17.join(
|
|
6253
|
+
SPAWN_LOCK_DIR = path17.join(os9.homedir(), ".exe-os", "spawn-locks");
|
|
6254
|
+
SESSION_CACHE = path17.join(os9.homedir(), ".exe-os", "session-cache");
|
|
6245
6255
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
6246
6256
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
6247
6257
|
VERIFY_PANE_LINES = 200;
|
|
6248
6258
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
6249
|
-
INTERCOM_LOG2 = path17.join(
|
|
6259
|
+
INTERCOM_LOG2 = path17.join(os9.homedir(), ".exe-os", "intercom.log");
|
|
6250
6260
|
DEBOUNCE_FILE = path17.join(SESSION_CACHE, "intercom-debounce.json");
|
|
6251
6261
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
6252
6262
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
package/dist/bin/git-sweep.js
CHANGED
|
@@ -660,6 +660,7 @@ var init_employees = __esm({
|
|
|
660
660
|
|
|
661
661
|
// src/lib/exe-daemon-client.ts
|
|
662
662
|
import net from "net";
|
|
663
|
+
import os5 from "os";
|
|
663
664
|
import { spawn } from "child_process";
|
|
664
665
|
import { randomUUID } from "crypto";
|
|
665
666
|
import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync } from "fs";
|
|
@@ -723,6 +724,15 @@ function findPackageRoot() {
|
|
|
723
724
|
return null;
|
|
724
725
|
}
|
|
725
726
|
function spawnDaemon() {
|
|
727
|
+
const freeGB = os5.freemem() / (1024 * 1024 * 1024);
|
|
728
|
+
const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
|
|
729
|
+
if (freeGB < 1.5 && totalGB <= 8) {
|
|
730
|
+
process.stderr.write(
|
|
731
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only. Close other apps and retry.
|
|
732
|
+
`
|
|
733
|
+
);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
726
736
|
const pkgRoot = findPackageRoot();
|
|
727
737
|
if (!pkgRoot) {
|
|
728
738
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
@@ -2212,7 +2222,7 @@ var init_plan_limits = __esm({
|
|
|
2212
2222
|
// src/lib/notifications.ts
|
|
2213
2223
|
import crypto from "crypto";
|
|
2214
2224
|
import path9 from "path";
|
|
2215
|
-
import
|
|
2225
|
+
import os6 from "os";
|
|
2216
2226
|
import {
|
|
2217
2227
|
readFileSync as readFileSync9,
|
|
2218
2228
|
readdirSync,
|
|
@@ -2369,7 +2379,7 @@ __export(tasks_crud_exports, {
|
|
|
2369
2379
|
});
|
|
2370
2380
|
import crypto3 from "crypto";
|
|
2371
2381
|
import path10 from "path";
|
|
2372
|
-
import
|
|
2382
|
+
import os7 from "os";
|
|
2373
2383
|
import { execSync as execSync4 } from "child_process";
|
|
2374
2384
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
2375
2385
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
|
|
@@ -2584,7 +2594,7 @@ ${laneWarning}` : laneWarning;
|
|
|
2584
2594
|
});
|
|
2585
2595
|
if (input.baseDir) {
|
|
2586
2596
|
try {
|
|
2587
|
-
const EXE_OS_DIR = path10.join(
|
|
2597
|
+
const EXE_OS_DIR = path10.join(os7.homedir(), ".exe-os");
|
|
2588
2598
|
const mdPath = path10.join(EXE_OS_DIR, taskFile);
|
|
2589
2599
|
const mdDir = path10.dirname(mdPath);
|
|
2590
2600
|
if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
|
|
@@ -4230,7 +4240,7 @@ __export(tmux_routing_exports, {
|
|
|
4230
4240
|
import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
|
|
4231
4241
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
|
|
4232
4242
|
import path15 from "path";
|
|
4233
|
-
import
|
|
4243
|
+
import os8 from "os";
|
|
4234
4244
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4235
4245
|
import { unlinkSync as unlinkSync6 } from "fs";
|
|
4236
4246
|
function spawnLockPath(sessionName) {
|
|
@@ -4644,7 +4654,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
4644
4654
|
const transport = getTransport();
|
|
4645
4655
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
4646
4656
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
4647
|
-
const logDir = path15.join(
|
|
4657
|
+
const logDir = path15.join(os8.homedir(), ".exe-os", "session-logs");
|
|
4648
4658
|
const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
4649
4659
|
if (!existsSync12(logDir)) {
|
|
4650
4660
|
mkdirSync6(logDir, { recursive: true });
|
|
@@ -4660,7 +4670,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
4660
4670
|
} catch {
|
|
4661
4671
|
}
|
|
4662
4672
|
try {
|
|
4663
|
-
const claudeJsonPath = path15.join(
|
|
4673
|
+
const claudeJsonPath = path15.join(os8.homedir(), ".claude.json");
|
|
4664
4674
|
let claudeJson = {};
|
|
4665
4675
|
try {
|
|
4666
4676
|
claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
|
|
@@ -4675,7 +4685,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
4675
4685
|
} catch {
|
|
4676
4686
|
}
|
|
4677
4687
|
try {
|
|
4678
|
-
const settingsDir = path15.join(
|
|
4688
|
+
const settingsDir = path15.join(os8.homedir(), ".claude", "projects");
|
|
4679
4689
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
4680
4690
|
const projSettingsDir = path15.join(settingsDir, normalizedKey);
|
|
4681
4691
|
const settingsPath = path15.join(projSettingsDir, "settings.json");
|
|
@@ -4726,7 +4736,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
4726
4736
|
let legacyFallbackWarned = false;
|
|
4727
4737
|
if (!useExeAgent && !useBinSymlink) {
|
|
4728
4738
|
const identityPath = path15.join(
|
|
4729
|
-
|
|
4739
|
+
os8.homedir(),
|
|
4730
4740
|
".exe-os",
|
|
4731
4741
|
"identity",
|
|
4732
4742
|
`${employeeName}.md`
|
|
@@ -4756,7 +4766,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
4756
4766
|
}
|
|
4757
4767
|
let sessionContextFlag = "";
|
|
4758
4768
|
try {
|
|
4759
|
-
const ctxDir = path15.join(
|
|
4769
|
+
const ctxDir = path15.join(os8.homedir(), ".exe-os", "session-cache");
|
|
4760
4770
|
mkdirSync6(ctxDir, { recursive: true });
|
|
4761
4771
|
const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
|
|
4762
4772
|
const ctxContent = [
|
|
@@ -4917,13 +4927,13 @@ var init_tmux_routing = __esm({
|
|
|
4917
4927
|
init_intercom_queue();
|
|
4918
4928
|
init_plan_limits();
|
|
4919
4929
|
init_employees();
|
|
4920
|
-
SPAWN_LOCK_DIR = path15.join(
|
|
4921
|
-
SESSION_CACHE = path15.join(
|
|
4930
|
+
SPAWN_LOCK_DIR = path15.join(os8.homedir(), ".exe-os", "spawn-locks");
|
|
4931
|
+
SESSION_CACHE = path15.join(os8.homedir(), ".exe-os", "session-cache");
|
|
4922
4932
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
4923
4933
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
4924
4934
|
VERIFY_PANE_LINES = 200;
|
|
4925
4935
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
4926
|
-
INTERCOM_LOG2 = path15.join(
|
|
4936
|
+
INTERCOM_LOG2 = path15.join(os8.homedir(), ".exe-os", "intercom.log");
|
|
4927
4937
|
DEBOUNCE_FILE = path15.join(SESSION_CACHE, "intercom-debounce.json");
|
|
4928
4938
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
4929
4939
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
@@ -4967,9 +4977,9 @@ var init_memory = __esm({
|
|
|
4967
4977
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
4968
4978
|
import { existsSync as existsSync13 } from "fs";
|
|
4969
4979
|
import path16 from "path";
|
|
4970
|
-
import
|
|
4980
|
+
import os9 from "os";
|
|
4971
4981
|
function getKeyDir() {
|
|
4972
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(
|
|
4982
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path16.join(os9.homedir(), ".exe-os");
|
|
4973
4983
|
}
|
|
4974
4984
|
function getKeyPath() {
|
|
4975
4985
|
return path16.join(getKeyDir(), "master.key");
|
|
@@ -4995,7 +5005,7 @@ async function getMasterKey() {
|
|
|
4995
5005
|
const keyPath = getKeyPath();
|
|
4996
5006
|
if (!existsSync13(keyPath)) {
|
|
4997
5007
|
process.stderr.write(
|
|
4998
|
-
`[keychain] Key not found at ${keyPath} (HOME=${
|
|
5008
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os9.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
4999
5009
|
`
|
|
5000
5010
|
);
|
|
5001
5011
|
return null;
|