@askexenow/exe-os 0.9.30 → 0.9.32
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 +135 -7
- package/dist/bin/backfill-responses.js +135 -7
- package/dist/bin/backfill-vectors.js +135 -7
- package/dist/bin/cleanup-stale-review-tasks.js +139 -11
- package/dist/bin/cli.js +812 -486
- package/dist/bin/exe-assign.js +135 -7
- package/dist/bin/exe-boot.js +422 -113
- package/dist/bin/exe-cloud.js +160 -9
- package/dist/bin/exe-dispatch.js +136 -8
- package/dist/bin/exe-doctor.js +255 -13
- package/dist/bin/exe-export-behaviors.js +136 -8
- package/dist/bin/exe-forget.js +136 -8
- package/dist/bin/exe-gateway.js +171 -24
- package/dist/bin/exe-heartbeat.js +141 -13
- package/dist/bin/exe-kill.js +140 -12
- package/dist/bin/exe-launch-agent.js +143 -15
- package/dist/bin/exe-link.js +357 -48
- package/dist/bin/exe-pending-messages.js +136 -8
- package/dist/bin/exe-pending-notifications.js +136 -8
- package/dist/bin/exe-pending-reviews.js +138 -10
- package/dist/bin/exe-review.js +136 -8
- package/dist/bin/exe-search.js +155 -20
- package/dist/bin/exe-session-cleanup.js +166 -38
- package/dist/bin/exe-start-codex.js +142 -14
- package/dist/bin/exe-start-opencode.js +140 -12
- package/dist/bin/exe-status.js +148 -20
- package/dist/bin/exe-team.js +136 -8
- package/dist/bin/git-sweep.js +138 -10
- package/dist/bin/graph-backfill.js +135 -7
- package/dist/bin/graph-export.js +136 -8
- package/dist/bin/intercom-check.js +153 -25
- package/dist/bin/scan-tasks.js +138 -10
- package/dist/bin/setup.js +447 -121
- package/dist/bin/shard-migrate.js +135 -7
- package/dist/gateway/index.js +151 -23
- package/dist/hooks/bug-report-worker.js +151 -23
- package/dist/hooks/codex-stop-task-finalizer.js +145 -17
- package/dist/hooks/commit-complete.js +138 -10
- package/dist/hooks/error-recall.js +159 -24
- package/dist/hooks/ingest.js +142 -14
- package/dist/hooks/instructions-loaded.js +136 -8
- package/dist/hooks/notification.js +136 -8
- package/dist/hooks/post-compact.js +136 -8
- package/dist/hooks/post-tool-combined.js +159 -24
- package/dist/hooks/pre-compact.js +136 -8
- package/dist/hooks/pre-tool-use.js +144 -16
- package/dist/hooks/prompt-submit.js +195 -55
- package/dist/hooks/session-end.js +141 -13
- package/dist/hooks/session-start.js +165 -30
- package/dist/hooks/stop.js +136 -8
- package/dist/hooks/subagent-stop.js +136 -8
- package/dist/hooks/summary-worker.js +374 -65
- package/dist/index.js +136 -8
- package/dist/lib/cloud-sync.js +355 -46
- package/dist/lib/consolidation.js +1 -0
- package/dist/lib/exe-daemon.js +469 -127
- package/dist/lib/hybrid-search.js +155 -20
- package/dist/lib/keychain.js +191 -7
- package/dist/lib/schedules.js +138 -10
- package/dist/lib/store.js +135 -7
- package/dist/mcp/server.js +706 -213
- package/dist/runtime/index.js +136 -8
- package/dist/tui/App.js +208 -31
- package/package.json +1 -1
package/dist/bin/exe-forget.js
CHANGED
|
@@ -1040,8 +1040,8 @@ function findPackageRoot() {
|
|
|
1040
1040
|
function getAvailableMemoryGB() {
|
|
1041
1041
|
if (process.platform === "darwin") {
|
|
1042
1042
|
try {
|
|
1043
|
-
const { execSync:
|
|
1044
|
-
const vmstat =
|
|
1043
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
1044
|
+
const vmstat = execSync3("vm_stat", { encoding: "utf8" });
|
|
1045
1045
|
const pageSize = 16384;
|
|
1046
1046
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1047
1047
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2780,6 +2780,7 @@ var init_database = __esm({
|
|
|
2780
2780
|
// src/lib/keychain.ts
|
|
2781
2781
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2782
2782
|
import { existsSync as existsSync6 } from "fs";
|
|
2783
|
+
import { execSync as execSync2 } from "child_process";
|
|
2783
2784
|
import path6 from "path";
|
|
2784
2785
|
import os5 from "os";
|
|
2785
2786
|
function getKeyDir() {
|
|
@@ -2788,6 +2789,59 @@ function getKeyDir() {
|
|
|
2788
2789
|
function getKeyPath() {
|
|
2789
2790
|
return path6.join(getKeyDir(), "master.key");
|
|
2790
2791
|
}
|
|
2792
|
+
function macKeychainGet() {
|
|
2793
|
+
if (process.platform !== "darwin") return null;
|
|
2794
|
+
try {
|
|
2795
|
+
return execSync2(
|
|
2796
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
2797
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2798
|
+
).trim();
|
|
2799
|
+
} catch {
|
|
2800
|
+
return null;
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
function macKeychainSet(value) {
|
|
2804
|
+
if (process.platform !== "darwin") return false;
|
|
2805
|
+
try {
|
|
2806
|
+
try {
|
|
2807
|
+
execSync2(
|
|
2808
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
2809
|
+
{ timeout: 5e3 }
|
|
2810
|
+
);
|
|
2811
|
+
} catch {
|
|
2812
|
+
}
|
|
2813
|
+
execSync2(
|
|
2814
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
2815
|
+
{ timeout: 5e3 }
|
|
2816
|
+
);
|
|
2817
|
+
return true;
|
|
2818
|
+
} catch {
|
|
2819
|
+
return false;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
function linuxSecretGet() {
|
|
2823
|
+
if (process.platform !== "linux") return null;
|
|
2824
|
+
try {
|
|
2825
|
+
return execSync2(
|
|
2826
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
2827
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2828
|
+
).trim();
|
|
2829
|
+
} catch {
|
|
2830
|
+
return null;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
function linuxSecretSet(value) {
|
|
2834
|
+
if (process.platform !== "linux") return false;
|
|
2835
|
+
try {
|
|
2836
|
+
execSync2(
|
|
2837
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
2838
|
+
{ timeout: 5e3 }
|
|
2839
|
+
);
|
|
2840
|
+
return true;
|
|
2841
|
+
} catch {
|
|
2842
|
+
return false;
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2791
2845
|
async function tryKeytar() {
|
|
2792
2846
|
try {
|
|
2793
2847
|
return await import("keytar");
|
|
@@ -2795,13 +2849,63 @@ async function tryKeytar() {
|
|
|
2795
2849
|
return null;
|
|
2796
2850
|
}
|
|
2797
2851
|
}
|
|
2852
|
+
function deriveMachineKey() {
|
|
2853
|
+
try {
|
|
2854
|
+
const crypto2 = __require("crypto");
|
|
2855
|
+
const material = [
|
|
2856
|
+
os5.hostname(),
|
|
2857
|
+
os5.userInfo().username,
|
|
2858
|
+
os5.arch(),
|
|
2859
|
+
os5.platform(),
|
|
2860
|
+
// Machine ID on Linux (stable across reboots)
|
|
2861
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
2862
|
+
].join("|");
|
|
2863
|
+
return crypto2.createHash("sha256").update(material).digest();
|
|
2864
|
+
} catch {
|
|
2865
|
+
return null;
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
function readMachineId() {
|
|
2869
|
+
try {
|
|
2870
|
+
const { readFileSync: readFileSync5 } = __require("fs");
|
|
2871
|
+
return readFileSync5("/etc/machine-id", "utf-8").trim();
|
|
2872
|
+
} catch {
|
|
2873
|
+
return "";
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
2877
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
2878
|
+
try {
|
|
2879
|
+
const crypto2 = __require("crypto");
|
|
2880
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
2881
|
+
if (parts.length !== 3) return null;
|
|
2882
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
2883
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
2884
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
2885
|
+
const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
2886
|
+
decipher.setAuthTag(authTag);
|
|
2887
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
2888
|
+
decrypted += decipher.final("utf-8");
|
|
2889
|
+
return decrypted;
|
|
2890
|
+
} catch {
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2798
2894
|
async function getMasterKey() {
|
|
2895
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
2896
|
+
if (nativeValue) {
|
|
2897
|
+
return Buffer.from(nativeValue, "base64");
|
|
2898
|
+
}
|
|
2799
2899
|
const keytar = await tryKeytar();
|
|
2800
2900
|
if (keytar) {
|
|
2801
2901
|
try {
|
|
2802
|
-
const
|
|
2803
|
-
if (
|
|
2804
|
-
|
|
2902
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
2903
|
+
if (keytarValue) {
|
|
2904
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
2905
|
+
if (migrated) {
|
|
2906
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
2907
|
+
}
|
|
2908
|
+
return Buffer.from(keytarValue, "base64");
|
|
2805
2909
|
}
|
|
2806
2910
|
} catch {
|
|
2807
2911
|
}
|
|
@@ -2815,8 +2919,31 @@ async function getMasterKey() {
|
|
|
2815
2919
|
return null;
|
|
2816
2920
|
}
|
|
2817
2921
|
try {
|
|
2818
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
2819
|
-
|
|
2922
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
2923
|
+
let b64Value;
|
|
2924
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
2925
|
+
const machineKey = deriveMachineKey();
|
|
2926
|
+
if (!machineKey) {
|
|
2927
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
2928
|
+
return null;
|
|
2929
|
+
}
|
|
2930
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
2931
|
+
if (!decrypted) {
|
|
2932
|
+
process.stderr.write(
|
|
2933
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
2934
|
+
);
|
|
2935
|
+
return null;
|
|
2936
|
+
}
|
|
2937
|
+
b64Value = decrypted;
|
|
2938
|
+
} else {
|
|
2939
|
+
b64Value = content;
|
|
2940
|
+
}
|
|
2941
|
+
const key = Buffer.from(b64Value, "base64");
|
|
2942
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
2943
|
+
if (migrated) {
|
|
2944
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
2945
|
+
}
|
|
2946
|
+
return key;
|
|
2820
2947
|
} catch (err) {
|
|
2821
2948
|
process.stderr.write(
|
|
2822
2949
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2825,12 +2952,13 @@ async function getMasterKey() {
|
|
|
2825
2952
|
return null;
|
|
2826
2953
|
}
|
|
2827
2954
|
}
|
|
2828
|
-
var SERVICE, ACCOUNT;
|
|
2955
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
2829
2956
|
var init_keychain = __esm({
|
|
2830
2957
|
"src/lib/keychain.ts"() {
|
|
2831
2958
|
"use strict";
|
|
2832
2959
|
SERVICE = "exe-mem";
|
|
2833
2960
|
ACCOUNT = "master-key";
|
|
2961
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
2834
2962
|
}
|
|
2835
2963
|
});
|
|
2836
2964
|
|
package/dist/bin/exe-gateway.js
CHANGED
|
@@ -1740,8 +1740,8 @@ function findPackageRoot() {
|
|
|
1740
1740
|
function getAvailableMemoryGB() {
|
|
1741
1741
|
if (process.platform === "darwin") {
|
|
1742
1742
|
try {
|
|
1743
|
-
const { execSync:
|
|
1744
|
-
const vmstat =
|
|
1743
|
+
const { execSync: execSync8 } = __require("child_process");
|
|
1744
|
+
const vmstat = execSync8("vm_stat", { encoding: "utf8" });
|
|
1745
1745
|
const pageSize = 16384;
|
|
1746
1746
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1747
1747
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3493,6 +3493,7 @@ var init_embedder = __esm({
|
|
|
3493
3493
|
// src/lib/keychain.ts
|
|
3494
3494
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3495
3495
|
import { existsSync as existsSync7 } from "fs";
|
|
3496
|
+
import { execSync as execSync2 } from "child_process";
|
|
3496
3497
|
import path8 from "path";
|
|
3497
3498
|
import os6 from "os";
|
|
3498
3499
|
function getKeyDir() {
|
|
@@ -3501,6 +3502,59 @@ function getKeyDir() {
|
|
|
3501
3502
|
function getKeyPath() {
|
|
3502
3503
|
return path8.join(getKeyDir(), "master.key");
|
|
3503
3504
|
}
|
|
3505
|
+
function macKeychainGet() {
|
|
3506
|
+
if (process.platform !== "darwin") return null;
|
|
3507
|
+
try {
|
|
3508
|
+
return execSync2(
|
|
3509
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3510
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3511
|
+
).trim();
|
|
3512
|
+
} catch {
|
|
3513
|
+
return null;
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
function macKeychainSet(value) {
|
|
3517
|
+
if (process.platform !== "darwin") return false;
|
|
3518
|
+
try {
|
|
3519
|
+
try {
|
|
3520
|
+
execSync2(
|
|
3521
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3522
|
+
{ timeout: 5e3 }
|
|
3523
|
+
);
|
|
3524
|
+
} catch {
|
|
3525
|
+
}
|
|
3526
|
+
execSync2(
|
|
3527
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3528
|
+
{ timeout: 5e3 }
|
|
3529
|
+
);
|
|
3530
|
+
return true;
|
|
3531
|
+
} catch {
|
|
3532
|
+
return false;
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
function linuxSecretGet() {
|
|
3536
|
+
if (process.platform !== "linux") return null;
|
|
3537
|
+
try {
|
|
3538
|
+
return execSync2(
|
|
3539
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3540
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3541
|
+
).trim();
|
|
3542
|
+
} catch {
|
|
3543
|
+
return null;
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
function linuxSecretSet(value) {
|
|
3547
|
+
if (process.platform !== "linux") return false;
|
|
3548
|
+
try {
|
|
3549
|
+
execSync2(
|
|
3550
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
3551
|
+
{ timeout: 5e3 }
|
|
3552
|
+
);
|
|
3553
|
+
return true;
|
|
3554
|
+
} catch {
|
|
3555
|
+
return false;
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3504
3558
|
async function tryKeytar() {
|
|
3505
3559
|
try {
|
|
3506
3560
|
return await import("keytar");
|
|
@@ -3508,13 +3562,63 @@ async function tryKeytar() {
|
|
|
3508
3562
|
return null;
|
|
3509
3563
|
}
|
|
3510
3564
|
}
|
|
3565
|
+
function deriveMachineKey() {
|
|
3566
|
+
try {
|
|
3567
|
+
const crypto10 = __require("crypto");
|
|
3568
|
+
const material = [
|
|
3569
|
+
os6.hostname(),
|
|
3570
|
+
os6.userInfo().username,
|
|
3571
|
+
os6.arch(),
|
|
3572
|
+
os6.platform(),
|
|
3573
|
+
// Machine ID on Linux (stable across reboots)
|
|
3574
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
3575
|
+
].join("|");
|
|
3576
|
+
return crypto10.createHash("sha256").update(material).digest();
|
|
3577
|
+
} catch {
|
|
3578
|
+
return null;
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
function readMachineId() {
|
|
3582
|
+
try {
|
|
3583
|
+
const { readFileSync: readFileSync16 } = __require("fs");
|
|
3584
|
+
return readFileSync16("/etc/machine-id", "utf-8").trim();
|
|
3585
|
+
} catch {
|
|
3586
|
+
return "";
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
3590
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
3591
|
+
try {
|
|
3592
|
+
const crypto10 = __require("crypto");
|
|
3593
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
3594
|
+
if (parts.length !== 3) return null;
|
|
3595
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
3596
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
3597
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
3598
|
+
const decipher = crypto10.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
3599
|
+
decipher.setAuthTag(authTag);
|
|
3600
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
3601
|
+
decrypted += decipher.final("utf-8");
|
|
3602
|
+
return decrypted;
|
|
3603
|
+
} catch {
|
|
3604
|
+
return null;
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3511
3607
|
async function getMasterKey() {
|
|
3608
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
3609
|
+
if (nativeValue) {
|
|
3610
|
+
return Buffer.from(nativeValue, "base64");
|
|
3611
|
+
}
|
|
3512
3612
|
const keytar = await tryKeytar();
|
|
3513
3613
|
if (keytar) {
|
|
3514
3614
|
try {
|
|
3515
|
-
const
|
|
3516
|
-
if (
|
|
3517
|
-
|
|
3615
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3616
|
+
if (keytarValue) {
|
|
3617
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
3618
|
+
if (migrated) {
|
|
3619
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
3620
|
+
}
|
|
3621
|
+
return Buffer.from(keytarValue, "base64");
|
|
3518
3622
|
}
|
|
3519
3623
|
} catch {
|
|
3520
3624
|
}
|
|
@@ -3528,8 +3632,31 @@ async function getMasterKey() {
|
|
|
3528
3632
|
return null;
|
|
3529
3633
|
}
|
|
3530
3634
|
try {
|
|
3531
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
3532
|
-
|
|
3635
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
3636
|
+
let b64Value;
|
|
3637
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
3638
|
+
const machineKey = deriveMachineKey();
|
|
3639
|
+
if (!machineKey) {
|
|
3640
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
3641
|
+
return null;
|
|
3642
|
+
}
|
|
3643
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
3644
|
+
if (!decrypted) {
|
|
3645
|
+
process.stderr.write(
|
|
3646
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
3647
|
+
);
|
|
3648
|
+
return null;
|
|
3649
|
+
}
|
|
3650
|
+
b64Value = decrypted;
|
|
3651
|
+
} else {
|
|
3652
|
+
b64Value = content;
|
|
3653
|
+
}
|
|
3654
|
+
const key = Buffer.from(b64Value, "base64");
|
|
3655
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
3656
|
+
if (migrated) {
|
|
3657
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
3658
|
+
}
|
|
3659
|
+
return key;
|
|
3533
3660
|
} catch (err) {
|
|
3534
3661
|
process.stderr.write(
|
|
3535
3662
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -3538,12 +3665,13 @@ async function getMasterKey() {
|
|
|
3538
3665
|
return null;
|
|
3539
3666
|
}
|
|
3540
3667
|
}
|
|
3541
|
-
var SERVICE, ACCOUNT;
|
|
3668
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
3542
3669
|
var init_keychain = __esm({
|
|
3543
3670
|
"src/lib/keychain.ts"() {
|
|
3544
3671
|
"use strict";
|
|
3545
3672
|
SERVICE = "exe-mem";
|
|
3546
3673
|
ACCOUNT = "master-key";
|
|
3674
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
3547
3675
|
}
|
|
3548
3676
|
});
|
|
3549
3677
|
|
|
@@ -7972,7 +8100,7 @@ var init_session_registry = __esm({
|
|
|
7972
8100
|
});
|
|
7973
8101
|
|
|
7974
8102
|
// src/lib/session-key.ts
|
|
7975
|
-
import { execSync as
|
|
8103
|
+
import { execSync as execSync3 } from "child_process";
|
|
7976
8104
|
function normalizeCommand(command) {
|
|
7977
8105
|
const trimmed = command.trim().toLowerCase();
|
|
7978
8106
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -7991,7 +8119,7 @@ function resolveRuntimeProcess() {
|
|
|
7991
8119
|
let pid = process.ppid;
|
|
7992
8120
|
for (let i = 0; i < 10; i++) {
|
|
7993
8121
|
try {
|
|
7994
|
-
const info =
|
|
8122
|
+
const info = execSync3(`ps -p ${pid} -o ppid=,comm=`, {
|
|
7995
8123
|
encoding: "utf8",
|
|
7996
8124
|
timeout: 2e3
|
|
7997
8125
|
}).trim();
|
|
@@ -8157,14 +8285,14 @@ var init_transport = __esm({
|
|
|
8157
8285
|
});
|
|
8158
8286
|
|
|
8159
8287
|
// src/lib/cc-agent-support.ts
|
|
8160
|
-
import { execSync as
|
|
8288
|
+
import { execSync as execSync4 } from "child_process";
|
|
8161
8289
|
function _resetCcAgentSupportCache() {
|
|
8162
8290
|
_cachedSupport = null;
|
|
8163
8291
|
}
|
|
8164
8292
|
function claudeSupportsAgentFlag() {
|
|
8165
8293
|
if (_cachedSupport !== null) return _cachedSupport;
|
|
8166
8294
|
try {
|
|
8167
|
-
const helpOutput =
|
|
8295
|
+
const helpOutput = execSync4("claude --help 2>&1", {
|
|
8168
8296
|
encoding: "utf-8",
|
|
8169
8297
|
timeout: 5e3
|
|
8170
8298
|
});
|
|
@@ -8558,7 +8686,7 @@ var init_session_kill_telemetry = __esm({
|
|
|
8558
8686
|
});
|
|
8559
8687
|
|
|
8560
8688
|
// src/lib/project-name.ts
|
|
8561
|
-
import { execSync as
|
|
8689
|
+
import { execSync as execSync5 } from "child_process";
|
|
8562
8690
|
import path16 from "path";
|
|
8563
8691
|
function getProjectName(cwd) {
|
|
8564
8692
|
const dir = cwd ?? process.cwd();
|
|
@@ -8566,7 +8694,7 @@ function getProjectName(cwd) {
|
|
|
8566
8694
|
try {
|
|
8567
8695
|
let repoRoot;
|
|
8568
8696
|
try {
|
|
8569
|
-
const gitCommonDir =
|
|
8697
|
+
const gitCommonDir = execSync5("git rev-parse --path-format=absolute --git-common-dir", {
|
|
8570
8698
|
cwd: dir,
|
|
8571
8699
|
encoding: "utf8",
|
|
8572
8700
|
timeout: 2e3,
|
|
@@ -8574,7 +8702,7 @@ function getProjectName(cwd) {
|
|
|
8574
8702
|
}).trim();
|
|
8575
8703
|
repoRoot = path16.dirname(gitCommonDir);
|
|
8576
8704
|
} catch {
|
|
8577
|
-
repoRoot =
|
|
8705
|
+
repoRoot = execSync5("git rev-parse --show-toplevel", {
|
|
8578
8706
|
cwd: dir,
|
|
8579
8707
|
encoding: "utf8",
|
|
8580
8708
|
timeout: 2e3,
|
|
@@ -8665,7 +8793,7 @@ var init_session_scope = __esm({
|
|
|
8665
8793
|
import crypto6 from "crypto";
|
|
8666
8794
|
import path17 from "path";
|
|
8667
8795
|
import os12 from "os";
|
|
8668
|
-
import { execSync as
|
|
8796
|
+
import { execSync as execSync6 } from "child_process";
|
|
8669
8797
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
8670
8798
|
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
8671
8799
|
async function writeCheckpoint(input) {
|
|
@@ -9010,14 +9138,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
9010
9138
|
if (!identifier || identifier === "unknown") return true;
|
|
9011
9139
|
try {
|
|
9012
9140
|
if (identifier.startsWith("%")) {
|
|
9013
|
-
const output =
|
|
9141
|
+
const output = execSync6("tmux list-panes -a -F '#{pane_id}'", {
|
|
9014
9142
|
timeout: 2e3,
|
|
9015
9143
|
encoding: "utf8",
|
|
9016
9144
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9017
9145
|
});
|
|
9018
9146
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
9019
9147
|
} else {
|
|
9020
|
-
|
|
9148
|
+
execSync6(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
9021
9149
|
timeout: 2e3,
|
|
9022
9150
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9023
9151
|
});
|
|
@@ -9026,7 +9154,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
9026
9154
|
} catch {
|
|
9027
9155
|
if (identifier.startsWith("%")) return true;
|
|
9028
9156
|
try {
|
|
9029
|
-
|
|
9157
|
+
execSync6("tmux list-sessions", {
|
|
9030
9158
|
timeout: 2e3,
|
|
9031
9159
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9032
9160
|
});
|
|
@@ -9041,12 +9169,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
9041
9169
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
9042
9170
|
try {
|
|
9043
9171
|
const since = new Date(taskCreatedAt).toISOString();
|
|
9044
|
-
const branch =
|
|
9172
|
+
const branch = execSync6(
|
|
9045
9173
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
9046
9174
|
{ encoding: "utf8", timeout: 3e3 }
|
|
9047
9175
|
).trim();
|
|
9048
9176
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
9049
|
-
const commitCount =
|
|
9177
|
+
const commitCount = execSync6(
|
|
9050
9178
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
9051
9179
|
{ encoding: "utf8", timeout: 5e3 }
|
|
9052
9180
|
).trim();
|
|
@@ -10576,7 +10704,7 @@ __export(tmux_routing_exports, {
|
|
|
10576
10704
|
spawnEmployee: () => spawnEmployee,
|
|
10577
10705
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
10578
10706
|
});
|
|
10579
|
-
import { execFileSync as execFileSync2, execSync as
|
|
10707
|
+
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
10580
10708
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync16, appendFileSync, readdirSync as readdirSync4 } from "fs";
|
|
10581
10709
|
import path21 from "path";
|
|
10582
10710
|
import os13 from "os";
|
|
@@ -11286,7 +11414,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
11286
11414
|
let booted = false;
|
|
11287
11415
|
for (let i = 0; i < 30; i++) {
|
|
11288
11416
|
try {
|
|
11289
|
-
|
|
11417
|
+
execSync7("sleep 0.5");
|
|
11290
11418
|
} catch {
|
|
11291
11419
|
}
|
|
11292
11420
|
try {
|
|
@@ -13208,6 +13336,20 @@ init_employees();
|
|
|
13208
13336
|
var CONFIG_DIR = process.env.EXE_GATEWAY_HOME || path23.join(os15.homedir(), ".exe-os");
|
|
13209
13337
|
var CONFIG_PATH3 = process.env.EXE_GATEWAY_CONFIG || path23.join(CONFIG_DIR, "gateway.json");
|
|
13210
13338
|
var DEFAULT_PORT = 3100;
|
|
13339
|
+
var LOCAL_SIGNAL_HTTP_HOSTS = /^(localhost|127\.0\.0\.1|::1|exe-signal-cli|signal-cli)$/i;
|
|
13340
|
+
function assertSecureSignalUrl(endpoint) {
|
|
13341
|
+
let parsed;
|
|
13342
|
+
try {
|
|
13343
|
+
parsed = new URL(endpoint);
|
|
13344
|
+
} catch {
|
|
13345
|
+
throw new Error(`Malformed Signal URL rejected: "${endpoint}".`);
|
|
13346
|
+
}
|
|
13347
|
+
if (parsed.protocol === "https:") return;
|
|
13348
|
+
if (parsed.protocol === "http:" && LOCAL_SIGNAL_HTTP_HOSTS.test(parsed.hostname)) return;
|
|
13349
|
+
throw new Error(
|
|
13350
|
+
`Insecure Signal URL rejected: "${endpoint}". Use https:// for remote hosts. Plain http:// is only allowed for localhost or Docker-internal signal services.`
|
|
13351
|
+
);
|
|
13352
|
+
}
|
|
13211
13353
|
function validateApiRouterProductionEnv(env = process.env, logger = console) {
|
|
13212
13354
|
if (env.NODE_ENV !== "production") return;
|
|
13213
13355
|
const apiRouterUrl = env.API_ROUTER_URL;
|
|
@@ -13303,7 +13445,11 @@ async function main() {
|
|
|
13303
13445
|
platform: "signal",
|
|
13304
13446
|
permissions: { canRead: true, canWrite: true, canExecute: true },
|
|
13305
13447
|
credentials: {
|
|
13306
|
-
baseUrl:
|
|
13448
|
+
baseUrl: (() => {
|
|
13449
|
+
const baseUrl = signalAccount?.signalCliUrl ?? "http://exe-signal-cli:8080";
|
|
13450
|
+
assertSecureSignalUrl(baseUrl);
|
|
13451
|
+
return baseUrl;
|
|
13452
|
+
})(),
|
|
13307
13453
|
account: signalAccount?.account ?? ""
|
|
13308
13454
|
}
|
|
13309
13455
|
});
|
|
@@ -13412,5 +13558,6 @@ if (isDirectExecution()) {
|
|
|
13412
13558
|
});
|
|
13413
13559
|
}
|
|
13414
13560
|
export {
|
|
13561
|
+
assertSecureSignalUrl,
|
|
13415
13562
|
validateApiRouterProductionEnv
|
|
13416
13563
|
};
|