@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
|
@@ -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: execSync6 } = __require("child_process");
|
|
1044
|
+
const vmstat = execSync6("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;
|
|
@@ -3171,7 +3171,7 @@ var init_runtime_table = __esm({
|
|
|
3171
3171
|
});
|
|
3172
3172
|
|
|
3173
3173
|
// src/lib/session-key.ts
|
|
3174
|
-
import { execSync as
|
|
3174
|
+
import { execSync as execSync3 } from "child_process";
|
|
3175
3175
|
function normalizeCommand(command) {
|
|
3176
3176
|
const trimmed = command.trim().toLowerCase();
|
|
3177
3177
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -3190,7 +3190,7 @@ function resolveRuntimeProcess() {
|
|
|
3190
3190
|
let pid = process.ppid;
|
|
3191
3191
|
for (let i = 0; i < 10; i++) {
|
|
3192
3192
|
try {
|
|
3193
|
-
const info =
|
|
3193
|
+
const info = execSync3(`ps -p ${pid} -o ppid=,comm=`, {
|
|
3194
3194
|
encoding: "utf8",
|
|
3195
3195
|
timeout: 2e3
|
|
3196
3196
|
}).trim();
|
|
@@ -3249,7 +3249,7 @@ __export(active_agent_exports, {
|
|
|
3249
3249
|
writeActiveAgent: () => writeActiveAgent
|
|
3250
3250
|
});
|
|
3251
3251
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
|
|
3252
|
-
import { execSync as
|
|
3252
|
+
import { execSync as execSync4 } from "child_process";
|
|
3253
3253
|
import path9 from "path";
|
|
3254
3254
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
3255
3255
|
if (candidate === baseName) return true;
|
|
@@ -3341,7 +3341,7 @@ function getActiveAgent() {
|
|
|
3341
3341
|
} catch {
|
|
3342
3342
|
}
|
|
3343
3343
|
try {
|
|
3344
|
-
const sessionName =
|
|
3344
|
+
const sessionName = execSync4(
|
|
3345
3345
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
3346
3346
|
{ encoding: "utf8", timeout: 2e3 }
|
|
3347
3347
|
).trim();
|
|
@@ -3460,7 +3460,7 @@ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdi
|
|
|
3460
3460
|
import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
|
|
3461
3461
|
import path12 from "path";
|
|
3462
3462
|
import os9 from "os";
|
|
3463
|
-
import { execSync as
|
|
3463
|
+
import { execSync as execSync5 } from "child_process";
|
|
3464
3464
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3465
3465
|
function resolvePackageRoot() {
|
|
3466
3466
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
@@ -3800,6 +3800,7 @@ import { createHash } from "crypto";
|
|
|
3800
3800
|
// src/lib/keychain.ts
|
|
3801
3801
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3802
3802
|
import { existsSync as existsSync6 } from "fs";
|
|
3803
|
+
import { execSync as execSync2 } from "child_process";
|
|
3803
3804
|
import path6 from "path";
|
|
3804
3805
|
import os5 from "os";
|
|
3805
3806
|
var SERVICE = "exe-mem";
|
|
@@ -3810,6 +3811,59 @@ function getKeyDir() {
|
|
|
3810
3811
|
function getKeyPath() {
|
|
3811
3812
|
return path6.join(getKeyDir(), "master.key");
|
|
3812
3813
|
}
|
|
3814
|
+
function macKeychainGet() {
|
|
3815
|
+
if (process.platform !== "darwin") return null;
|
|
3816
|
+
try {
|
|
3817
|
+
return execSync2(
|
|
3818
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3819
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3820
|
+
).trim();
|
|
3821
|
+
} catch {
|
|
3822
|
+
return null;
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
function macKeychainSet(value) {
|
|
3826
|
+
if (process.platform !== "darwin") return false;
|
|
3827
|
+
try {
|
|
3828
|
+
try {
|
|
3829
|
+
execSync2(
|
|
3830
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3831
|
+
{ timeout: 5e3 }
|
|
3832
|
+
);
|
|
3833
|
+
} catch {
|
|
3834
|
+
}
|
|
3835
|
+
execSync2(
|
|
3836
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3837
|
+
{ timeout: 5e3 }
|
|
3838
|
+
);
|
|
3839
|
+
return true;
|
|
3840
|
+
} catch {
|
|
3841
|
+
return false;
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
function linuxSecretGet() {
|
|
3845
|
+
if (process.platform !== "linux") return null;
|
|
3846
|
+
try {
|
|
3847
|
+
return execSync2(
|
|
3848
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3849
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
3850
|
+
).trim();
|
|
3851
|
+
} catch {
|
|
3852
|
+
return null;
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
function linuxSecretSet(value) {
|
|
3856
|
+
if (process.platform !== "linux") return false;
|
|
3857
|
+
try {
|
|
3858
|
+
execSync2(
|
|
3859
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
3860
|
+
{ timeout: 5e3 }
|
|
3861
|
+
);
|
|
3862
|
+
return true;
|
|
3863
|
+
} catch {
|
|
3864
|
+
return false;
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3813
3867
|
async function tryKeytar() {
|
|
3814
3868
|
try {
|
|
3815
3869
|
return await import("keytar");
|
|
@@ -3817,13 +3871,64 @@ async function tryKeytar() {
|
|
|
3817
3871
|
return null;
|
|
3818
3872
|
}
|
|
3819
3873
|
}
|
|
3874
|
+
var ENCRYPTED_PREFIX = "enc:";
|
|
3875
|
+
function deriveMachineKey() {
|
|
3876
|
+
try {
|
|
3877
|
+
const crypto3 = __require("crypto");
|
|
3878
|
+
const material = [
|
|
3879
|
+
os5.hostname(),
|
|
3880
|
+
os5.userInfo().username,
|
|
3881
|
+
os5.arch(),
|
|
3882
|
+
os5.platform(),
|
|
3883
|
+
// Machine ID on Linux (stable across reboots)
|
|
3884
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
3885
|
+
].join("|");
|
|
3886
|
+
return crypto3.createHash("sha256").update(material).digest();
|
|
3887
|
+
} catch {
|
|
3888
|
+
return null;
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
function readMachineId() {
|
|
3892
|
+
try {
|
|
3893
|
+
const { readFileSync: readFileSync10 } = __require("fs");
|
|
3894
|
+
return readFileSync10("/etc/machine-id", "utf-8").trim();
|
|
3895
|
+
} catch {
|
|
3896
|
+
return "";
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
3900
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
3901
|
+
try {
|
|
3902
|
+
const crypto3 = __require("crypto");
|
|
3903
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
3904
|
+
if (parts.length !== 3) return null;
|
|
3905
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
3906
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
3907
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
3908
|
+
const decipher = crypto3.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
3909
|
+
decipher.setAuthTag(authTag);
|
|
3910
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
3911
|
+
decrypted += decipher.final("utf-8");
|
|
3912
|
+
return decrypted;
|
|
3913
|
+
} catch {
|
|
3914
|
+
return null;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3820
3917
|
async function getMasterKey() {
|
|
3918
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
3919
|
+
if (nativeValue) {
|
|
3920
|
+
return Buffer.from(nativeValue, "base64");
|
|
3921
|
+
}
|
|
3821
3922
|
const keytar = await tryKeytar();
|
|
3822
3923
|
if (keytar) {
|
|
3823
3924
|
try {
|
|
3824
|
-
const
|
|
3825
|
-
if (
|
|
3826
|
-
|
|
3925
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3926
|
+
if (keytarValue) {
|
|
3927
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
3928
|
+
if (migrated) {
|
|
3929
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
3930
|
+
}
|
|
3931
|
+
return Buffer.from(keytarValue, "base64");
|
|
3827
3932
|
}
|
|
3828
3933
|
} catch {
|
|
3829
3934
|
}
|
|
@@ -3837,8 +3942,31 @@ async function getMasterKey() {
|
|
|
3837
3942
|
return null;
|
|
3838
3943
|
}
|
|
3839
3944
|
try {
|
|
3840
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
3841
|
-
|
|
3945
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
3946
|
+
let b64Value;
|
|
3947
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
3948
|
+
const machineKey = deriveMachineKey();
|
|
3949
|
+
if (!machineKey) {
|
|
3950
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
3951
|
+
return null;
|
|
3952
|
+
}
|
|
3953
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
3954
|
+
if (!decrypted) {
|
|
3955
|
+
process.stderr.write(
|
|
3956
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
3957
|
+
);
|
|
3958
|
+
return null;
|
|
3959
|
+
}
|
|
3960
|
+
b64Value = decrypted;
|
|
3961
|
+
} else {
|
|
3962
|
+
b64Value = content;
|
|
3963
|
+
}
|
|
3964
|
+
const key = Buffer.from(b64Value, "base64");
|
|
3965
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
3966
|
+
if (migrated) {
|
|
3967
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
3968
|
+
}
|
|
3969
|
+
return key;
|
|
3842
3970
|
} catch (err) {
|
|
3843
3971
|
process.stderr.write(
|
|
3844
3972
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
package/dist/bin/exe-status.js
CHANGED
|
@@ -1062,8 +1062,8 @@ function findPackageRoot() {
|
|
|
1062
1062
|
function getAvailableMemoryGB() {
|
|
1063
1063
|
if (process.platform === "darwin") {
|
|
1064
1064
|
try {
|
|
1065
|
-
const { execSync:
|
|
1066
|
-
const vmstat =
|
|
1065
|
+
const { execSync: execSync6 } = __require("child_process");
|
|
1066
|
+
const vmstat = execSync6("vm_stat", { encoding: "utf8" });
|
|
1067
1067
|
const pageSize = 16384;
|
|
1068
1068
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1069
1069
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2802,6 +2802,7 @@ var init_database = __esm({
|
|
|
2802
2802
|
// src/lib/keychain.ts
|
|
2803
2803
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2804
2804
|
import { existsSync as existsSync6 } from "fs";
|
|
2805
|
+
import { execSync as execSync2 } from "child_process";
|
|
2805
2806
|
import path6 from "path";
|
|
2806
2807
|
import os5 from "os";
|
|
2807
2808
|
function getKeyDir() {
|
|
@@ -2810,6 +2811,59 @@ function getKeyDir() {
|
|
|
2810
2811
|
function getKeyPath() {
|
|
2811
2812
|
return path6.join(getKeyDir(), "master.key");
|
|
2812
2813
|
}
|
|
2814
|
+
function macKeychainGet() {
|
|
2815
|
+
if (process.platform !== "darwin") return null;
|
|
2816
|
+
try {
|
|
2817
|
+
return execSync2(
|
|
2818
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
2819
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2820
|
+
).trim();
|
|
2821
|
+
} catch {
|
|
2822
|
+
return null;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
function macKeychainSet(value) {
|
|
2826
|
+
if (process.platform !== "darwin") return false;
|
|
2827
|
+
try {
|
|
2828
|
+
try {
|
|
2829
|
+
execSync2(
|
|
2830
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
2831
|
+
{ timeout: 5e3 }
|
|
2832
|
+
);
|
|
2833
|
+
} catch {
|
|
2834
|
+
}
|
|
2835
|
+
execSync2(
|
|
2836
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
2837
|
+
{ timeout: 5e3 }
|
|
2838
|
+
);
|
|
2839
|
+
return true;
|
|
2840
|
+
} catch {
|
|
2841
|
+
return false;
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
function linuxSecretGet() {
|
|
2845
|
+
if (process.platform !== "linux") return null;
|
|
2846
|
+
try {
|
|
2847
|
+
return execSync2(
|
|
2848
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
2849
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
2850
|
+
).trim();
|
|
2851
|
+
} catch {
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
function linuxSecretSet(value) {
|
|
2856
|
+
if (process.platform !== "linux") return false;
|
|
2857
|
+
try {
|
|
2858
|
+
execSync2(
|
|
2859
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
2860
|
+
{ timeout: 5e3 }
|
|
2861
|
+
);
|
|
2862
|
+
return true;
|
|
2863
|
+
} catch {
|
|
2864
|
+
return false;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2813
2867
|
async function tryKeytar() {
|
|
2814
2868
|
try {
|
|
2815
2869
|
return await import("keytar");
|
|
@@ -2817,13 +2871,63 @@ async function tryKeytar() {
|
|
|
2817
2871
|
return null;
|
|
2818
2872
|
}
|
|
2819
2873
|
}
|
|
2874
|
+
function deriveMachineKey() {
|
|
2875
|
+
try {
|
|
2876
|
+
const crypto2 = __require("crypto");
|
|
2877
|
+
const material = [
|
|
2878
|
+
os5.hostname(),
|
|
2879
|
+
os5.userInfo().username,
|
|
2880
|
+
os5.arch(),
|
|
2881
|
+
os5.platform(),
|
|
2882
|
+
// Machine ID on Linux (stable across reboots)
|
|
2883
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
2884
|
+
].join("|");
|
|
2885
|
+
return crypto2.createHash("sha256").update(material).digest();
|
|
2886
|
+
} catch {
|
|
2887
|
+
return null;
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
function readMachineId() {
|
|
2891
|
+
try {
|
|
2892
|
+
const { readFileSync: readFileSync10 } = __require("fs");
|
|
2893
|
+
return readFileSync10("/etc/machine-id", "utf-8").trim();
|
|
2894
|
+
} catch {
|
|
2895
|
+
return "";
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
2899
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
2900
|
+
try {
|
|
2901
|
+
const crypto2 = __require("crypto");
|
|
2902
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
2903
|
+
if (parts.length !== 3) return null;
|
|
2904
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
2905
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
2906
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
2907
|
+
const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
2908
|
+
decipher.setAuthTag(authTag);
|
|
2909
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
2910
|
+
decrypted += decipher.final("utf-8");
|
|
2911
|
+
return decrypted;
|
|
2912
|
+
} catch {
|
|
2913
|
+
return null;
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2820
2916
|
async function getMasterKey() {
|
|
2917
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
2918
|
+
if (nativeValue) {
|
|
2919
|
+
return Buffer.from(nativeValue, "base64");
|
|
2920
|
+
}
|
|
2821
2921
|
const keytar = await tryKeytar();
|
|
2822
2922
|
if (keytar) {
|
|
2823
2923
|
try {
|
|
2824
|
-
const
|
|
2825
|
-
if (
|
|
2826
|
-
|
|
2924
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
2925
|
+
if (keytarValue) {
|
|
2926
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
2927
|
+
if (migrated) {
|
|
2928
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
2929
|
+
}
|
|
2930
|
+
return Buffer.from(keytarValue, "base64");
|
|
2827
2931
|
}
|
|
2828
2932
|
} catch {
|
|
2829
2933
|
}
|
|
@@ -2837,8 +2941,31 @@ async function getMasterKey() {
|
|
|
2837
2941
|
return null;
|
|
2838
2942
|
}
|
|
2839
2943
|
try {
|
|
2840
|
-
const content = await readFile3(keyPath, "utf-8");
|
|
2841
|
-
|
|
2944
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
2945
|
+
let b64Value;
|
|
2946
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
2947
|
+
const machineKey = deriveMachineKey();
|
|
2948
|
+
if (!machineKey) {
|
|
2949
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
2950
|
+
return null;
|
|
2951
|
+
}
|
|
2952
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
2953
|
+
if (!decrypted) {
|
|
2954
|
+
process.stderr.write(
|
|
2955
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
2956
|
+
);
|
|
2957
|
+
return null;
|
|
2958
|
+
}
|
|
2959
|
+
b64Value = decrypted;
|
|
2960
|
+
} else {
|
|
2961
|
+
b64Value = content;
|
|
2962
|
+
}
|
|
2963
|
+
const key = Buffer.from(b64Value, "base64");
|
|
2964
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
2965
|
+
if (migrated) {
|
|
2966
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
2967
|
+
}
|
|
2968
|
+
return key;
|
|
2842
2969
|
} catch (err) {
|
|
2843
2970
|
process.stderr.write(
|
|
2844
2971
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2847,12 +2974,13 @@ async function getMasterKey() {
|
|
|
2847
2974
|
return null;
|
|
2848
2975
|
}
|
|
2849
2976
|
}
|
|
2850
|
-
var SERVICE, ACCOUNT;
|
|
2977
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
2851
2978
|
var init_keychain = __esm({
|
|
2852
2979
|
"src/lib/keychain.ts"() {
|
|
2853
2980
|
"use strict";
|
|
2854
2981
|
SERVICE = "exe-mem";
|
|
2855
2982
|
ACCOUNT = "master-key";
|
|
2983
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
2856
2984
|
}
|
|
2857
2985
|
});
|
|
2858
2986
|
|
|
@@ -4095,7 +4223,7 @@ var init_session_registry = __esm({
|
|
|
4095
4223
|
});
|
|
4096
4224
|
|
|
4097
4225
|
// src/lib/session-key.ts
|
|
4098
|
-
import { execSync as
|
|
4226
|
+
import { execSync as execSync4 } from "child_process";
|
|
4099
4227
|
function normalizeCommand(command) {
|
|
4100
4228
|
const trimmed = command.trim().toLowerCase();
|
|
4101
4229
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -4114,7 +4242,7 @@ function resolveRuntimeProcess() {
|
|
|
4114
4242
|
let pid = process.ppid;
|
|
4115
4243
|
for (let i = 0; i < 10; i++) {
|
|
4116
4244
|
try {
|
|
4117
|
-
const info =
|
|
4245
|
+
const info = execSync4(`ps -p ${pid} -o ppid=,comm=`, {
|
|
4118
4246
|
encoding: "utf8",
|
|
4119
4247
|
timeout: 2e3
|
|
4120
4248
|
}).trim();
|
|
@@ -4280,7 +4408,7 @@ var init_transport = __esm({
|
|
|
4280
4408
|
});
|
|
4281
4409
|
|
|
4282
4410
|
// src/lib/cc-agent-support.ts
|
|
4283
|
-
import { execSync as
|
|
4411
|
+
import { execSync as execSync5 } from "child_process";
|
|
4284
4412
|
var init_cc_agent_support = __esm({
|
|
4285
4413
|
"src/lib/cc-agent-support.ts"() {
|
|
4286
4414
|
"use strict";
|
|
@@ -4562,13 +4690,13 @@ async function fastDbInit() {
|
|
|
4562
4690
|
init_database();
|
|
4563
4691
|
|
|
4564
4692
|
// src/lib/tmux-status.ts
|
|
4565
|
-
import { execSync as
|
|
4693
|
+
import { execSync as execSync3 } from "child_process";
|
|
4566
4694
|
function inTmux() {
|
|
4567
4695
|
if (process.env.TMUX || process.env.TMUX_PANE) return true;
|
|
4568
4696
|
const term = process.env.TERM ?? "";
|
|
4569
4697
|
if (term.startsWith("tmux") || term.startsWith("screen")) return true;
|
|
4570
4698
|
try {
|
|
4571
|
-
|
|
4699
|
+
execSync3("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
4572
4700
|
encoding: "utf8",
|
|
4573
4701
|
timeout: 2e3
|
|
4574
4702
|
});
|
|
@@ -4578,12 +4706,12 @@ function inTmux() {
|
|
|
4578
4706
|
try {
|
|
4579
4707
|
let pid = process.ppid;
|
|
4580
4708
|
for (let depth = 0; depth < 8 && pid > 1; depth++) {
|
|
4581
|
-
const comm =
|
|
4709
|
+
const comm = execSync3(`ps -p ${pid} -o comm= 2>/dev/null`, {
|
|
4582
4710
|
encoding: "utf8",
|
|
4583
4711
|
timeout: 1e3
|
|
4584
4712
|
}).trim();
|
|
4585
4713
|
if (/tmux/.test(comm)) return true;
|
|
4586
|
-
const ppid =
|
|
4714
|
+
const ppid = execSync3(`ps -p ${pid} -o ppid= 2>/dev/null`, {
|
|
4587
4715
|
encoding: "utf8",
|
|
4588
4716
|
timeout: 1e3
|
|
4589
4717
|
}).trim();
|
|
@@ -4596,7 +4724,7 @@ function inTmux() {
|
|
|
4596
4724
|
}
|
|
4597
4725
|
function listTmuxSessions() {
|
|
4598
4726
|
try {
|
|
4599
|
-
const out =
|
|
4727
|
+
const out = execSync3("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
4600
4728
|
encoding: "utf8",
|
|
4601
4729
|
timeout: 3e3
|
|
4602
4730
|
});
|
|
@@ -4607,7 +4735,7 @@ function listTmuxSessions() {
|
|
|
4607
4735
|
}
|
|
4608
4736
|
function capturePaneLines(windowName, lines = 10) {
|
|
4609
4737
|
try {
|
|
4610
|
-
const out =
|
|
4738
|
+
const out = execSync3(
|
|
4611
4739
|
`tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
|
|
4612
4740
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4613
4741
|
);
|
|
@@ -4618,7 +4746,7 @@ function capturePaneLines(windowName, lines = 10) {
|
|
|
4618
4746
|
}
|
|
4619
4747
|
function getPaneCwd(windowName) {
|
|
4620
4748
|
try {
|
|
4621
|
-
const out =
|
|
4749
|
+
const out = execSync3(
|
|
4622
4750
|
`tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
|
|
4623
4751
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4624
4752
|
);
|
|
@@ -4629,7 +4757,7 @@ function getPaneCwd(windowName) {
|
|
|
4629
4757
|
}
|
|
4630
4758
|
function projectFromPath(dir) {
|
|
4631
4759
|
try {
|
|
4632
|
-
const root =
|
|
4760
|
+
const root = execSync3("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
|
|
4633
4761
|
encoding: "utf8",
|
|
4634
4762
|
timeout: 3e3
|
|
4635
4763
|
}).trim();
|
|
@@ -4688,7 +4816,7 @@ function getEmployeeStatuses(employeeNames) {
|
|
|
4688
4816
|
}
|
|
4689
4817
|
let paneAlive = true;
|
|
4690
4818
|
try {
|
|
4691
|
-
const paneStatus =
|
|
4819
|
+
const paneStatus = execSync3(
|
|
4692
4820
|
`tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
|
|
4693
4821
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4694
4822
|
).trim();
|