@askexenow/exe-os 0.9.113 → 0.9.114
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/agentic-ontology-backfill.js +24 -12
- package/dist/bin/agentic-reflection-backfill.js +24 -12
- package/dist/bin/agentic-semantic-label.js +24 -12
- package/dist/bin/backfill-conversations.js +24 -12
- package/dist/bin/backfill-responses.js +24 -12
- package/dist/bin/backfill-vectors.js +24 -12
- package/dist/bin/bulk-sync-postgres.js +24 -12
- package/dist/bin/cleanup-stale-review-tasks.js +24 -12
- package/dist/bin/cli.js +96 -22
- package/dist/bin/exe-agent.js +27 -0
- package/dist/bin/exe-assign.js +24 -12
- package/dist/bin/exe-boot.js +44 -15
- package/dist/bin/exe-call.js +8 -0
- package/dist/bin/exe-cloud.js +34 -11
- package/dist/bin/exe-dispatch.js +34 -16
- package/dist/bin/exe-doctor.js +24 -12
- package/dist/bin/exe-export-behaviors.js +24 -12
- package/dist/bin/exe-forget.js +24 -12
- package/dist/bin/exe-gateway.js +33 -15
- package/dist/bin/exe-heartbeat.js +24 -12
- package/dist/bin/exe-kill.js +24 -12
- package/dist/bin/exe-launch-agent.js +103 -17
- package/dist/bin/exe-new-employee.js +9 -1
- package/dist/bin/exe-pending-messages.js +24 -12
- package/dist/bin/exe-pending-notifications.js +24 -12
- package/dist/bin/exe-pending-reviews.js +24 -12
- package/dist/bin/exe-rename.js +24 -12
- package/dist/bin/exe-review.js +24 -12
- package/dist/bin/exe-search.js +24 -12
- package/dist/bin/exe-session-cleanup.js +33 -15
- package/dist/bin/exe-start-codex.js +33 -13
- package/dist/bin/exe-start-opencode.js +33 -13
- package/dist/bin/exe-status.js +24 -12
- package/dist/bin/exe-team.js +24 -12
- package/dist/bin/git-sweep.js +34 -16
- package/dist/bin/graph-backfill.js +24 -12
- package/dist/bin/graph-export.js +24 -12
- package/dist/bin/install.js +9 -1
- package/dist/bin/intercom-check.js +33 -15
- package/dist/bin/scan-tasks.js +34 -16
- package/dist/bin/setup.js +60 -11
- package/dist/bin/shard-migrate.js +24 -12
- package/dist/gateway/index.js +33 -15
- package/dist/hooks/bug-report-worker.js +33 -15
- package/dist/hooks/codex-stop-task-finalizer.js +32 -12
- package/dist/hooks/commit-complete.js +34 -16
- package/dist/hooks/error-recall.js +24 -12
- package/dist/hooks/ingest.js +33 -15
- package/dist/hooks/instructions-loaded.js +24 -12
- package/dist/hooks/notification.js +24 -12
- package/dist/hooks/post-compact.js +24 -12
- package/dist/hooks/post-tool-combined.js +24 -12
- package/dist/hooks/pre-compact.js +34 -16
- package/dist/hooks/pre-tool-use.js +58 -11
- package/dist/hooks/prompt-submit.js +33 -15
- package/dist/hooks/session-end.js +34 -16
- package/dist/hooks/session-start.js +32 -12
- package/dist/hooks/stop.js +24 -12
- package/dist/hooks/subagent-stop.js +24 -12
- package/dist/hooks/summary-worker.js +34 -11
- package/dist/index.js +60 -15
- package/dist/lib/agent-config.js +8 -0
- package/dist/lib/cloud-sync.js +34 -11
- package/dist/lib/consolidation.js +9 -1
- package/dist/lib/employees.js +8 -0
- package/dist/lib/exe-daemon.js +174 -17
- package/dist/lib/hybrid-search.js +24 -12
- package/dist/lib/keychain.js +24 -12
- package/dist/lib/schedules.js +24 -12
- package/dist/lib/skill-learning.js +8 -0
- package/dist/lib/store.js +24 -12
- package/dist/lib/tasks.js +10 -4
- package/dist/lib/tmux-routing.js +10 -4
- package/dist/mcp/server.js +44 -15
- package/dist/mcp/tools/create-task.js +10 -4
- package/dist/mcp/tools/update-task.js +10 -4
- package/dist/runtime/index.js +60 -15
- package/dist/tui/App.js +61 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -367,6 +367,7 @@ __export(agent_config_exports, {
|
|
|
367
367
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
368
368
|
getAgentRuntime: () => getAgentRuntime,
|
|
369
369
|
loadAgentConfig: () => loadAgentConfig,
|
|
370
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
370
371
|
saveAgentConfig: () => saveAgentConfig,
|
|
371
372
|
setAgentMcps: () => setAgentMcps,
|
|
372
373
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -395,6 +396,13 @@ function getAgentRuntime(agentId) {
|
|
|
395
396
|
if (orgDefault) return orgDefault;
|
|
396
397
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
397
398
|
}
|
|
399
|
+
function normalizeCcModelName(model) {
|
|
400
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
401
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
402
|
+
ccModel += "[1m]";
|
|
403
|
+
}
|
|
404
|
+
return ccModel;
|
|
405
|
+
}
|
|
398
406
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
399
407
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
400
408
|
if (!knownModels) {
|
|
@@ -7869,10 +7877,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7869
7877
|
}
|
|
7870
7878
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
7871
7879
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
ccModel += "[1m]";
|
|
7875
|
-
}
|
|
7880
|
+
const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
|
|
7881
|
+
const ccModel = normalizeCcModelName2(agentRtConfig.model);
|
|
7876
7882
|
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
7877
7883
|
}
|
|
7878
7884
|
}
|
|
@@ -8004,7 +8010,7 @@ var init_tmux_routing = __esm({
|
|
|
8004
8010
|
});
|
|
8005
8011
|
|
|
8006
8012
|
// src/lib/keychain.ts
|
|
8007
|
-
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
8013
|
+
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
8008
8014
|
import { existsSync as existsSync17, statSync as statSync3 } from "fs";
|
|
8009
8015
|
import { execSync as execSync9 } from "child_process";
|
|
8010
8016
|
import path20 from "path";
|
|
@@ -8039,12 +8045,14 @@ function linuxSecretAvailable() {
|
|
|
8039
8045
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
8040
8046
|
if (process.platform !== "linux") return false;
|
|
8041
8047
|
try {
|
|
8042
|
-
const uid = typeof os13.userInfo().uid === "number" ? os13.userInfo().uid : -1;
|
|
8043
8048
|
const st = statSync3(keyPath);
|
|
8044
8049
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
8050
|
+
const uid = typeof os13.userInfo().uid === "number" ? os13.userInfo().uid : -1;
|
|
8045
8051
|
if (uid === 0) return true;
|
|
8046
8052
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
8047
|
-
|
|
8053
|
+
if (exeOsDir && path20.resolve(keyPath).startsWith(path20.resolve(exeOsDir) + path20.sep)) return true;
|
|
8054
|
+
if (!linuxSecretAvailable()) return true;
|
|
8055
|
+
return false;
|
|
8048
8056
|
} catch {
|
|
8049
8057
|
return false;
|
|
8050
8058
|
}
|
|
@@ -8194,15 +8202,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
8194
8202
|
await mkdir4(dir, { recursive: true });
|
|
8195
8203
|
const keyPath = getKeyPath();
|
|
8196
8204
|
const machineKey = deriveMachineKey();
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8205
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
8206
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
8207
|
+
const tmpPath = keyPath + ".tmp";
|
|
8208
|
+
try {
|
|
8209
|
+
if (existsSync17(keyPath)) {
|
|
8210
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
8211
|
+
});
|
|
8212
|
+
}
|
|
8213
|
+
await writeFile5(tmpPath, content, "utf-8");
|
|
8214
|
+
await chmod2(tmpPath, 384);
|
|
8215
|
+
await rename(tmpPath, keyPath);
|
|
8216
|
+
} catch (err) {
|
|
8217
|
+
try {
|
|
8218
|
+
await unlink(tmpPath);
|
|
8219
|
+
} catch {
|
|
8220
|
+
}
|
|
8221
|
+
throw err;
|
|
8202
8222
|
}
|
|
8203
|
-
|
|
8204
|
-
await chmod2(keyPath, 384);
|
|
8205
|
-
return "plaintext";
|
|
8223
|
+
return result;
|
|
8206
8224
|
}
|
|
8207
8225
|
async function getMasterKey() {
|
|
8208
8226
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -13555,6 +13573,33 @@ var DANGEROUS_PATTERNS = [
|
|
|
13555
13573
|
regex: /\bkill\s+-9\b/,
|
|
13556
13574
|
severity: "warning",
|
|
13557
13575
|
reason: "Force kill signal"
|
|
13576
|
+
},
|
|
13577
|
+
// MCP bypass — agents must use MCP tools, never access the DB directly.
|
|
13578
|
+
// These patterns catch attempts to work around a disconnected MCP server.
|
|
13579
|
+
{
|
|
13580
|
+
regex: /\bsqlite3\b.*\bmemories\.db\b/,
|
|
13581
|
+
severity: "critical",
|
|
13582
|
+
reason: "Direct SQLite access bypasses MCP contract boundary \u2014 use MCP tools"
|
|
13583
|
+
},
|
|
13584
|
+
{
|
|
13585
|
+
regex: /\bsqlite3\b.*\.exe-os\b/,
|
|
13586
|
+
severity: "critical",
|
|
13587
|
+
reason: "Direct SQLite access to exe-os database \u2014 use MCP tools"
|
|
13588
|
+
},
|
|
13589
|
+
{
|
|
13590
|
+
regex: /\bnode\s+-e\b.*\b(better-sqlite3|libsql|sqlite3)\b/,
|
|
13591
|
+
severity: "critical",
|
|
13592
|
+
reason: "Inline Node.js script accessing SQLite directly \u2014 use MCP tools"
|
|
13593
|
+
},
|
|
13594
|
+
{
|
|
13595
|
+
regex: /\brequire\s*\(\s*['"].*memories\.db['"]\s*\)/,
|
|
13596
|
+
severity: "critical",
|
|
13597
|
+
reason: "Direct require of memories database \u2014 use MCP tools"
|
|
13598
|
+
},
|
|
13599
|
+
{
|
|
13600
|
+
regex: /\bcat\b.*\bmemories\.db\b/,
|
|
13601
|
+
severity: "warning",
|
|
13602
|
+
reason: "Reading raw database file \u2014 encrypted data, use MCP tools instead"
|
|
13558
13603
|
}
|
|
13559
13604
|
];
|
|
13560
13605
|
function checkDangerousPatterns(command) {
|
package/dist/lib/agent-config.js
CHANGED
|
@@ -175,6 +175,13 @@ function getAgentRuntime(agentId) {
|
|
|
175
175
|
if (orgDefault) return orgDefault;
|
|
176
176
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
177
177
|
}
|
|
178
|
+
function normalizeCcModelName(model) {
|
|
179
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
180
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
181
|
+
ccModel += "[1m]";
|
|
182
|
+
}
|
|
183
|
+
return ccModel;
|
|
184
|
+
}
|
|
178
185
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
179
186
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
180
187
|
if (!knownModels) {
|
|
@@ -223,6 +230,7 @@ export {
|
|
|
223
230
|
clearAgentRuntime,
|
|
224
231
|
getAgentRuntime,
|
|
225
232
|
loadAgentConfig,
|
|
233
|
+
normalizeCcModelName,
|
|
226
234
|
saveAgentConfig,
|
|
227
235
|
setAgentMcps,
|
|
228
236
|
setAgentRuntime
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -3289,7 +3289,7 @@ __export(keychain_exports, {
|
|
|
3289
3289
|
importMnemonic: () => importMnemonic,
|
|
3290
3290
|
setMasterKey: () => setMasterKey
|
|
3291
3291
|
});
|
|
3292
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3292
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
3293
3293
|
import { existsSync as existsSync9, statSync as statSync3 } from "fs";
|
|
3294
3294
|
import { execSync as execSync3 } from "child_process";
|
|
3295
3295
|
import path8 from "path";
|
|
@@ -3324,12 +3324,14 @@ function linuxSecretAvailable() {
|
|
|
3324
3324
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
3325
3325
|
if (process.platform !== "linux") return false;
|
|
3326
3326
|
try {
|
|
3327
|
-
const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
|
|
3328
3327
|
const st = statSync3(keyPath);
|
|
3329
3328
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3329
|
+
const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
|
|
3330
3330
|
if (uid === 0) return true;
|
|
3331
3331
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
3332
|
-
|
|
3332
|
+
if (exeOsDir && path8.resolve(keyPath).startsWith(path8.resolve(exeOsDir) + path8.sep)) return true;
|
|
3333
|
+
if (!linuxSecretAvailable()) return true;
|
|
3334
|
+
return false;
|
|
3333
3335
|
} catch {
|
|
3334
3336
|
return false;
|
|
3335
3337
|
}
|
|
@@ -3479,15 +3481,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
3479
3481
|
await mkdir3(dir, { recursive: true });
|
|
3480
3482
|
const keyPath = getKeyPath();
|
|
3481
3483
|
const machineKey = deriveMachineKey();
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3484
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
3485
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
3486
|
+
const tmpPath = keyPath + ".tmp";
|
|
3487
|
+
try {
|
|
3488
|
+
if (existsSync9(keyPath)) {
|
|
3489
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
3490
|
+
});
|
|
3491
|
+
}
|
|
3492
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
3493
|
+
await chmod2(tmpPath, 384);
|
|
3494
|
+
await rename(tmpPath, keyPath);
|
|
3495
|
+
} catch (err) {
|
|
3496
|
+
try {
|
|
3497
|
+
await unlink(tmpPath);
|
|
3498
|
+
} catch {
|
|
3499
|
+
}
|
|
3500
|
+
throw err;
|
|
3487
3501
|
}
|
|
3488
|
-
|
|
3489
|
-
await chmod2(keyPath, 384);
|
|
3490
|
-
return "plaintext";
|
|
3502
|
+
return result;
|
|
3491
3503
|
}
|
|
3492
3504
|
async function getMasterKey() {
|
|
3493
3505
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -4156,6 +4168,15 @@ async function fetchWithRetry(url, init) {
|
|
|
4156
4168
|
}
|
|
4157
4169
|
throw lastError;
|
|
4158
4170
|
}
|
|
4171
|
+
function migrateEndpoint(endpoint) {
|
|
4172
|
+
if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
|
|
4173
|
+
process.stderr.write(
|
|
4174
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
4175
|
+
);
|
|
4176
|
+
return "https://cloud.askexe.com";
|
|
4177
|
+
}
|
|
4178
|
+
return endpoint;
|
|
4179
|
+
}
|
|
4159
4180
|
function assertSecureEndpoint(endpoint) {
|
|
4160
4181
|
if (endpoint.startsWith("https://")) return;
|
|
4161
4182
|
if (endpoint.startsWith("http://")) {
|
|
@@ -4294,6 +4315,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
4294
4315
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
4295
4316
|
}
|
|
4296
4317
|
async function cloudSync(config) {
|
|
4318
|
+
config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
|
|
4297
4319
|
if (!isSyncCryptoInitialized()) {
|
|
4298
4320
|
try {
|
|
4299
4321
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
@@ -5404,6 +5426,7 @@ export {
|
|
|
5404
5426
|
markCloudReuploadRequired,
|
|
5405
5427
|
mergeConfig,
|
|
5406
5428
|
mergeRosterFromRemote,
|
|
5429
|
+
migrateEndpoint,
|
|
5407
5430
|
pushToPostgres,
|
|
5408
5431
|
recordRosterDeletion
|
|
5409
5432
|
};
|
|
@@ -183,6 +183,7 @@ __export(agent_config_exports, {
|
|
|
183
183
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
184
184
|
getAgentRuntime: () => getAgentRuntime,
|
|
185
185
|
loadAgentConfig: () => loadAgentConfig,
|
|
186
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
186
187
|
saveAgentConfig: () => saveAgentConfig,
|
|
187
188
|
setAgentMcps: () => setAgentMcps,
|
|
188
189
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -211,6 +212,13 @@ function getAgentRuntime(agentId) {
|
|
|
211
212
|
if (orgDefault) return orgDefault;
|
|
212
213
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
213
214
|
}
|
|
215
|
+
function normalizeCcModelName(model) {
|
|
216
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
217
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
218
|
+
ccModel += "[1m]";
|
|
219
|
+
}
|
|
220
|
+
return ccModel;
|
|
221
|
+
}
|
|
214
222
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
215
223
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
216
224
|
if (!knownModels) {
|
|
@@ -581,7 +589,7 @@ init_memory();
|
|
|
581
589
|
init_database();
|
|
582
590
|
|
|
583
591
|
// src/lib/keychain.ts
|
|
584
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
592
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
585
593
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
586
594
|
import { execSync as execSync2 } from "child_process";
|
|
587
595
|
import path5 from "path";
|
package/dist/lib/employees.js
CHANGED
|
@@ -169,6 +169,7 @@ __export(agent_config_exports, {
|
|
|
169
169
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
170
170
|
getAgentRuntime: () => getAgentRuntime,
|
|
171
171
|
loadAgentConfig: () => loadAgentConfig,
|
|
172
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
172
173
|
saveAgentConfig: () => saveAgentConfig,
|
|
173
174
|
setAgentMcps: () => setAgentMcps,
|
|
174
175
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -197,6 +198,13 @@ function getAgentRuntime(agentId) {
|
|
|
197
198
|
if (orgDefault) return orgDefault;
|
|
198
199
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
199
200
|
}
|
|
201
|
+
function normalizeCcModelName(model) {
|
|
202
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
203
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
204
|
+
ccModel += "[1m]";
|
|
205
|
+
}
|
|
206
|
+
return ccModel;
|
|
207
|
+
}
|
|
200
208
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
201
209
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
202
210
|
if (!knownModels) {
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -567,6 +567,7 @@ __export(agent_config_exports, {
|
|
|
567
567
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
568
568
|
getAgentRuntime: () => getAgentRuntime,
|
|
569
569
|
loadAgentConfig: () => loadAgentConfig,
|
|
570
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
570
571
|
saveAgentConfig: () => saveAgentConfig,
|
|
571
572
|
setAgentMcps: () => setAgentMcps,
|
|
572
573
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -595,6 +596,13 @@ function getAgentRuntime(agentId) {
|
|
|
595
596
|
if (orgDefault) return orgDefault;
|
|
596
597
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
597
598
|
}
|
|
599
|
+
function normalizeCcModelName(model) {
|
|
600
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
601
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
602
|
+
ccModel += "[1m]";
|
|
603
|
+
}
|
|
604
|
+
return ccModel;
|
|
605
|
+
}
|
|
598
606
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
599
607
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
600
608
|
if (!knownModels) {
|
|
@@ -5510,7 +5518,7 @@ __export(keychain_exports, {
|
|
|
5510
5518
|
importMnemonic: () => importMnemonic,
|
|
5511
5519
|
setMasterKey: () => setMasterKey
|
|
5512
5520
|
});
|
|
5513
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
5521
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
5514
5522
|
import { existsSync as existsSync12, statSync as statSync5 } from "fs";
|
|
5515
5523
|
import { execSync as execSync3 } from "child_process";
|
|
5516
5524
|
import path11 from "path";
|
|
@@ -5545,12 +5553,14 @@ function linuxSecretAvailable() {
|
|
|
5545
5553
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
5546
5554
|
if (process.platform !== "linux") return false;
|
|
5547
5555
|
try {
|
|
5548
|
-
const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
|
|
5549
5556
|
const st = statSync5(keyPath);
|
|
5550
5557
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
5558
|
+
const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
|
|
5551
5559
|
if (uid === 0) return true;
|
|
5552
5560
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
5553
|
-
|
|
5561
|
+
if (exeOsDir && path11.resolve(keyPath).startsWith(path11.resolve(exeOsDir) + path11.sep)) return true;
|
|
5562
|
+
if (!linuxSecretAvailable()) return true;
|
|
5563
|
+
return false;
|
|
5554
5564
|
} catch {
|
|
5555
5565
|
return false;
|
|
5556
5566
|
}
|
|
@@ -5700,15 +5710,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
5700
5710
|
await mkdir3(dir, { recursive: true });
|
|
5701
5711
|
const keyPath = getKeyPath();
|
|
5702
5712
|
const machineKey = deriveMachineKey();
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5713
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
5714
|
+
const result3 = machineKey ? "encrypted" : "plaintext";
|
|
5715
|
+
const tmpPath = keyPath + ".tmp";
|
|
5716
|
+
try {
|
|
5717
|
+
if (existsSync12(keyPath)) {
|
|
5718
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
5719
|
+
});
|
|
5720
|
+
}
|
|
5721
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
5722
|
+
await chmod2(tmpPath, 384);
|
|
5723
|
+
await rename(tmpPath, keyPath);
|
|
5724
|
+
} catch (err) {
|
|
5725
|
+
try {
|
|
5726
|
+
await unlink(tmpPath);
|
|
5727
|
+
} catch {
|
|
5728
|
+
}
|
|
5729
|
+
throw err;
|
|
5708
5730
|
}
|
|
5709
|
-
|
|
5710
|
-
await chmod2(keyPath, 384);
|
|
5711
|
-
return "plaintext";
|
|
5731
|
+
return result3;
|
|
5712
5732
|
}
|
|
5713
5733
|
async function getMasterKey() {
|
|
5714
5734
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -13968,10 +13988,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
13968
13988
|
}
|
|
13969
13989
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
13970
13990
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
ccModel += "[1m]";
|
|
13974
|
-
}
|
|
13991
|
+
const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
|
|
13992
|
+
const ccModel = normalizeCcModelName2(agentRtConfig.model);
|
|
13975
13993
|
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
13976
13994
|
}
|
|
13977
13995
|
}
|
|
@@ -22316,6 +22334,7 @@ __export(daemon_orchestration_exports, {
|
|
|
22316
22334
|
REVIEW_NUDGE_COOLDOWN_MS: () => REVIEW_NUDGE_COOLDOWN_MS,
|
|
22317
22335
|
SESSION_CONTEXT_THRESHOLD_PCT: () => SESSION_CONTEXT_THRESHOLD_PCT,
|
|
22318
22336
|
SESSION_TTL_HOURS: () => SESSION_TTL_HOURS,
|
|
22337
|
+
STUCK_TASK_GRACE_MS: () => STUCK_TASK_GRACE_MS,
|
|
22319
22338
|
_resetAutoWakeState: () => _resetAutoWakeState,
|
|
22320
22339
|
checkSessionTTL: () => checkSessionTTL,
|
|
22321
22340
|
classifyTtlKillReason: () => classifyTtlKillReason,
|
|
@@ -22325,12 +22344,14 @@ __export(daemon_orchestration_exports, {
|
|
|
22325
22344
|
createOrphanReaperRealDeps: () => createOrphanReaperRealDeps,
|
|
22326
22345
|
createReviewNudgeRealDeps: () => createReviewNudgeRealDeps,
|
|
22327
22346
|
createSessionTTLRealDeps: () => createSessionTTLRealDeps,
|
|
22347
|
+
createStuckTaskRealDeps: () => createStuckTaskRealDeps,
|
|
22328
22348
|
loadNudgeState: () => loadNudgeState,
|
|
22329
22349
|
pollIdleEmployees: () => pollIdleEmployees,
|
|
22330
22350
|
pollIdleKill: () => pollIdleKill,
|
|
22331
22351
|
pollOrphanedTasks: () => pollOrphanedTasks,
|
|
22332
22352
|
pollReviewNudge: () => pollReviewNudge,
|
|
22333
22353
|
reapOrphanedMcpProcesses: () => reapOrphanedMcpProcesses,
|
|
22354
|
+
releaseStuckTasks: () => releaseStuckTasks,
|
|
22334
22355
|
saveNudgeState: () => saveNudgeState,
|
|
22335
22356
|
shouldAutoWake: () => shouldAutoWake,
|
|
22336
22357
|
shouldKillIdleSession: () => shouldKillIdleSession,
|
|
@@ -22818,6 +22839,86 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
22818
22839
|
}
|
|
22819
22840
|
return woken;
|
|
22820
22841
|
}
|
|
22842
|
+
async function releaseStuckTasks(deps, nowMs = Date.now()) {
|
|
22843
|
+
let liveSessions;
|
|
22844
|
+
try {
|
|
22845
|
+
liveSessions = deps.listTmuxSessions();
|
|
22846
|
+
} catch {
|
|
22847
|
+
return [];
|
|
22848
|
+
}
|
|
22849
|
+
const liveAgents = /* @__PURE__ */ new Set();
|
|
22850
|
+
for (const session of liveSessions) {
|
|
22851
|
+
const agent = deps.parseAgentFromSession(session);
|
|
22852
|
+
if (agent) liveAgents.add(agent);
|
|
22853
|
+
}
|
|
22854
|
+
for (const session of liveSessions) {
|
|
22855
|
+
if (isExeSession(session)) liveAgents.add(session);
|
|
22856
|
+
}
|
|
22857
|
+
let tasks;
|
|
22858
|
+
try {
|
|
22859
|
+
tasks = await deps.queryInProgressTasks();
|
|
22860
|
+
} catch {
|
|
22861
|
+
return [];
|
|
22862
|
+
}
|
|
22863
|
+
const released = [];
|
|
22864
|
+
for (const t of tasks) {
|
|
22865
|
+
if (liveAgents.has(t.agentId)) continue;
|
|
22866
|
+
const updatedMs = new Date(t.updatedAt).getTime();
|
|
22867
|
+
if (isNaN(updatedMs) || nowMs - updatedMs < STUCK_TASK_GRACE_MS) continue;
|
|
22868
|
+
const ageMinutes = Math.round((nowMs - updatedMs) / 6e4);
|
|
22869
|
+
const reason = `[auto-release] Agent "${t.agentId}" session is dead and task has been in_progress for ${ageMinutes}m with no update. Marked blocked for triage.`;
|
|
22870
|
+
try {
|
|
22871
|
+
await deps.markTaskBlocked(t.taskId, reason);
|
|
22872
|
+
released.push(t.taskId);
|
|
22873
|
+
process.stderr.write(
|
|
22874
|
+
`[stuck-release] Task ${t.taskId} (${t.agentId}) \u2014 in_progress for ${ageMinutes}m, agent dead \u2192 blocked
|
|
22875
|
+
`
|
|
22876
|
+
);
|
|
22877
|
+
} catch (err) {
|
|
22878
|
+
process.stderr.write(
|
|
22879
|
+
`[stuck-release] Failed to release ${t.taskId}: ${err instanceof Error ? err.message : String(err)}
|
|
22880
|
+
`
|
|
22881
|
+
);
|
|
22882
|
+
}
|
|
22883
|
+
}
|
|
22884
|
+
return released;
|
|
22885
|
+
}
|
|
22886
|
+
function createStuckTaskRealDeps(getClient2) {
|
|
22887
|
+
return {
|
|
22888
|
+
listTmuxSessions: () => {
|
|
22889
|
+
const { listTmuxSessions: listTmuxSessions2 } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
22890
|
+
return listTmuxSessions2();
|
|
22891
|
+
},
|
|
22892
|
+
queryInProgressTasks: async () => {
|
|
22893
|
+
const client = getClient2();
|
|
22894
|
+
const result3 = await client.execute({
|
|
22895
|
+
sql: `SELECT id, assigned_to, session_scope, updated_at FROM tasks
|
|
22896
|
+
WHERE status = 'in_progress'
|
|
22897
|
+
ORDER BY updated_at ASC`,
|
|
22898
|
+
args: []
|
|
22899
|
+
});
|
|
22900
|
+
return result3.rows.map((r) => ({
|
|
22901
|
+
taskId: String(r.id),
|
|
22902
|
+
agentId: String(r.assigned_to),
|
|
22903
|
+
sessionScope: r.session_scope ? String(r.session_scope) : null,
|
|
22904
|
+
updatedAt: String(r.updated_at)
|
|
22905
|
+
}));
|
|
22906
|
+
},
|
|
22907
|
+
markTaskBlocked: async (taskId, reason) => {
|
|
22908
|
+
const client = getClient2();
|
|
22909
|
+
await client.execute({
|
|
22910
|
+
sql: `UPDATE tasks SET status = 'blocked', result = ?, updated_at = ? WHERE id = ?`,
|
|
22911
|
+
args: [reason, (/* @__PURE__ */ new Date()).toISOString(), taskId]
|
|
22912
|
+
});
|
|
22913
|
+
},
|
|
22914
|
+
parseAgentFromSession: (sessionName) => {
|
|
22915
|
+
const { baseAgentName: baseAgentName2 } = (init_employees(), __toCommonJS(employees_exports));
|
|
22916
|
+
if (!sessionName.includes("-")) return null;
|
|
22917
|
+
const agentPart = sessionName.split("-")[0];
|
|
22918
|
+
return baseAgentName2(agentPart);
|
|
22919
|
+
}
|
|
22920
|
+
};
|
|
22921
|
+
}
|
|
22821
22922
|
function createAutoWakeRealDeps(getClient2, projectDir) {
|
|
22822
22923
|
return {
|
|
22823
22924
|
listTmuxSessions: () => {
|
|
@@ -22910,7 +23011,7 @@ function createOrphanReaperRealDeps() {
|
|
|
22910
23011
|
selfPid: process.pid
|
|
22911
23012
|
};
|
|
22912
23013
|
}
|
|
22913
|
-
var IDLE_NUDGE_DEDUP_MS, SESSION_TTL_HOURS, SESSION_CONTEXT_THRESHOLD_PCT, IDLE_KILL_INTERCOM_ACK_WINDOW_MS, REVIEW_NUDGE_COOLDOWN_MS, NUDGE_STATE_PATH, AUTO_WAKE_COOLDOWN_MS, AUTO_WAKE_MAX_RETRIES, _autoWakeLastSpawn, _autoWakeTaskRetries, ORPHAN_SIGKILL_DELAY_MS, ORPHAN_PATTERNS;
|
|
23014
|
+
var IDLE_NUDGE_DEDUP_MS, SESSION_TTL_HOURS, SESSION_CONTEXT_THRESHOLD_PCT, IDLE_KILL_INTERCOM_ACK_WINDOW_MS, REVIEW_NUDGE_COOLDOWN_MS, NUDGE_STATE_PATH, AUTO_WAKE_COOLDOWN_MS, AUTO_WAKE_MAX_RETRIES, _autoWakeLastSpawn, _autoWakeTaskRetries, STUCK_TASK_GRACE_MS, ORPHAN_SIGKILL_DELAY_MS, ORPHAN_PATTERNS;
|
|
22914
23015
|
var init_daemon_orchestration = __esm({
|
|
22915
23016
|
"src/lib/daemon-orchestration.ts"() {
|
|
22916
23017
|
"use strict";
|
|
@@ -22927,6 +23028,7 @@ var init_daemon_orchestration = __esm({
|
|
|
22927
23028
|
AUTO_WAKE_MAX_RETRIES = 3;
|
|
22928
23029
|
_autoWakeLastSpawn = /* @__PURE__ */ new Map();
|
|
22929
23030
|
_autoWakeTaskRetries = /* @__PURE__ */ new Map();
|
|
23031
|
+
STUCK_TASK_GRACE_MS = 30 * 60 * 1e3;
|
|
22930
23032
|
ORPHAN_SIGKILL_DELAY_MS = 5e3;
|
|
22931
23033
|
ORPHAN_PATTERNS = [
|
|
22932
23034
|
"exe-os/dist/mcp/server.js",
|
|
@@ -25089,6 +25191,7 @@ __export(cloud_sync_exports, {
|
|
|
25089
25191
|
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
25090
25192
|
mergeConfig: () => mergeConfig,
|
|
25091
25193
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
25194
|
+
migrateEndpoint: () => migrateEndpoint,
|
|
25092
25195
|
pushToPostgres: () => pushToPostgres,
|
|
25093
25196
|
recordRosterDeletion: () => recordRosterDeletion
|
|
25094
25197
|
});
|
|
@@ -25259,6 +25362,15 @@ async function fetchWithRetry(url, init) {
|
|
|
25259
25362
|
}
|
|
25260
25363
|
throw lastError;
|
|
25261
25364
|
}
|
|
25365
|
+
function migrateEndpoint(endpoint2) {
|
|
25366
|
+
if (endpoint2 === "https://askexe.com/cloud" || endpoint2 === "https://askexe.com/cloud/") {
|
|
25367
|
+
process.stderr.write(
|
|
25368
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
25369
|
+
);
|
|
25370
|
+
return "https://cloud.askexe.com";
|
|
25371
|
+
}
|
|
25372
|
+
return endpoint2;
|
|
25373
|
+
}
|
|
25262
25374
|
function assertSecureEndpoint(endpoint2) {
|
|
25263
25375
|
if (endpoint2.startsWith("https://")) return;
|
|
25264
25376
|
if (endpoint2.startsWith("http://")) {
|
|
@@ -25396,6 +25508,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
25396
25508
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
25397
25509
|
}
|
|
25398
25510
|
async function cloudSync(config2) {
|
|
25511
|
+
config2 = { ...config2, endpoint: migrateEndpoint(config2.endpoint) };
|
|
25399
25512
|
if (!isSyncCryptoInitialized()) {
|
|
25400
25513
|
try {
|
|
25401
25514
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
@@ -37163,7 +37276,25 @@ async function startMcpHttpServer() {
|
|
|
37163
37276
|
}
|
|
37164
37277
|
const agentId = req.headers["x-agent-id"] || "default";
|
|
37165
37278
|
const agentRole = req.headers["x-agent-role"] || "employee";
|
|
37166
|
-
|
|
37279
|
+
let sessionHint = req.headers["x-exe-session"] || "";
|
|
37280
|
+
if (sessionHint.includes("$(") || sessionHint.includes("#{") || sessionHint.includes("tmux")) {
|
|
37281
|
+
sessionHint = "";
|
|
37282
|
+
}
|
|
37283
|
+
if (!sessionHint) {
|
|
37284
|
+
try {
|
|
37285
|
+
const { getTransport: getTransport2 } = (init_transport(), __toCommonJS(transport_exports));
|
|
37286
|
+
const transport2 = getTransport2();
|
|
37287
|
+
const liveSessions = transport2.listSessions();
|
|
37288
|
+
const agentSessions = liveSessions.filter((s) => s.startsWith(agentId + "-"));
|
|
37289
|
+
if (agentSessions.length === 1) {
|
|
37290
|
+
sessionHint = agentSessions[0];
|
|
37291
|
+
} else {
|
|
37292
|
+
const roots = liveSessions.filter((s) => !s.includes("-") && /^[a-z]+\d*$/.test(s));
|
|
37293
|
+
if (roots.length === 1) sessionHint = roots[0];
|
|
37294
|
+
}
|
|
37295
|
+
} catch {
|
|
37296
|
+
}
|
|
37297
|
+
}
|
|
37167
37298
|
const runtime = inferMcpRuntime({
|
|
37168
37299
|
runtimeHeader: req.headers["x-agent-runtime"] || req.headers["x-runtime"],
|
|
37169
37300
|
userAgent: req.headers["user-agent"],
|
|
@@ -37871,6 +38002,31 @@ function startAutoWake() {
|
|
|
37871
38002
|
process.stderr.write(`[exed] Auto-wake started (every ${AUTO_WAKE_INTERVAL_MS / 1e3}s)
|
|
37872
38003
|
`);
|
|
37873
38004
|
}
|
|
38005
|
+
var STUCK_TASK_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
38006
|
+
function startStuckTaskRelease() {
|
|
38007
|
+
const tick = async () => {
|
|
38008
|
+
fired("stuck_task_release");
|
|
38009
|
+
if (!await ensureStoreForPolling()) return;
|
|
38010
|
+
try {
|
|
38011
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
38012
|
+
const { releaseStuckTasks: releaseStuckTasks2, createStuckTaskRealDeps: createStuckTaskRealDeps2 } = await Promise.resolve().then(() => (init_daemon_orchestration(), daemon_orchestration_exports));
|
|
38013
|
+
const deps = createStuckTaskRealDeps2(getClient2);
|
|
38014
|
+
const released = await releaseStuckTasks2(deps);
|
|
38015
|
+
if (released.length > 0) {
|
|
38016
|
+
acted("stuck_task_release");
|
|
38017
|
+
process.stderr.write(`[exed] Stuck-release: ${released.length} task(s) moved to blocked
|
|
38018
|
+
`);
|
|
38019
|
+
}
|
|
38020
|
+
} catch (err) {
|
|
38021
|
+
process.stderr.write(`[exed] Stuck-release error: ${err instanceof Error ? err.message : String(err)}
|
|
38022
|
+
`);
|
|
38023
|
+
}
|
|
38024
|
+
};
|
|
38025
|
+
const timer = setInterval(() => void tick(), STUCK_TASK_CHECK_INTERVAL_MS);
|
|
38026
|
+
timer.unref();
|
|
38027
|
+
process.stderr.write(`[exed] Stuck-task release started (every ${STUCK_TASK_CHECK_INTERVAL_MS / 1e3}s)
|
|
38028
|
+
`);
|
|
38029
|
+
}
|
|
37874
38030
|
var TOTAL_MEM_GB = os24.totalmem() / 1024 ** 3;
|
|
37875
38031
|
var RSS_WARN_BYTES = Number(process.env.EXE_RSS_WARN_MB) * 1024 * 1024 || (TOTAL_MEM_GB >= 64 ? 6 * 1024 ** 3 : TOTAL_MEM_GB >= 32 ? 4 * 1024 ** 3 : TOTAL_MEM_GB >= 16 ? 2.5 * 1024 ** 3 : 1.5 * 1024 ** 3);
|
|
37876
38032
|
var RSS_RESTART_BYTES = Number(process.env.EXE_RSS_RESTART_MB) * 1024 * 1024 || (TOTAL_MEM_GB >= 64 ? 8 * 1024 ** 3 : TOTAL_MEM_GB >= 32 ? 6 * 1024 ** 3 : TOTAL_MEM_GB >= 16 ? 4 * 1024 ** 3 : 3 * 1024 ** 3);
|
|
@@ -38211,6 +38367,7 @@ try {
|
|
|
38211
38367
|
startOrphanReaper();
|
|
38212
38368
|
startAgentStats();
|
|
38213
38369
|
startAutoWake();
|
|
38370
|
+
startStuckTaskRelease();
|
|
38214
38371
|
startGraphExtraction();
|
|
38215
38372
|
startMemoryQueueDrain();
|
|
38216
38373
|
startIntercomQueueDrain();
|
|
@@ -3314,7 +3314,7 @@ var init_database = __esm({
|
|
|
3314
3314
|
});
|
|
3315
3315
|
|
|
3316
3316
|
// src/lib/keychain.ts
|
|
3317
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3317
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
3318
3318
|
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
3319
3319
|
import { execSync as execSync3 } from "child_process";
|
|
3320
3320
|
import path6 from "path";
|
|
@@ -3349,12 +3349,14 @@ function linuxSecretAvailable() {
|
|
|
3349
3349
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
3350
3350
|
if (process.platform !== "linux") return false;
|
|
3351
3351
|
try {
|
|
3352
|
-
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3353
3352
|
const st = statSync3(keyPath);
|
|
3354
3353
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3354
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3355
3355
|
if (uid === 0) return true;
|
|
3356
3356
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
3357
|
-
|
|
3357
|
+
if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
|
|
3358
|
+
if (!linuxSecretAvailable()) return true;
|
|
3359
|
+
return false;
|
|
3358
3360
|
} catch {
|
|
3359
3361
|
return false;
|
|
3360
3362
|
}
|
|
@@ -3504,15 +3506,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
3504
3506
|
await mkdir3(dir, { recursive: true });
|
|
3505
3507
|
const keyPath = getKeyPath();
|
|
3506
3508
|
const machineKey = deriveMachineKey();
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3509
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
3510
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
3511
|
+
const tmpPath = keyPath + ".tmp";
|
|
3512
|
+
try {
|
|
3513
|
+
if (existsSync7(keyPath)) {
|
|
3514
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
3515
|
+
});
|
|
3516
|
+
}
|
|
3517
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
3518
|
+
await chmod2(tmpPath, 384);
|
|
3519
|
+
await rename(tmpPath, keyPath);
|
|
3520
|
+
} catch (err) {
|
|
3521
|
+
try {
|
|
3522
|
+
await unlink(tmpPath);
|
|
3523
|
+
} catch {
|
|
3524
|
+
}
|
|
3525
|
+
throw err;
|
|
3526
|
+
}
|
|
3527
|
+
return result;
|
|
3516
3528
|
}
|
|
3517
3529
|
async function getMasterKey() {
|
|
3518
3530
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|