@askexenow/exe-os 0.9.113 → 0.9.115
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 +36 -12
- package/dist/bin/agentic-reflection-backfill.js +36 -12
- package/dist/bin/agentic-semantic-label.js +36 -12
- package/dist/bin/backfill-conversations.js +36 -12
- package/dist/bin/backfill-responses.js +36 -12
- package/dist/bin/backfill-vectors.js +36 -12
- package/dist/bin/bulk-sync-postgres.js +36 -12
- package/dist/bin/cleanup-stale-review-tasks.js +470 -113
- package/dist/bin/cli.js +413 -62
- package/dist/bin/exe-agent.js +27 -0
- package/dist/bin/exe-assign.js +36 -12
- package/dist/bin/exe-boot.js +246 -54
- package/dist/bin/exe-call.js +8 -0
- package/dist/bin/exe-cloud.js +47 -12
- package/dist/bin/exe-dispatch.js +348 -53
- package/dist/bin/exe-doctor.js +51 -13
- package/dist/bin/exe-export-behaviors.js +37 -12
- package/dist/bin/exe-forget.js +36 -12
- package/dist/bin/exe-gateway.js +348 -53
- package/dist/bin/exe-heartbeat.js +471 -113
- package/dist/bin/exe-kill.js +36 -12
- package/dist/bin/exe-launch-agent.js +117 -18
- package/dist/bin/exe-new-employee.js +9 -1
- package/dist/bin/exe-pending-messages.js +452 -95
- package/dist/bin/exe-pending-notifications.js +452 -95
- package/dist/bin/exe-pending-reviews.js +452 -95
- package/dist/bin/exe-rename.js +36 -12
- package/dist/bin/exe-review.js +36 -12
- package/dist/bin/exe-search.js +37 -12
- package/dist/bin/exe-session-cleanup.js +348 -53
- package/dist/bin/exe-settings.js +12 -0
- package/dist/bin/exe-start-codex.js +46 -13
- package/dist/bin/exe-start-opencode.js +46 -13
- package/dist/bin/exe-status.js +460 -114
- package/dist/bin/exe-support.js +12 -0
- package/dist/bin/exe-team.js +36 -12
- package/dist/bin/git-sweep.js +348 -53
- package/dist/bin/graph-backfill.js +36 -12
- package/dist/bin/graph-export.js +36 -12
- package/dist/bin/install.js +9 -1
- package/dist/bin/intercom-check.js +255 -53
- package/dist/bin/scan-tasks.js +348 -53
- package/dist/bin/setup.js +74 -12
- package/dist/bin/shard-migrate.js +36 -12
- package/dist/gateway/index.js +348 -53
- package/dist/hooks/bug-report-worker.js +348 -53
- package/dist/hooks/codex-stop-task-finalizer.js +308 -37
- package/dist/hooks/commit-complete.js +348 -53
- package/dist/hooks/error-recall.js +37 -12
- package/dist/hooks/ingest.js +363 -54
- package/dist/hooks/instructions-loaded.js +36 -12
- package/dist/hooks/notification.js +36 -12
- package/dist/hooks/post-compact.js +426 -72
- package/dist/hooks/post-tool-combined.js +501 -146
- package/dist/hooks/pre-compact.js +348 -53
- package/dist/hooks/pre-tool-use.js +92 -13
- package/dist/hooks/prompt-submit.js +348 -53
- package/dist/hooks/session-end.js +158 -53
- package/dist/hooks/session-start.js +66 -13
- package/dist/hooks/stop.js +420 -72
- package/dist/hooks/subagent-stop.js +419 -72
- package/dist/hooks/summary-worker.js +442 -121
- package/dist/index.js +375 -53
- package/dist/lib/agent-config.js +8 -0
- package/dist/lib/cloud-sync.js +35 -12
- package/dist/lib/config.js +13 -0
- package/dist/lib/consolidation.js +9 -1
- package/dist/lib/embedder.js +13 -0
- package/dist/lib/employees.js +8 -0
- package/dist/lib/exe-daemon.js +524 -60
- package/dist/lib/hybrid-search.js +37 -12
- package/dist/lib/keychain.js +25 -13
- package/dist/lib/messaging.js +395 -74
- package/dist/lib/schedules.js +36 -12
- package/dist/lib/skill-learning.js +21 -0
- package/dist/lib/store.js +36 -12
- package/dist/lib/tasks.js +324 -41
- package/dist/lib/tmux-routing.js +324 -41
- package/dist/mcp/server.js +374 -54
- package/dist/mcp/tools/create-task.js +324 -41
- package/dist/mcp/tools/list-tasks.js +406 -57
- package/dist/mcp/tools/send-message.js +395 -74
- package/dist/mcp/tools/update-task.js +324 -41
- package/dist/runtime/index.js +375 -53
- package/dist/tui/App.js +377 -55
- package/package.json +1 -1
package/dist/bin/setup.js
CHANGED
|
@@ -144,6 +144,17 @@ function normalizeOrchestration(raw) {
|
|
|
144
144
|
const userOrg = raw.orchestration ?? {};
|
|
145
145
|
raw.orchestration = { ...defaultOrg, ...userOrg };
|
|
146
146
|
}
|
|
147
|
+
function normalizeCloudEndpoint(raw) {
|
|
148
|
+
const cloud = raw.cloud;
|
|
149
|
+
if (!cloud?.endpoint) return;
|
|
150
|
+
const ep = String(cloud.endpoint);
|
|
151
|
+
if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
|
|
152
|
+
cloud.endpoint = "https://cloud.askexe.com";
|
|
153
|
+
process.stderr.write(
|
|
154
|
+
"[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
147
158
|
async function loadConfig() {
|
|
148
159
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
149
160
|
await ensurePrivateDir(dir);
|
|
@@ -169,6 +180,7 @@ async function loadConfig() {
|
|
|
169
180
|
normalizeSessionLifecycle(migratedCfg);
|
|
170
181
|
normalizeAutoUpdate(migratedCfg);
|
|
171
182
|
normalizeOrchestration(migratedCfg);
|
|
183
|
+
normalizeCloudEndpoint(migratedCfg);
|
|
172
184
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
173
185
|
if (config.dbPath.startsWith("~")) {
|
|
174
186
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -197,6 +209,7 @@ function loadConfigSync() {
|
|
|
197
209
|
normalizeSessionLifecycle(migratedCfg);
|
|
198
210
|
normalizeAutoUpdate(migratedCfg);
|
|
199
211
|
normalizeOrchestration(migratedCfg);
|
|
212
|
+
normalizeCloudEndpoint(migratedCfg);
|
|
200
213
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
201
214
|
if (config.dbPath.startsWith("~")) {
|
|
202
215
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -330,7 +343,7 @@ __export(keychain_exports, {
|
|
|
330
343
|
importMnemonic: () => importMnemonic,
|
|
331
344
|
setMasterKey: () => setMasterKey
|
|
332
345
|
});
|
|
333
|
-
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
346
|
+
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
334
347
|
import { existsSync as existsSync3, statSync } from "fs";
|
|
335
348
|
import { execSync } from "child_process";
|
|
336
349
|
import path2 from "path";
|
|
@@ -365,12 +378,14 @@ function linuxSecretAvailable() {
|
|
|
365
378
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
366
379
|
if (process.platform !== "linux") return false;
|
|
367
380
|
try {
|
|
368
|
-
const uid = typeof os2.userInfo().uid === "number" ? os2.userInfo().uid : -1;
|
|
369
381
|
const st = statSync(keyPath);
|
|
370
382
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
383
|
+
const uid = typeof os2.userInfo().uid === "number" ? os2.userInfo().uid : -1;
|
|
371
384
|
if (uid === 0) return true;
|
|
372
385
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
373
|
-
|
|
386
|
+
if (exeOsDir && path2.resolve(keyPath).startsWith(path2.resolve(exeOsDir) + path2.sep)) return true;
|
|
387
|
+
if (!linuxSecretAvailable()) return true;
|
|
388
|
+
return false;
|
|
374
389
|
} catch {
|
|
375
390
|
return false;
|
|
376
391
|
}
|
|
@@ -520,15 +535,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
520
535
|
await mkdir2(dir, { recursive: true });
|
|
521
536
|
const keyPath = getKeyPath();
|
|
522
537
|
const machineKey = deriveMachineKey();
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
538
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
539
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
540
|
+
const tmpPath = keyPath + ".tmp";
|
|
541
|
+
try {
|
|
542
|
+
if (existsSync3(keyPath)) {
|
|
543
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
await writeFile2(tmpPath, content, "utf-8");
|
|
547
|
+
await chmod2(tmpPath, 384);
|
|
548
|
+
await rename(tmpPath, keyPath);
|
|
549
|
+
} catch (err) {
|
|
550
|
+
try {
|
|
551
|
+
await unlink(tmpPath);
|
|
552
|
+
} catch {
|
|
553
|
+
}
|
|
554
|
+
throw err;
|
|
528
555
|
}
|
|
529
|
-
|
|
530
|
-
await chmod2(keyPath, 384);
|
|
531
|
-
return "plaintext";
|
|
556
|
+
return result;
|
|
532
557
|
}
|
|
533
558
|
async function getMasterKey() {
|
|
534
559
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -595,7 +620,7 @@ async function getMasterKey() {
|
|
|
595
620
|
b64Value = content;
|
|
596
621
|
}
|
|
597
622
|
const key = Buffer.from(b64Value, "base64");
|
|
598
|
-
if (
|
|
623
|
+
if (isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
599
624
|
return key;
|
|
600
625
|
}
|
|
601
626
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
@@ -1963,6 +1988,7 @@ __export(agent_config_exports, {
|
|
|
1963
1988
|
clearAgentRuntime: () => clearAgentRuntime,
|
|
1964
1989
|
getAgentRuntime: () => getAgentRuntime,
|
|
1965
1990
|
loadAgentConfig: () => loadAgentConfig,
|
|
1991
|
+
normalizeCcModelName: () => normalizeCcModelName,
|
|
1966
1992
|
saveAgentConfig: () => saveAgentConfig,
|
|
1967
1993
|
setAgentMcps: () => setAgentMcps,
|
|
1968
1994
|
setAgentRuntime: () => setAgentRuntime
|
|
@@ -1991,6 +2017,13 @@ function getAgentRuntime(agentId) {
|
|
|
1991
2017
|
if (orgDefault) return orgDefault;
|
|
1992
2018
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
1993
2019
|
}
|
|
2020
|
+
function normalizeCcModelName(model) {
|
|
2021
|
+
let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
2022
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
2023
|
+
ccModel += "[1m]";
|
|
2024
|
+
}
|
|
2025
|
+
return ccModel;
|
|
2026
|
+
}
|
|
1994
2027
|
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
1995
2028
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
1996
2029
|
if (!knownModels) {
|
|
@@ -5151,6 +5184,7 @@ __export(cloud_sync_exports, {
|
|
|
5151
5184
|
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
5152
5185
|
mergeConfig: () => mergeConfig,
|
|
5153
5186
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
5187
|
+
migrateEndpoint: () => migrateEndpoint,
|
|
5154
5188
|
pushToPostgres: () => pushToPostgres,
|
|
5155
5189
|
recordRosterDeletion: () => recordRosterDeletion
|
|
5156
5190
|
});
|
|
@@ -5321,6 +5355,15 @@ async function fetchWithRetry(url, init) {
|
|
|
5321
5355
|
}
|
|
5322
5356
|
throw lastError;
|
|
5323
5357
|
}
|
|
5358
|
+
function migrateEndpoint(endpoint) {
|
|
5359
|
+
if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
|
|
5360
|
+
process.stderr.write(
|
|
5361
|
+
"[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
|
|
5362
|
+
);
|
|
5363
|
+
return "https://cloud.askexe.com";
|
|
5364
|
+
}
|
|
5365
|
+
return endpoint;
|
|
5366
|
+
}
|
|
5324
5367
|
function assertSecureEndpoint(endpoint) {
|
|
5325
5368
|
if (endpoint.startsWith("https://")) return;
|
|
5326
5369
|
if (endpoint.startsWith("http://")) {
|
|
@@ -5458,6 +5501,7 @@ async function markCloudReuploadRequired(client = getClient()) {
|
|
|
5458
5501
|
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
5459
5502
|
}
|
|
5460
5503
|
async function cloudSync(config) {
|
|
5504
|
+
config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
|
|
5461
5505
|
if (!isSyncCryptoInitialized()) {
|
|
5462
5506
|
try {
|
|
5463
5507
|
const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
@@ -8796,6 +8840,24 @@ async function runSetupWizard(opts = {}) {
|
|
|
8796
8840
|
log("");
|
|
8797
8841
|
log("=== exe-os Setup ===");
|
|
8798
8842
|
log("");
|
|
8843
|
+
if (process.platform === "darwin") {
|
|
8844
|
+
const currentShell = process.env.SHELL ?? "";
|
|
8845
|
+
if (currentShell.includes("bash")) {
|
|
8846
|
+
log(" \u26A0 Your default shell is bash.");
|
|
8847
|
+
log(" macOS uses zsh by default since Catalina (2019).");
|
|
8848
|
+
log(" exe-os works with bash, but switching to zsh is recommended:");
|
|
8849
|
+
log(" chsh -s /bin/zsh");
|
|
8850
|
+
log(" Then restart your terminal.");
|
|
8851
|
+
log("");
|
|
8852
|
+
const cont = await ask(rl, " Continue with bash? (y/n, default: y): ");
|
|
8853
|
+
if (cont.toLowerCase() === "n") {
|
|
8854
|
+
log(" Run `chsh -s /bin/zsh`, restart your terminal, then run setup again.");
|
|
8855
|
+
rl.close();
|
|
8856
|
+
return;
|
|
8857
|
+
}
|
|
8858
|
+
log("");
|
|
8859
|
+
}
|
|
8860
|
+
}
|
|
8799
8861
|
log("What are you setting up?");
|
|
8800
8862
|
log("");
|
|
8801
8863
|
log(" [1] First device / brand new Exe OS memory");
|
|
@@ -193,6 +193,17 @@ function normalizeOrchestration(raw) {
|
|
|
193
193
|
const userOrg = raw.orchestration ?? {};
|
|
194
194
|
raw.orchestration = { ...defaultOrg, ...userOrg };
|
|
195
195
|
}
|
|
196
|
+
function normalizeCloudEndpoint(raw) {
|
|
197
|
+
const cloud = raw.cloud;
|
|
198
|
+
if (!cloud?.endpoint) return;
|
|
199
|
+
const ep = String(cloud.endpoint);
|
|
200
|
+
if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
|
|
201
|
+
cloud.endpoint = "https://cloud.askexe.com";
|
|
202
|
+
process.stderr.write(
|
|
203
|
+
"[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
196
207
|
async function loadConfig() {
|
|
197
208
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
198
209
|
await ensurePrivateDir(dir);
|
|
@@ -218,6 +229,7 @@ async function loadConfig() {
|
|
|
218
229
|
normalizeSessionLifecycle(migratedCfg);
|
|
219
230
|
normalizeAutoUpdate(migratedCfg);
|
|
220
231
|
normalizeOrchestration(migratedCfg);
|
|
232
|
+
normalizeCloudEndpoint(migratedCfg);
|
|
221
233
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
222
234
|
if (config.dbPath.startsWith("~")) {
|
|
223
235
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -4385,7 +4397,7 @@ init_memory();
|
|
|
4385
4397
|
init_database();
|
|
4386
4398
|
|
|
4387
4399
|
// src/lib/keychain.ts
|
|
4388
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4400
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
|
|
4389
4401
|
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
4390
4402
|
import { execSync as execSync3 } from "child_process";
|
|
4391
4403
|
import path6 from "path";
|
|
@@ -4424,12 +4436,14 @@ function linuxSecretAvailable() {
|
|
|
4424
4436
|
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
4425
4437
|
if (process.platform !== "linux") return false;
|
|
4426
4438
|
try {
|
|
4427
|
-
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4428
4439
|
const st = statSync3(keyPath);
|
|
4429
4440
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4441
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4430
4442
|
if (uid === 0) return true;
|
|
4431
4443
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
4432
|
-
|
|
4444
|
+
if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
|
|
4445
|
+
if (!linuxSecretAvailable()) return true;
|
|
4446
|
+
return false;
|
|
4433
4447
|
} catch {
|
|
4434
4448
|
return false;
|
|
4435
4449
|
}
|
|
@@ -4580,15 +4594,25 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
4580
4594
|
await mkdir3(dir, { recursive: true });
|
|
4581
4595
|
const keyPath = getKeyPath();
|
|
4582
4596
|
const machineKey = deriveMachineKey();
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4597
|
+
const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
|
|
4598
|
+
const result = machineKey ? "encrypted" : "plaintext";
|
|
4599
|
+
const tmpPath = keyPath + ".tmp";
|
|
4600
|
+
try {
|
|
4601
|
+
if (existsSync7(keyPath)) {
|
|
4602
|
+
await copyFile(keyPath, keyPath + ".bak").catch(() => {
|
|
4603
|
+
});
|
|
4604
|
+
}
|
|
4605
|
+
await writeFile3(tmpPath, content, "utf-8");
|
|
4606
|
+
await chmod2(tmpPath, 384);
|
|
4607
|
+
await rename(tmpPath, keyPath);
|
|
4608
|
+
} catch (err) {
|
|
4609
|
+
try {
|
|
4610
|
+
await unlink(tmpPath);
|
|
4611
|
+
} catch {
|
|
4612
|
+
}
|
|
4613
|
+
throw err;
|
|
4588
4614
|
}
|
|
4589
|
-
|
|
4590
|
-
await chmod2(keyPath, 384);
|
|
4591
|
-
return "plaintext";
|
|
4615
|
+
return result;
|
|
4592
4616
|
}
|
|
4593
4617
|
async function getMasterKey() {
|
|
4594
4618
|
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
@@ -4655,7 +4679,7 @@ async function getMasterKey() {
|
|
|
4655
4679
|
b64Value = content;
|
|
4656
4680
|
}
|
|
4657
4681
|
const key = Buffer.from(b64Value, "base64");
|
|
4658
|
-
if (
|
|
4682
|
+
if (isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
4659
4683
|
return key;
|
|
4660
4684
|
}
|
|
4661
4685
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|