@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-team.js
CHANGED
|
@@ -1051,8 +1051,8 @@ function findPackageRoot() {
|
|
|
1051
1051
|
function getAvailableMemoryGB() {
|
|
1052
1052
|
if (process.platform === "darwin") {
|
|
1053
1053
|
try {
|
|
1054
|
-
const { execSync:
|
|
1055
|
-
const vmstat =
|
|
1054
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
1055
|
+
const vmstat = execSync3("vm_stat", { encoding: "utf8" });
|
|
1056
1056
|
const pageSize = 16384;
|
|
1057
1057
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1058
1058
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2791,6 +2791,7 @@ var init_database = __esm({
|
|
|
2791
2791
|
// src/lib/keychain.ts
|
|
2792
2792
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2793
2793
|
import { existsSync as existsSync6 } from "fs";
|
|
2794
|
+
import { execSync as execSync2 } from "child_process";
|
|
2794
2795
|
import path6 from "path";
|
|
2795
2796
|
import os5 from "os";
|
|
2796
2797
|
function getKeyDir() {
|
|
@@ -2799,6 +2800,59 @@ function getKeyDir() {
|
|
|
2799
2800
|
function getKeyPath() {
|
|
2800
2801
|
return path6.join(getKeyDir(), "master.key");
|
|
2801
2802
|
}
|
|
2803
|
+
function macKeychainGet() {
|
|
2804
|
+
if (process.platform !== "darwin") return null;
|
|
2805
|
+
try {
|
|
2806
|
+
return execSync2(
|
|
2807
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
2808
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2809
|
+
).trim();
|
|
2810
|
+
} catch {
|
|
2811
|
+
return null;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
function macKeychainSet(value) {
|
|
2815
|
+
if (process.platform !== "darwin") return false;
|
|
2816
|
+
try {
|
|
2817
|
+
try {
|
|
2818
|
+
execSync2(
|
|
2819
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
2820
|
+
{ timeout: 5e3 }
|
|
2821
|
+
);
|
|
2822
|
+
} catch {
|
|
2823
|
+
}
|
|
2824
|
+
execSync2(
|
|
2825
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
2826
|
+
{ timeout: 5e3 }
|
|
2827
|
+
);
|
|
2828
|
+
return true;
|
|
2829
|
+
} catch {
|
|
2830
|
+
return false;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
function linuxSecretGet() {
|
|
2834
|
+
if (process.platform !== "linux") return null;
|
|
2835
|
+
try {
|
|
2836
|
+
return execSync2(
|
|
2837
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
2838
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2839
|
+
).trim();
|
|
2840
|
+
} catch {
|
|
2841
|
+
return null;
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
function linuxSecretSet(value) {
|
|
2845
|
+
if (process.platform !== "linux") return false;
|
|
2846
|
+
try {
|
|
2847
|
+
execSync2(
|
|
2848
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
2849
|
+
{ timeout: 5e3 }
|
|
2850
|
+
);
|
|
2851
|
+
return true;
|
|
2852
|
+
} catch {
|
|
2853
|
+
return false;
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2802
2856
|
async function tryKeytar() {
|
|
2803
2857
|
try {
|
|
2804
2858
|
return await import("keytar");
|
|
@@ -2806,13 +2860,63 @@ async function tryKeytar() {
|
|
|
2806
2860
|
return null;
|
|
2807
2861
|
}
|
|
2808
2862
|
}
|
|
2863
|
+
function deriveMachineKey() {
|
|
2864
|
+
try {
|
|
2865
|
+
const crypto2 = __require("crypto");
|
|
2866
|
+
const material = [
|
|
2867
|
+
os5.hostname(),
|
|
2868
|
+
os5.userInfo().username,
|
|
2869
|
+
os5.arch(),
|
|
2870
|
+
os5.platform(),
|
|
2871
|
+
// Machine ID on Linux (stable across reboots)
|
|
2872
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
2873
|
+
].join("|");
|
|
2874
|
+
return crypto2.createHash("sha256").update(material).digest();
|
|
2875
|
+
} catch {
|
|
2876
|
+
return null;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
function readMachineId() {
|
|
2880
|
+
try {
|
|
2881
|
+
const { readFileSync: readFileSync5 } = __require("fs");
|
|
2882
|
+
return readFileSync5("/etc/machine-id", "utf-8").trim();
|
|
2883
|
+
} catch {
|
|
2884
|
+
return "";
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
2888
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
2889
|
+
try {
|
|
2890
|
+
const crypto2 = __require("crypto");
|
|
2891
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
2892
|
+
if (parts.length !== 3) return null;
|
|
2893
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
2894
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
2895
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
2896
|
+
const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
2897
|
+
decipher.setAuthTag(authTag);
|
|
2898
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
2899
|
+
decrypted += decipher.final("utf-8");
|
|
2900
|
+
return decrypted;
|
|
2901
|
+
} catch {
|
|
2902
|
+
return null;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2809
2905
|
async function getMasterKey() {
|
|
2906
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
2907
|
+
if (nativeValue) {
|
|
2908
|
+
return Buffer.from(nativeValue, "base64");
|
|
2909
|
+
}
|
|
2810
2910
|
const keytar = await tryKeytar();
|
|
2811
2911
|
if (keytar) {
|
|
2812
2912
|
try {
|
|
2813
|
-
const
|
|
2814
|
-
if (
|
|
2815
|
-
|
|
2913
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
2914
|
+
if (keytarValue) {
|
|
2915
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
2916
|
+
if (migrated) {
|
|
2917
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
2918
|
+
}
|
|
2919
|
+
return Buffer.from(keytarValue, "base64");
|
|
2816
2920
|
}
|
|
2817
2921
|
} catch {
|
|
2818
2922
|
}
|
|
@@ -2826,8 +2930,31 @@ async function getMasterKey() {
|
|
|
2826
2930
|
return null;
|
|
2827
2931
|
}
|
|
2828
2932
|
try {
|
|
2829
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
2830
|
-
|
|
2933
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
2934
|
+
let b64Value;
|
|
2935
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
2936
|
+
const machineKey = deriveMachineKey();
|
|
2937
|
+
if (!machineKey) {
|
|
2938
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
2939
|
+
return null;
|
|
2940
|
+
}
|
|
2941
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
2942
|
+
if (!decrypted) {
|
|
2943
|
+
process.stderr.write(
|
|
2944
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
2945
|
+
);
|
|
2946
|
+
return null;
|
|
2947
|
+
}
|
|
2948
|
+
b64Value = decrypted;
|
|
2949
|
+
} else {
|
|
2950
|
+
b64Value = content;
|
|
2951
|
+
}
|
|
2952
|
+
const key = Buffer.from(b64Value, "base64");
|
|
2953
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
2954
|
+
if (migrated) {
|
|
2955
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
2956
|
+
}
|
|
2957
|
+
return key;
|
|
2831
2958
|
} catch (err) {
|
|
2832
2959
|
process.stderr.write(
|
|
2833
2960
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2836,12 +2963,13 @@ async function getMasterKey() {
|
|
|
2836
2963
|
return null;
|
|
2837
2964
|
}
|
|
2838
2965
|
}
|
|
2839
|
-
var SERVICE, ACCOUNT;
|
|
2966
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
2840
2967
|
var init_keychain = __esm({
|
|
2841
2968
|
"src/lib/keychain.ts"() {
|
|
2842
2969
|
"use strict";
|
|
2843
2970
|
SERVICE = "exe-mem";
|
|
2844
2971
|
ACCOUNT = "master-key";
|
|
2972
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
2845
2973
|
}
|
|
2846
2974
|
});
|
|
2847
2975
|
|
package/dist/bin/git-sweep.js
CHANGED
|
@@ -1608,8 +1608,8 @@ function findPackageRoot() {
|
|
|
1608
1608
|
function getAvailableMemoryGB() {
|
|
1609
1609
|
if (process.platform === "darwin") {
|
|
1610
1610
|
try {
|
|
1611
|
-
const { execSync:
|
|
1612
|
-
const vmstat =
|
|
1611
|
+
const { execSync: execSync9 } = __require("child_process");
|
|
1612
|
+
const vmstat = execSync9("vm_stat", { encoding: "utf8" });
|
|
1613
1613
|
const pageSize = 16384;
|
|
1614
1614
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1615
1615
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -6464,6 +6464,7 @@ var init_task_scope = __esm({
|
|
|
6464
6464
|
// src/lib/keychain.ts
|
|
6465
6465
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6466
6466
|
import { existsSync as existsSync15 } from "fs";
|
|
6467
|
+
import { execSync as execSync7 } from "child_process";
|
|
6467
6468
|
import path18 from "path";
|
|
6468
6469
|
import os11 from "os";
|
|
6469
6470
|
function getKeyDir() {
|
|
@@ -6472,6 +6473,59 @@ function getKeyDir() {
|
|
|
6472
6473
|
function getKeyPath() {
|
|
6473
6474
|
return path18.join(getKeyDir(), "master.key");
|
|
6474
6475
|
}
|
|
6476
|
+
function macKeychainGet() {
|
|
6477
|
+
if (process.platform !== "darwin") return null;
|
|
6478
|
+
try {
|
|
6479
|
+
return execSync7(
|
|
6480
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
6481
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
6482
|
+
).trim();
|
|
6483
|
+
} catch {
|
|
6484
|
+
return null;
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
function macKeychainSet(value) {
|
|
6488
|
+
if (process.platform !== "darwin") return false;
|
|
6489
|
+
try {
|
|
6490
|
+
try {
|
|
6491
|
+
execSync7(
|
|
6492
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
6493
|
+
{ timeout: 5e3 }
|
|
6494
|
+
);
|
|
6495
|
+
} catch {
|
|
6496
|
+
}
|
|
6497
|
+
execSync7(
|
|
6498
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
6499
|
+
{ timeout: 5e3 }
|
|
6500
|
+
);
|
|
6501
|
+
return true;
|
|
6502
|
+
} catch {
|
|
6503
|
+
return false;
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
function linuxSecretGet() {
|
|
6507
|
+
if (process.platform !== "linux") return null;
|
|
6508
|
+
try {
|
|
6509
|
+
return execSync7(
|
|
6510
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
6511
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
6512
|
+
).trim();
|
|
6513
|
+
} catch {
|
|
6514
|
+
return null;
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6517
|
+
function linuxSecretSet(value) {
|
|
6518
|
+
if (process.platform !== "linux") return false;
|
|
6519
|
+
try {
|
|
6520
|
+
execSync7(
|
|
6521
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
6522
|
+
{ timeout: 5e3 }
|
|
6523
|
+
);
|
|
6524
|
+
return true;
|
|
6525
|
+
} catch {
|
|
6526
|
+
return false;
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6475
6529
|
async function tryKeytar() {
|
|
6476
6530
|
try {
|
|
6477
6531
|
return await import("keytar");
|
|
@@ -6479,13 +6533,63 @@ async function tryKeytar() {
|
|
|
6479
6533
|
return null;
|
|
6480
6534
|
}
|
|
6481
6535
|
}
|
|
6536
|
+
function deriveMachineKey() {
|
|
6537
|
+
try {
|
|
6538
|
+
const crypto7 = __require("crypto");
|
|
6539
|
+
const material = [
|
|
6540
|
+
os11.hostname(),
|
|
6541
|
+
os11.userInfo().username,
|
|
6542
|
+
os11.arch(),
|
|
6543
|
+
os11.platform(),
|
|
6544
|
+
// Machine ID on Linux (stable across reboots)
|
|
6545
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
6546
|
+
].join("|");
|
|
6547
|
+
return crypto7.createHash("sha256").update(material).digest();
|
|
6548
|
+
} catch {
|
|
6549
|
+
return null;
|
|
6550
|
+
}
|
|
6551
|
+
}
|
|
6552
|
+
function readMachineId() {
|
|
6553
|
+
try {
|
|
6554
|
+
const { readFileSync: readFileSync13 } = __require("fs");
|
|
6555
|
+
return readFileSync13("/etc/machine-id", "utf-8").trim();
|
|
6556
|
+
} catch {
|
|
6557
|
+
return "";
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
6561
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
6562
|
+
try {
|
|
6563
|
+
const crypto7 = __require("crypto");
|
|
6564
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
6565
|
+
if (parts.length !== 3) return null;
|
|
6566
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
6567
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
6568
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
6569
|
+
const decipher = crypto7.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
6570
|
+
decipher.setAuthTag(authTag);
|
|
6571
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
6572
|
+
decrypted += decipher.final("utf-8");
|
|
6573
|
+
return decrypted;
|
|
6574
|
+
} catch {
|
|
6575
|
+
return null;
|
|
6576
|
+
}
|
|
6577
|
+
}
|
|
6482
6578
|
async function getMasterKey() {
|
|
6579
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
6580
|
+
if (nativeValue) {
|
|
6581
|
+
return Buffer.from(nativeValue, "base64");
|
|
6582
|
+
}
|
|
6483
6583
|
const keytar = await tryKeytar();
|
|
6484
6584
|
if (keytar) {
|
|
6485
6585
|
try {
|
|
6486
|
-
const
|
|
6487
|
-
if (
|
|
6488
|
-
|
|
6586
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
6587
|
+
if (keytarValue) {
|
|
6588
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
6589
|
+
if (migrated) {
|
|
6590
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
6591
|
+
}
|
|
6592
|
+
return Buffer.from(keytarValue, "base64");
|
|
6489
6593
|
}
|
|
6490
6594
|
} catch {
|
|
6491
6595
|
}
|
|
@@ -6499,8 +6603,31 @@ async function getMasterKey() {
|
|
|
6499
6603
|
return null;
|
|
6500
6604
|
}
|
|
6501
6605
|
try {
|
|
6502
|
-
const content = await readFile4(keyPath, "utf-8");
|
|
6503
|
-
|
|
6606
|
+
const content = (await readFile4(keyPath, "utf-8")).trim();
|
|
6607
|
+
let b64Value;
|
|
6608
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
6609
|
+
const machineKey = deriveMachineKey();
|
|
6610
|
+
if (!machineKey) {
|
|
6611
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
6612
|
+
return null;
|
|
6613
|
+
}
|
|
6614
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
6615
|
+
if (!decrypted) {
|
|
6616
|
+
process.stderr.write(
|
|
6617
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
6618
|
+
);
|
|
6619
|
+
return null;
|
|
6620
|
+
}
|
|
6621
|
+
b64Value = decrypted;
|
|
6622
|
+
} else {
|
|
6623
|
+
b64Value = content;
|
|
6624
|
+
}
|
|
6625
|
+
const key = Buffer.from(b64Value, "base64");
|
|
6626
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
6627
|
+
if (migrated) {
|
|
6628
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
6629
|
+
}
|
|
6630
|
+
return key;
|
|
6504
6631
|
} catch (err) {
|
|
6505
6632
|
process.stderr.write(
|
|
6506
6633
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -6509,12 +6636,13 @@ async function getMasterKey() {
|
|
|
6509
6636
|
return null;
|
|
6510
6637
|
}
|
|
6511
6638
|
}
|
|
6512
|
-
var SERVICE, ACCOUNT;
|
|
6639
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
6513
6640
|
var init_keychain = __esm({
|
|
6514
6641
|
"src/lib/keychain.ts"() {
|
|
6515
6642
|
"use strict";
|
|
6516
6643
|
SERVICE = "exe-mem";
|
|
6517
6644
|
ACCOUNT = "master-key";
|
|
6645
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
6518
6646
|
}
|
|
6519
6647
|
});
|
|
6520
6648
|
|
|
@@ -7692,7 +7820,7 @@ var init_store = __esm({
|
|
|
7692
7820
|
|
|
7693
7821
|
// src/lib/git-task-sweep.ts
|
|
7694
7822
|
init_task_scope();
|
|
7695
|
-
import { execSync as
|
|
7823
|
+
import { execSync as execSync8 } from "child_process";
|
|
7696
7824
|
var DEFAULT_COMMIT_LIMIT = 50;
|
|
7697
7825
|
var DEFAULT_STALE_MINUTES = 10;
|
|
7698
7826
|
var AUTO_ESCALATE_THRESHOLD = 0.6;
|
|
@@ -7759,7 +7887,7 @@ function matchScore(task, commitMessage, changedFiles) {
|
|
|
7759
7887
|
function getRecentCommits(limit = DEFAULT_COMMIT_LIMIT) {
|
|
7760
7888
|
try {
|
|
7761
7889
|
const SEPARATOR = "<<SEP>>";
|
|
7762
|
-
const output =
|
|
7890
|
+
const output = execSync8(
|
|
7763
7891
|
`git log --format="%h${SEPARATOR}%s${SEPARATOR}%aI" --name-only -n ${limit} -z`,
|
|
7764
7892
|
{ encoding: "utf8", timeout: 1e4 }
|
|
7765
7893
|
);
|
|
@@ -1029,8 +1029,8 @@ function findPackageRoot() {
|
|
|
1029
1029
|
function getAvailableMemoryGB() {
|
|
1030
1030
|
if (process.platform === "darwin") {
|
|
1031
1031
|
try {
|
|
1032
|
-
const { execSync:
|
|
1033
|
-
const vmstat =
|
|
1032
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
1033
|
+
const vmstat = execSync3("vm_stat", { encoding: "utf8" });
|
|
1034
1034
|
const pageSize = 16384;
|
|
1035
1035
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1036
1036
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3141,6 +3141,7 @@ import { createHash } from "crypto";
|
|
|
3141
3141
|
// src/lib/keychain.ts
|
|
3142
3142
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3143
3143
|
import { existsSync as existsSync6 } from "fs";
|
|
3144
|
+
import { execSync as execSync2 } from "child_process";
|
|
3144
3145
|
import path6 from "path";
|
|
3145
3146
|
import os5 from "os";
|
|
3146
3147
|
var SERVICE = "exe-mem";
|
|
@@ -3151,6 +3152,59 @@ function getKeyDir() {
|
|
|
3151
3152
|
function getKeyPath() {
|
|
3152
3153
|
return path6.join(getKeyDir(), "master.key");
|
|
3153
3154
|
}
|
|
3155
|
+
function macKeychainGet() {
|
|
3156
|
+
if (process.platform !== "darwin") return null;
|
|
3157
|
+
try {
|
|
3158
|
+
return execSync2(
|
|
3159
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3160
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3161
|
+
).trim();
|
|
3162
|
+
} catch {
|
|
3163
|
+
return null;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
function macKeychainSet(value) {
|
|
3167
|
+
if (process.platform !== "darwin") return false;
|
|
3168
|
+
try {
|
|
3169
|
+
try {
|
|
3170
|
+
execSync2(
|
|
3171
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3172
|
+
{ timeout: 5e3 }
|
|
3173
|
+
);
|
|
3174
|
+
} catch {
|
|
3175
|
+
}
|
|
3176
|
+
execSync2(
|
|
3177
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3178
|
+
{ timeout: 5e3 }
|
|
3179
|
+
);
|
|
3180
|
+
return true;
|
|
3181
|
+
} catch {
|
|
3182
|
+
return false;
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
function linuxSecretGet() {
|
|
3186
|
+
if (process.platform !== "linux") return null;
|
|
3187
|
+
try {
|
|
3188
|
+
return execSync2(
|
|
3189
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3190
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3191
|
+
).trim();
|
|
3192
|
+
} catch {
|
|
3193
|
+
return null;
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
function linuxSecretSet(value) {
|
|
3197
|
+
if (process.platform !== "linux") return false;
|
|
3198
|
+
try {
|
|
3199
|
+
execSync2(
|
|
3200
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
3201
|
+
{ timeout: 5e3 }
|
|
3202
|
+
);
|
|
3203
|
+
return true;
|
|
3204
|
+
} catch {
|
|
3205
|
+
return false;
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3154
3208
|
async function tryKeytar() {
|
|
3155
3209
|
try {
|
|
3156
3210
|
return await import("keytar");
|
|
@@ -3158,13 +3212,64 @@ async function tryKeytar() {
|
|
|
3158
3212
|
return null;
|
|
3159
3213
|
}
|
|
3160
3214
|
}
|
|
3215
|
+
var ENCRYPTED_PREFIX = "enc:";
|
|
3216
|
+
function deriveMachineKey() {
|
|
3217
|
+
try {
|
|
3218
|
+
const crypto3 = __require("crypto");
|
|
3219
|
+
const material = [
|
|
3220
|
+
os5.hostname(),
|
|
3221
|
+
os5.userInfo().username,
|
|
3222
|
+
os5.arch(),
|
|
3223
|
+
os5.platform(),
|
|
3224
|
+
// Machine ID on Linux (stable across reboots)
|
|
3225
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
3226
|
+
].join("|");
|
|
3227
|
+
return crypto3.createHash("sha256").update(material).digest();
|
|
3228
|
+
} catch {
|
|
3229
|
+
return null;
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
function readMachineId() {
|
|
3233
|
+
try {
|
|
3234
|
+
const { readFileSync: readFileSync5 } = __require("fs");
|
|
3235
|
+
return readFileSync5("/etc/machine-id", "utf-8").trim();
|
|
3236
|
+
} catch {
|
|
3237
|
+
return "";
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
3241
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
3242
|
+
try {
|
|
3243
|
+
const crypto3 = __require("crypto");
|
|
3244
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
3245
|
+
if (parts.length !== 3) return null;
|
|
3246
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
3247
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
3248
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
3249
|
+
const decipher = crypto3.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
3250
|
+
decipher.setAuthTag(authTag);
|
|
3251
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
3252
|
+
decrypted += decipher.final("utf-8");
|
|
3253
|
+
return decrypted;
|
|
3254
|
+
} catch {
|
|
3255
|
+
return null;
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3161
3258
|
async function getMasterKey() {
|
|
3259
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
3260
|
+
if (nativeValue) {
|
|
3261
|
+
return Buffer.from(nativeValue, "base64");
|
|
3262
|
+
}
|
|
3162
3263
|
const keytar = await tryKeytar();
|
|
3163
3264
|
if (keytar) {
|
|
3164
3265
|
try {
|
|
3165
|
-
const
|
|
3166
|
-
if (
|
|
3167
|
-
|
|
3266
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3267
|
+
if (keytarValue) {
|
|
3268
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
3269
|
+
if (migrated) {
|
|
3270
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
3271
|
+
}
|
|
3272
|
+
return Buffer.from(keytarValue, "base64");
|
|
3168
3273
|
}
|
|
3169
3274
|
} catch {
|
|
3170
3275
|
}
|
|
@@ -3178,8 +3283,31 @@ async function getMasterKey() {
|
|
|
3178
3283
|
return null;
|
|
3179
3284
|
}
|
|
3180
3285
|
try {
|
|
3181
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
3182
|
-
|
|
3286
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
3287
|
+
let b64Value;
|
|
3288
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
3289
|
+
const machineKey = deriveMachineKey();
|
|
3290
|
+
if (!machineKey) {
|
|
3291
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
3292
|
+
return null;
|
|
3293
|
+
}
|
|
3294
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
3295
|
+
if (!decrypted) {
|
|
3296
|
+
process.stderr.write(
|
|
3297
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
3298
|
+
);
|
|
3299
|
+
return null;
|
|
3300
|
+
}
|
|
3301
|
+
b64Value = decrypted;
|
|
3302
|
+
} else {
|
|
3303
|
+
b64Value = content;
|
|
3304
|
+
}
|
|
3305
|
+
const key = Buffer.from(b64Value, "base64");
|
|
3306
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
3307
|
+
if (migrated) {
|
|
3308
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
3309
|
+
}
|
|
3310
|
+
return key;
|
|
3183
3311
|
} catch (err) {
|
|
3184
3312
|
process.stderr.write(
|
|
3185
3313
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|