@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/bin/cli.js
CHANGED
|
@@ -368,6 +368,7 @@ __export(agent_config_exports, {
|
|
|
368
368
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
369
369
|
getAgentRuntime: () => getAgentRuntime,
|
|
370
370
|
loadAgentConfig: () => loadAgentConfig,
|
|
371
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
371
372
|
saveAgentConfig: () => saveAgentConfig,
|
|
372
373
|
setAgentMcps: () => setAgentMcps,
|
|
373
374
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -396,6 +397,13 @@ function getAgentRuntime(agentId) {
|
|
|
396
397
|
if (orgDefault) return orgDefault;
|
|
397
398
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
398
399
|
}
|
|
400
|
+
function normalizeCcModelName(model) {
|
|
401
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
402
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
403
|
+
ccModel += "[1m]";
|
|
404
|
+
}
|
|
405
|
+
return ccModel;
|
|
406
|
+
}
|
|
399
407
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
400
408
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
401
409
|
if (!knownModels) {
|
|
@@ -896,7 +904,7 @@ function readOrCreateDaemonToken(homeDir = os5.homedir()) {
|
|
|
896
904
|
function buildMcpHttpHeaders(homeDir = os5.homedir(), opts = {}) {
|
|
897
905
|
const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
|
|
898
906
|
const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
899
|
-
const sessionName = opts.useShellPlaceholders ? "
|
|
907
|
+
const sessionName = opts.useShellPlaceholders ? "" : process.env.EXE_SESSION_NAME ?? "";
|
|
900
908
|
const headers = {
|
|
901
909
|
Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
|
|
902
910
|
"X-Agent-Id": agentId,
|
|
@@ -2555,7 +2563,7 @@ __export(keychain_exports, {
|
|
|
2555
2563
|
importMnemonic: () => importMnemonic,
|
|
2556
2564
|
setMasterKey: () => setMasterKey
|
|
2557
2565
|
});
|
|
2558
|
-
import { readFile as readFile4, writeFile as writeFile4, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
2566
|
+
import { readFile as readFile4, writeFile as writeFile4, unlink, mkdir as mkdir4, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
2559
2567
|
import { existsSync as existsSync10, statSync } from "fs";
|
|
2560
2568
|
import { execSync as execSync3 } from "child_process";
|
|
2561
2569
|
import path9 from "path";
|
|
@@ -2590,12 +2598,14 @@ function linuxSecretAvailable() {
|
|
|
2590
2598
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
2591
2599
|
if (process.platform !== "linux") return false;
|
|
2592
2600
|
try {
|
|
2593
|
-
const uid = typeof os8.userInfo().uid === "number" ? os8.userInfo().uid : -1;
|
|
2594
2601
|
const st = statSync(keyPath);
|
|
2595
2602
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
2603
|
+
const uid = typeof os8.userInfo().uid === "number" ? os8.userInfo().uid : -1;
|
|
2596
2604
|
if (uid === 0) return true;
|
|
2597
2605
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
2598
|
-
|
|
2606
|
+
if (exeOsDir && path9.resolve(keyPath).startsWith(path9.resolve(exeOsDir) + path9.sep)) return true;
|
|
2607
|
+
if (!linuxSecretAvailable()) return true;
|
|
2608
|
+
return false;
|
|
2599
2609
|
} catch {
|
|
2600
2610
|
return false;
|
|
2601
2611
|
}
|
|
@@ -2745,15 +2755,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
2745
2755
|
await mkdir4(dir, { recursive: true });
|
|
2746
2756
|
const keyPath = getKeyPath();
|
|
2747
2757
|
const machineKey = deriveMachineKey();
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2758
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
2759
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
2760
|
+
const tmpPath = keyPath + ".tmp";
|
|
2761
|
+
try {
|
|
2762
|
+
if (existsSync10(keyPath)) {
|
|
2763
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
await writeFile4(tmpPath, content, "utf-8");
|
|
2767
|
+
await chmod2(tmpPath, 384);
|
|
2768
|
+
await rename(tmpPath, keyPath);
|
|
2769
|
+
} catch (err) {
|
|
2770
|
+
try {
|
|
2771
|
+
await unlink(tmpPath);
|
|
2772
|
+
} catch {
|
|
2773
|
+
}
|
|
2774
|
+
throw err;
|
|
2753
2775
|
}
|
|
2754
|
-
|
|
2755
|
-
await chmod2(keyPath, 384);
|
|
2756
|
-
return "plaintext";
|
|
2776
|
+
return result;
|
|
2757
2777
|
}
|
|
2758
2778
|
async function getMasterKey() {
|
|
2759
2779
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -6999,6 +7019,7 @@ __export(cloud_sync_exports, {
|
|
|
6999
7019
|
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
7000
7020
|
mergeConfig: () => mergeConfig,
|
|
7001
7021
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
7022
|
+
migrateEndpoint: () => migrateEndpoint,
|
|
7002
7023
|
pushToPostgres: () => pushToPostgres,
|
|
7003
7024
|
recordRosterDeletion: () => recordRosterDeletion
|
|
7004
7025
|
});
|
|
@@ -7169,6 +7190,15 @@ async function fetchWithRetry(url, init) {
|
|
|
7169
7190
|
}
|
|
7170
7191
|
throw lastError;
|
|
7171
7192
|
}
|
|
7193
|
+
function migrateEndpoint(endpoint) {
|
|
7194
|
+
if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
|
|
7195
|
+
process.stderr.write(
|
|
7196
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
7197
|
+
);
|
|
7198
|
+
return "https://cloud.askexe.com";
|
|
7199
|
+
}
|
|
7200
|
+
return endpoint;
|
|
7201
|
+
}
|
|
7172
7202
|
function assertSecureEndpoint(endpoint) {
|
|
7173
7203
|
if (endpoint.startsWith("https://")) return;
|
|
7174
7204
|
if (endpoint.startsWith("http://")) {
|
|
@@ -7306,6 +7336,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
7306
7336
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
7307
7337
|
}
|
|
7308
7338
|
async function cloudSync(config) {
|
|
7339
|
+
config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
|
|
7309
7340
|
if (!isSyncCryptoInitialized()) {
|
|
7310
7341
|
try {
|
|
7311
7342
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
@@ -17135,10 +17166,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
17135
17166
|
}
|
|
17136
17167
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
17137
17168
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
ccModel += "[1m]";
|
|
17141
|
-
}
|
|
17169
|
+
const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
|
|
17170
|
+
const ccModel = normalizeCcModelName2(agentRtConfig.model);
|
|
17142
17171
|
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
17143
17172
|
}
|
|
17144
17173
|
}
|
|
@@ -20483,6 +20512,24 @@ async function runSetupWizard(opts = {}) {
|
|
|
20483
20512
|
log("");
|
|
20484
20513
|
log("=== exe-os Setup ===");
|
|
20485
20514
|
log("");
|
|
20515
|
+
if (process.platform === "darwin") {
|
|
20516
|
+
const currentShell = process.env.SHELL ?? "";
|
|
20517
|
+
if (currentShell.includes("bash")) {
|
|
20518
|
+
log(" \u26A0 Your default shell is bash.");
|
|
20519
|
+
log(" macOS uses zsh by default since Catalina (2019).");
|
|
20520
|
+
log(" exe-os works with bash, but switching to zsh is recommended:");
|
|
20521
|
+
log(" chsh -s /bin/zsh");
|
|
20522
|
+
log(" Then restart your terminal.");
|
|
20523
|
+
log("");
|
|
20524
|
+
const cont = await ask3(rl, " Continue with bash? (y/n, default: y): ");
|
|
20525
|
+
if (cont.toLowerCase() === "n") {
|
|
20526
|
+
log(" Run `chsh -s /bin/zsh`, restart your terminal, then run setup again.");
|
|
20527
|
+
rl.close();
|
|
20528
|
+
return;
|
|
20529
|
+
}
|
|
20530
|
+
log("");
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20486
20533
|
log("What are you setting up?");
|
|
20487
20534
|
log("");
|
|
20488
20535
|
log(" [1] First device / brand new Exe OS memory");
|
|
@@ -21155,7 +21202,7 @@ var init_setup_wizard = __esm({
|
|
|
21155
21202
|
});
|
|
21156
21203
|
|
|
21157
21204
|
// src/lib/update-backup.ts
|
|
21158
|
-
import { copyFile, readFile as readFile6, readdir as readdir3, writeFile as writeFile7, rm as rm2, mkdir as mkdir7, cp } from "fs/promises";
|
|
21205
|
+
import { copyFile as copyFile2, readFile as readFile6, readdir as readdir3, writeFile as writeFile7, rm as rm2, mkdir as mkdir7, cp } from "fs/promises";
|
|
21159
21206
|
import { existsSync as existsSync36 } from "fs";
|
|
21160
21207
|
import path42 from "path";
|
|
21161
21208
|
import os20 from "os";
|
|
@@ -21191,7 +21238,7 @@ async function createUpdateBackup(currentVersion, dataDir2, homeDir = os20.homed
|
|
|
21191
21238
|
if (!existsSync36(src)) continue;
|
|
21192
21239
|
const dest = path42.join(backupDir, target.name);
|
|
21193
21240
|
if (target.type === "file") {
|
|
21194
|
-
await
|
|
21241
|
+
await copyFile2(src, dest);
|
|
21195
21242
|
} else {
|
|
21196
21243
|
await cp(src, dest, { recursive: true });
|
|
21197
21244
|
}
|
|
@@ -21202,7 +21249,7 @@ async function createUpdateBackup(currentVersion, dataDir2, homeDir = os20.homed
|
|
|
21202
21249
|
if (entry.isFile() && entry.name.endsWith(".db") && entry.name !== BACKUP_DIR_NAME) {
|
|
21203
21250
|
const src = path42.join(dir, entry.name);
|
|
21204
21251
|
const dest = path42.join(backupDir, entry.name);
|
|
21205
|
-
await
|
|
21252
|
+
await copyFile2(src, dest);
|
|
21206
21253
|
backedUpFiles.push(entry.name);
|
|
21207
21254
|
}
|
|
21208
21255
|
}
|
|
@@ -21211,7 +21258,7 @@ async function createUpdateBackup(currentVersion, dataDir2, homeDir = os20.homed
|
|
|
21211
21258
|
for (const target of externalBackupTargets(homeDir)) {
|
|
21212
21259
|
if (!existsSync36(target.path)) continue;
|
|
21213
21260
|
await mkdir7(externalDir, { recursive: true });
|
|
21214
|
-
await
|
|
21261
|
+
await copyFile2(target.path, path42.join(externalDir, target.name));
|
|
21215
21262
|
externalFiles.push(target);
|
|
21216
21263
|
}
|
|
21217
21264
|
const manifest = {
|
|
@@ -21246,14 +21293,14 @@ async function restoreFromBackup(dataDir2) {
|
|
|
21246
21293
|
if (stat2.isDirectory()) {
|
|
21247
21294
|
await cp(src, dest, { recursive: true, force: true });
|
|
21248
21295
|
} else {
|
|
21249
|
-
await
|
|
21296
|
+
await copyFile2(src, dest);
|
|
21250
21297
|
}
|
|
21251
21298
|
}
|
|
21252
21299
|
for (const external of manifest.externalFiles ?? []) {
|
|
21253
21300
|
const src = path42.join(backupDir, "external", external.name);
|
|
21254
21301
|
if (!existsSync36(src)) continue;
|
|
21255
21302
|
await mkdir7(path42.dirname(external.path), { recursive: true });
|
|
21256
|
-
await
|
|
21303
|
+
await copyFile2(src, external.path);
|
|
21257
21304
|
}
|
|
21258
21305
|
return manifest;
|
|
21259
21306
|
}
|
|
@@ -32121,6 +32168,33 @@ var init_dangerous_patterns = __esm({
|
|
|
32121
32168
|
regex: /\bkill\s+-9\b/,
|
|
32122
32169
|
severity: "warning",
|
|
32123
32170
|
reason: "Force kill signal"
|
|
32171
|
+
},
|
|
32172
|
+
// MCP bypass — agents must use MCP tools, never access the DB directly.
|
|
32173
|
+
// These patterns catch attempts to work around a disconnected MCP server.
|
|
32174
|
+
{
|
|
32175
|
+
regex: /\bsqlite3\b.*\bmemories\.db\b/,
|
|
32176
|
+
severity: "critical",
|
|
32177
|
+
reason: "Direct SQLite access bypasses MCP contract boundary \u2014 use MCP tools"
|
|
32178
|
+
},
|
|
32179
|
+
{
|
|
32180
|
+
regex: /\bsqlite3\b.*\.exe-os\b/,
|
|
32181
|
+
severity: "critical",
|
|
32182
|
+
reason: "Direct SQLite access to exe-os database \u2014 use MCP tools"
|
|
32183
|
+
},
|
|
32184
|
+
{
|
|
32185
|
+
regex: /\bnode\s+-e\b.*\b(better-sqlite3|libsql|sqlite3)\b/,
|
|
32186
|
+
severity: "critical",
|
|
32187
|
+
reason: "Inline Node.js script accessing SQLite directly \u2014 use MCP tools"
|
|
32188
|
+
},
|
|
32189
|
+
{
|
|
32190
|
+
regex: /\brequire\s*\(\s*['"].*memories\.db['"]\s*\)/,
|
|
32191
|
+
severity: "critical",
|
|
32192
|
+
reason: "Direct require of memories database \u2014 use MCP tools"
|
|
32193
|
+
},
|
|
32194
|
+
{
|
|
32195
|
+
regex: /\bcat\b.*\bmemories\.db\b/,
|
|
32196
|
+
severity: "warning",
|
|
32197
|
+
reason: "Reading raw database file \u2014 encrypted data, use MCP tools instead"
|
|
32124
32198
|
}
|
|
32125
32199
|
];
|
|
32126
32200
|
}
|
package/dist/bin/exe-agent.js
CHANGED
|
@@ -1861,6 +1861,33 @@ var DANGEROUS_PATTERNS = [
|
|
|
1861
1861
|
regex: /\bkill\s+-9\b/,
|
|
1862
1862
|
severity: "warning",
|
|
1863
1863
|
reason: "Force kill signal"
|
|
1864
|
+
},
|
|
1865
|
+
// MCP bypass — agents must use MCP tools, never access the DB directly.
|
|
1866
|
+
// These patterns catch attempts to work around a disconnected MCP server.
|
|
1867
|
+
{
|
|
1868
|
+
regex: /\bsqlite3\b.*\bmemories\.db\b/,
|
|
1869
|
+
severity: "critical",
|
|
1870
|
+
reason: "Direct SQLite access bypasses MCP contract boundary \u2014 use MCP tools"
|
|
1871
|
+
},
|
|
1872
|
+
{
|
|
1873
|
+
regex: /\bsqlite3\b.*\.exe-os\b/,
|
|
1874
|
+
severity: "critical",
|
|
1875
|
+
reason: "Direct SQLite access to exe-os database \u2014 use MCP tools"
|
|
1876
|
+
},
|
|
1877
|
+
{
|
|
1878
|
+
regex: /\bnode\s+-e\b.*\b(better-sqlite3|libsql|sqlite3)\b/,
|
|
1879
|
+
severity: "critical",
|
|
1880
|
+
reason: "Inline Node.js script accessing SQLite directly \u2014 use MCP tools"
|
|
1881
|
+
},
|
|
1882
|
+
{
|
|
1883
|
+
regex: /\brequire\s*\(\s*['"].*memories\.db['"]\s*\)/,
|
|
1884
|
+
severity: "critical",
|
|
1885
|
+
reason: "Direct require of memories database \u2014 use MCP tools"
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
regex: /\bcat\b.*\bmemories\.db\b/,
|
|
1889
|
+
severity: "warning",
|
|
1890
|
+
reason: "Reading raw database file \u2014 encrypted data, use MCP tools instead"
|
|
1864
1891
|
}
|
|
1865
1892
|
];
|
|
1866
1893
|
function checkDangerousPatterns(command) {
|
package/dist/bin/exe-assign.js
CHANGED
|
@@ -4681,7 +4681,7 @@ init_memory();
|
|
|
4681
4681
|
init_database();
|
|
4682
4682
|
|
|
4683
4683
|
// src/lib/keychain.ts
|
|
4684
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4684
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
4685
4685
|
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
4686
4686
|
import { execSync as execSync3 } from "child_process";
|
|
4687
4687
|
import path6 from "path";
|
|
@@ -4720,12 +4720,14 @@ function linuxSecretAvailable() {
|
|
|
4720
4720
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
4721
4721
|
if (process.platform !== "linux") return false;
|
|
4722
4722
|
try {
|
|
4723
|
-
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4724
4723
|
const st = statSync3(keyPath);
|
|
4725
4724
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4725
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4726
4726
|
if (uid === 0) return true;
|
|
4727
4727
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
4728
|
-
|
|
4728
|
+
if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
|
|
4729
|
+
if (!linuxSecretAvailable()) return true;
|
|
4730
|
+
return false;
|
|
4729
4731
|
} catch {
|
|
4730
4732
|
return false;
|
|
4731
4733
|
}
|
|
@@ -4876,15 +4878,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
4876
4878
|
await mkdir3(dir, { recursive: true });
|
|
4877
4879
|
const keyPath = getKeyPath();
|
|
4878
4880
|
const machineKey = deriveMachineKey();
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4881
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
4882
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
4883
|
+
const tmpPath = keyPath + ".tmp";
|
|
4884
|
+
try {
|
|
4885
|
+
if (existsSync7(keyPath)) {
|
|
4886
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
4887
|
+
});
|
|
4888
|
+
}
|
|
4889
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
4890
|
+
await chmod2(tmpPath, 384);
|
|
4891
|
+
await rename(tmpPath, keyPath);
|
|
4892
|
+
} catch (err) {
|
|
4893
|
+
try {
|
|
4894
|
+
await unlink(tmpPath);
|
|
4895
|
+
} catch {
|
|
4896
|
+
}
|
|
4897
|
+
throw err;
|
|
4898
|
+
}
|
|
4899
|
+
return result;
|
|
4888
4900
|
}
|
|
4889
4901
|
async function getMasterKey() {
|
|
4890
4902
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
package/dist/bin/exe-boot.js
CHANGED
|
@@ -368,6 +368,7 @@ __export(agent_config_exports, {
|
|
|
368
368
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
369
369
|
getAgentRuntime: () => getAgentRuntime,
|
|
370
370
|
loadAgentConfig: () => loadAgentConfig,
|
|
371
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
371
372
|
saveAgentConfig: () => saveAgentConfig,
|
|
372
373
|
setAgentMcps: () => setAgentMcps,
|
|
373
374
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -396,6 +397,13 @@ function getAgentRuntime(agentId) {
|
|
|
396
397
|
if (orgDefault) return orgDefault;
|
|
397
398
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
398
399
|
}
|
|
400
|
+
function normalizeCcModelName(model) {
|
|
401
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
402
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
403
|
+
ccModel += "[1m]";
|
|
404
|
+
}
|
|
405
|
+
return ccModel;
|
|
406
|
+
}
|
|
399
407
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
400
408
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
401
409
|
if (!knownModels) {
|
|
@@ -4060,7 +4068,7 @@ __export(keychain_exports, {
|
|
|
4060
4068
|
importMnemonic: () => importMnemonic,
|
|
4061
4069
|
setMasterKey: () => setMasterKey
|
|
4062
4070
|
});
|
|
4063
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4071
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
4064
4072
|
import { existsSync as existsSync8, statSync as statSync3 } from "fs";
|
|
4065
4073
|
import { execSync as execSync3 } from "child_process";
|
|
4066
4074
|
import path7 from "path";
|
|
@@ -4095,12 +4103,14 @@ function linuxSecretAvailable() {
|
|
|
4095
4103
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
4096
4104
|
if (process.platform !== "linux") return false;
|
|
4097
4105
|
try {
|
|
4098
|
-
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4099
4106
|
const st = statSync3(keyPath);
|
|
4100
4107
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4108
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4101
4109
|
if (uid === 0) return true;
|
|
4102
4110
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
4103
|
-
|
|
4111
|
+
if (exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep)) return true;
|
|
4112
|
+
if (!linuxSecretAvailable()) return true;
|
|
4113
|
+
return false;
|
|
4104
4114
|
} catch {
|
|
4105
4115
|
return false;
|
|
4106
4116
|
}
|
|
@@ -4250,15 +4260,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
4250
4260
|
await mkdir3(dir, { recursive: true });
|
|
4251
4261
|
const keyPath = getKeyPath();
|
|
4252
4262
|
const machineKey = deriveMachineKey();
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4263
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
4264
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
4265
|
+
const tmpPath = keyPath + ".tmp";
|
|
4266
|
+
try {
|
|
4267
|
+
if (existsSync8(keyPath)) {
|
|
4268
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4271
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
4272
|
+
await chmod2(tmpPath, 384);
|
|
4273
|
+
await rename(tmpPath, keyPath);
|
|
4274
|
+
} catch (err) {
|
|
4275
|
+
try {
|
|
4276
|
+
await unlink(tmpPath);
|
|
4277
|
+
} catch {
|
|
4278
|
+
}
|
|
4279
|
+
throw err;
|
|
4258
4280
|
}
|
|
4259
|
-
|
|
4260
|
-
await chmod2(keyPath, 384);
|
|
4261
|
-
return "plaintext";
|
|
4281
|
+
return result;
|
|
4262
4282
|
}
|
|
4263
4283
|
async function getMasterKey() {
|
|
4264
4284
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -9401,10 +9421,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9401
9421
|
}
|
|
9402
9422
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
9403
9423
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
ccModel += "[1m]";
|
|
9407
|
-
}
|
|
9424
|
+
const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
|
|
9425
|
+
const ccModel = normalizeCcModelName2(agentRtConfig.model);
|
|
9408
9426
|
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
9409
9427
|
}
|
|
9410
9428
|
}
|
|
@@ -10151,6 +10169,7 @@ __export(cloud_sync_exports, {
|
|
|
10151
10169
|
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
10152
10170
|
mergeConfig: () => mergeConfig,
|
|
10153
10171
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
10172
|
+
migrateEndpoint: () => migrateEndpoint,
|
|
10154
10173
|
pushToPostgres: () => pushToPostgres,
|
|
10155
10174
|
recordRosterDeletion: () => recordRosterDeletion
|
|
10156
10175
|
});
|
|
@@ -10321,6 +10340,15 @@ async function fetchWithRetry(url, init) {
|
|
|
10321
10340
|
}
|
|
10322
10341
|
throw lastError;
|
|
10323
10342
|
}
|
|
10343
|
+
function migrateEndpoint(endpoint) {
|
|
10344
|
+
if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
|
|
10345
|
+
process.stderr.write(
|
|
10346
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
10347
|
+
);
|
|
10348
|
+
return "https://cloud.askexe.com";
|
|
10349
|
+
}
|
|
10350
|
+
return endpoint;
|
|
10351
|
+
}
|
|
10324
10352
|
function assertSecureEndpoint(endpoint) {
|
|
10325
10353
|
if (endpoint.startsWith("https://")) return;
|
|
10326
10354
|
if (endpoint.startsWith("http://")) {
|
|
@@ -10458,6 +10486,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
10458
10486
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
10459
10487
|
}
|
|
10460
10488
|
async function cloudSync(config) {
|
|
10489
|
+
config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
|
|
10461
10490
|
if (!isSyncCryptoInitialized()) {
|
|
10462
10491
|
try {
|
|
10463
10492
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
package/dist/bin/exe-call.js
CHANGED
|
@@ -1263,6 +1263,7 @@ __export(agent_config_exports, {
|
|
|
1263
1263
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
1264
1264
|
getAgentRuntime: () => getAgentRuntime,
|
|
1265
1265
|
loadAgentConfig: () => loadAgentConfig,
|
|
1266
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
1266
1267
|
saveAgentConfig: () => saveAgentConfig,
|
|
1267
1268
|
setAgentMcps: () => setAgentMcps,
|
|
1268
1269
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -1291,6 +1292,13 @@ function getAgentRuntime(agentId) {
|
|
|
1291
1292
|
if (orgDefault) return orgDefault;
|
|
1292
1293
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
1293
1294
|
}
|
|
1295
|
+
function normalizeCcModelName(model) {
|
|
1296
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
1297
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
1298
|
+
ccModel += "[1m]";
|
|
1299
|
+
}
|
|
1300
|
+
return ccModel;
|
|
1301
|
+
}
|
|
1294
1302
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
1295
1303
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
1296
1304
|
if (!knownModels) {
|
package/dist/bin/exe-cloud.js
CHANGED
|
@@ -25,7 +25,7 @@ __export(keychain_exports, {
|
|
|
25
25
|
importMnemonic: () => importMnemonic,
|
|
26
26
|
setMasterKey: () => setMasterKey
|
|
27
27
|
});
|
|
28
|
-
import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
28
|
+
import { readFile, writeFile, unlink, mkdir, chmod, rename, copyFile } from "fs/promises";
|
|
29
29
|
import { existsSync, statSync } from "fs";
|
|
30
30
|
import { execSync } from "child_process";
|
|
31
31
|
import path from "path";
|
|
@@ -60,12 +60,14 @@ function linuxSecretAvailable() {
|
|
|
60
60
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
61
61
|
if (process.platform !== "linux") return false;
|
|
62
62
|
try {
|
|
63
|
-
const uid = typeof os.userInfo().uid === "number" ? os.userInfo().uid : -1;
|
|
64
63
|
const st = statSync(keyPath);
|
|
65
64
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
65
|
+
const uid = typeof os.userInfo().uid === "number" ? os.userInfo().uid : -1;
|
|
66
66
|
if (uid === 0) return true;
|
|
67
67
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
68
|
-
|
|
68
|
+
if (exeOsDir && path.resolve(keyPath).startsWith(path.resolve(exeOsDir) + path.sep)) return true;
|
|
69
|
+
if (!linuxSecretAvailable()) return true;
|
|
70
|
+
return false;
|
|
69
71
|
} catch {
|
|
70
72
|
return false;
|
|
71
73
|
}
|
|
@@ -215,15 +217,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
215
217
|
await mkdir(dir, { recursive: true });
|
|
216
218
|
const keyPath = getKeyPath();
|
|
217
219
|
const machineKey = deriveMachineKey();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
221
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
222
|
+
const tmpPath = keyPath + ".tmp";
|
|
223
|
+
try {
|
|
224
|
+
if (existsSync(keyPath)) {
|
|
225
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
await writeFile(tmpPath, content, "utf-8");
|
|
229
|
+
await chmod(tmpPath, 384);
|
|
230
|
+
await rename(tmpPath, keyPath);
|
|
231
|
+
} catch (err) {
|
|
232
|
+
try {
|
|
233
|
+
await unlink(tmpPath);
|
|
234
|
+
} catch {
|
|
235
|
+
}
|
|
236
|
+
throw err;
|
|
223
237
|
}
|
|
224
|
-
|
|
225
|
-
await chmod(keyPath, 384);
|
|
226
|
-
return "plaintext";
|
|
238
|
+
return result;
|
|
227
239
|
}
|
|
228
240
|
async function getMasterKey() {
|
|
229
241
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -4761,6 +4773,7 @@ __export(cloud_sync_exports, {
|
|
|
4761
4773
|
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
4762
4774
|
mergeConfig: () => mergeConfig,
|
|
4763
4775
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
4776
|
+
migrateEndpoint: () => migrateEndpoint,
|
|
4764
4777
|
pushToPostgres: () => pushToPostgres,
|
|
4765
4778
|
recordRosterDeletion: () => recordRosterDeletion
|
|
4766
4779
|
});
|
|
@@ -4931,6 +4944,15 @@ async function fetchWithRetry(url, init) {
|
|
|
4931
4944
|
}
|
|
4932
4945
|
throw lastError;
|
|
4933
4946
|
}
|
|
4947
|
+
function migrateEndpoint(endpoint) {
|
|
4948
|
+
if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
|
|
4949
|
+
process.stderr.write(
|
|
4950
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
4951
|
+
);
|
|
4952
|
+
return "https://cloud.askexe.com";
|
|
4953
|
+
}
|
|
4954
|
+
return endpoint;
|
|
4955
|
+
}
|
|
4934
4956
|
function assertSecureEndpoint(endpoint) {
|
|
4935
4957
|
if (endpoint.startsWith("https://")) return;
|
|
4936
4958
|
if (endpoint.startsWith("http://")) {
|
|
@@ -5068,6 +5090,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
5068
5090
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
5069
5091
|
}
|
|
5070
5092
|
async function cloudSync(config) {
|
|
5093
|
+
config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
|
|
5071
5094
|
if (!isSyncCryptoInitialized()) {
|
|
5072
5095
|
try {
|
|
5073
5096
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|