@askexenow/exe-os 0.8.61 → 0.8.63
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 +2 -3
- package/dist/bin/backfill-responses.js +3 -4
- package/dist/bin/backfill-vectors.js +0 -1
- package/dist/bin/cleanup-stale-review-tasks.js +0 -1
- package/dist/bin/cli.js +1654 -397
- package/dist/bin/exe-assign.js +0 -1
- package/dist/bin/exe-boot.js +61 -84
- package/dist/bin/exe-cloud.js +28 -60
- package/dist/bin/exe-dispatch.js +0 -1
- package/dist/bin/exe-doctor.js +0 -1
- package/dist/bin/exe-export-behaviors.js +1 -2
- package/dist/bin/exe-forget.js +0 -1
- package/dist/bin/exe-gateway.js +16 -17
- package/dist/bin/exe-heartbeat.js +1 -2
- package/dist/bin/exe-kill.js +2 -3
- package/dist/bin/exe-launch-agent.js +1 -2
- package/dist/bin/exe-link.js +49 -78
- package/dist/bin/exe-pending-messages.js +1 -2
- package/dist/bin/exe-pending-notifications.js +0 -1
- package/dist/bin/exe-pending-reviews.js +1 -2
- package/dist/bin/exe-review.js +0 -1
- package/dist/bin/exe-search.js +2 -3
- package/dist/bin/exe-session-cleanup.js +4 -5
- package/dist/bin/exe-status.js +0 -1
- package/dist/bin/exe-team.js +0 -1
- package/dist/bin/git-sweep.js +0 -1
- package/dist/bin/graph-backfill.js +5 -6
- package/dist/bin/graph-export.js +0 -1
- package/dist/bin/scan-tasks.js +0 -1
- package/dist/bin/setup.js +1460 -115
- package/dist/bin/shard-migrate.js +0 -1
- package/dist/bin/wiki-sync.js +0 -1
- package/dist/gateway/index.js +16 -17
- package/dist/hooks/bug-report-worker.js +11 -12
- package/dist/hooks/commit-complete.js +0 -1
- package/dist/hooks/error-recall.js +2 -3
- package/dist/hooks/ingest-worker.js +14 -15
- package/dist/hooks/instructions-loaded.js +0 -1
- package/dist/hooks/notification.js +0 -1
- package/dist/hooks/post-compact.js +0 -1
- package/dist/hooks/pre-compact.js +2 -3
- package/dist/hooks/pre-tool-use.js +0 -1
- package/dist/hooks/prompt-ingest-worker.js +2 -3
- package/dist/hooks/prompt-submit.js +6 -7
- package/dist/hooks/response-ingest-worker.js +2 -3
- package/dist/hooks/session-end.js +3 -4
- package/dist/hooks/session-start.js +2 -3
- package/dist/hooks/stop.js +2 -3
- package/dist/hooks/subagent-stop.js +0 -1
- package/dist/hooks/summary-worker.js +51 -74
- package/dist/index.js +7 -8
- package/dist/lib/cloud-sync.js +21 -12
- package/dist/lib/consolidation.js +0 -1
- package/dist/lib/exe-daemon.js +33 -65
- package/dist/lib/hybrid-search.js +2 -3
- package/dist/lib/keychain.js +19 -58
- package/dist/lib/schedules.js +2 -3
- package/dist/lib/store.js +0 -1
- package/dist/mcp/server.js +29 -30
- package/dist/runtime/index.js +2 -3
- package/dist/tui/App.js +24 -56
- package/package.json +1 -1
|
@@ -976,7 +976,6 @@ import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
|
976
976
|
import { existsSync } from "fs";
|
|
977
977
|
import path from "path";
|
|
978
978
|
import os from "os";
|
|
979
|
-
import crypto from "crypto";
|
|
980
979
|
function getKeyDir() {
|
|
981
980
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
982
981
|
}
|
|
@@ -1041,65 +1040,34 @@ async function deleteMasterKey() {
|
|
|
1041
1040
|
await unlink(keyPath);
|
|
1042
1041
|
}
|
|
1043
1042
|
}
|
|
1044
|
-
function
|
|
1045
|
-
if (key.length !== 32) {
|
|
1046
|
-
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
1047
|
-
}
|
|
1048
|
-
const hash = crypto.createHash("sha256").update(key).digest();
|
|
1049
|
-
const checksumByte = hash[0];
|
|
1050
|
-
let bits = "";
|
|
1051
|
-
for (const byte of key) {
|
|
1052
|
-
bits += byte.toString(2).padStart(8, "0");
|
|
1053
|
-
}
|
|
1054
|
-
bits += checksumByte.toString(2).padStart(8, "0");
|
|
1055
|
-
const words = [];
|
|
1056
|
-
let wordlist;
|
|
1043
|
+
async function loadBip39() {
|
|
1057
1044
|
try {
|
|
1058
|
-
|
|
1059
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
1060
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
1045
|
+
return await import("bip39");
|
|
1061
1046
|
} catch {
|
|
1062
|
-
throw new Error(
|
|
1047
|
+
throw new Error(
|
|
1048
|
+
"bip39 package not found. Run: npm install -g bip39\nOr reinstall exe-os: npm install -g @askexenow/exe-os"
|
|
1049
|
+
);
|
|
1063
1050
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1051
|
+
}
|
|
1052
|
+
async function exportMnemonic(key) {
|
|
1053
|
+
if (key.length !== 32) {
|
|
1054
|
+
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
1067
1055
|
}
|
|
1068
|
-
|
|
1056
|
+
const { entropyToMnemonic } = await loadBip39();
|
|
1057
|
+
return entropyToMnemonic(key.toString("hex"));
|
|
1069
1058
|
}
|
|
1070
|
-
function importMnemonic(mnemonic) {
|
|
1071
|
-
const
|
|
1059
|
+
async function importMnemonic(mnemonic) {
|
|
1060
|
+
const trimmed = mnemonic.trim();
|
|
1061
|
+
const words = trimmed.split(/\s+/);
|
|
1072
1062
|
if (words.length !== 24) {
|
|
1073
1063
|
throw new Error(`Expected 24 words, got ${words.length}`);
|
|
1074
1064
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
1079
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
1080
|
-
} catch {
|
|
1081
|
-
throw new Error("bip39 package required. Install with: npm install bip39");
|
|
1082
|
-
}
|
|
1083
|
-
let bits = "";
|
|
1084
|
-
for (const word of words) {
|
|
1085
|
-
const index = wordlist.indexOf(word.toLowerCase());
|
|
1086
|
-
if (index === -1) {
|
|
1087
|
-
throw new Error(`Invalid BIP39 word: "${word}"`);
|
|
1088
|
-
}
|
|
1089
|
-
bits += index.toString(2).padStart(11, "0");
|
|
1090
|
-
}
|
|
1091
|
-
const entropyBits = bits.slice(0, 256);
|
|
1092
|
-
const checksumBits = bits.slice(256, 264);
|
|
1093
|
-
const key = Buffer.alloc(32);
|
|
1094
|
-
for (let i = 0; i < 32; i++) {
|
|
1095
|
-
key[i] = parseInt(entropyBits.slice(i * 8, (i + 1) * 8), 2);
|
|
1065
|
+
const { validateMnemonic, mnemonicToEntropy } = await loadBip39();
|
|
1066
|
+
if (!validateMnemonic(trimmed)) {
|
|
1067
|
+
throw new Error("Invalid mnemonic \u2014 check for typos or missing words");
|
|
1096
1068
|
}
|
|
1097
|
-
const
|
|
1098
|
-
|
|
1099
|
-
if (checksumBits !== expectedChecksum) {
|
|
1100
|
-
throw new Error("Invalid mnemonic checksum");
|
|
1101
|
-
}
|
|
1102
|
-
return key;
|
|
1069
|
+
const entropy = mnemonicToEntropy(trimmed);
|
|
1070
|
+
return Buffer.from(entropy, "hex");
|
|
1103
1071
|
}
|
|
1104
1072
|
var SERVICE, ACCOUNT;
|
|
1105
1073
|
var init_keychain = __esm({
|
|
@@ -1836,7 +1804,7 @@ ${p.content}`).join("\n\n");
|
|
|
1836
1804
|
});
|
|
1837
1805
|
|
|
1838
1806
|
// src/lib/notifications.ts
|
|
1839
|
-
import
|
|
1807
|
+
import crypto from "crypto";
|
|
1840
1808
|
import path4 from "path";
|
|
1841
1809
|
import os3 from "os";
|
|
1842
1810
|
import {
|
|
@@ -1849,7 +1817,7 @@ import {
|
|
|
1849
1817
|
async function writeNotification(notification) {
|
|
1850
1818
|
try {
|
|
1851
1819
|
const client = getClient();
|
|
1852
|
-
const id =
|
|
1820
|
+
const id = crypto.randomUUID();
|
|
1853
1821
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1854
1822
|
await client.execute({
|
|
1855
1823
|
sql: `INSERT INTO notifications (id, agent_id, agent_role, event, project, summary, task_file, read, created_at)
|
|
@@ -3258,13 +3226,13 @@ __export(crypto_exports, {
|
|
|
3258
3226
|
initSyncCrypto: () => initSyncCrypto,
|
|
3259
3227
|
isSyncCryptoInitialized: () => isSyncCryptoInitialized
|
|
3260
3228
|
});
|
|
3261
|
-
import
|
|
3229
|
+
import crypto2 from "crypto";
|
|
3262
3230
|
function initSyncCrypto(masterKey) {
|
|
3263
3231
|
if (masterKey.length !== 32) {
|
|
3264
3232
|
throw new Error(`Master key must be 32 bytes, got ${masterKey.length}`);
|
|
3265
3233
|
}
|
|
3266
3234
|
_syncKey = Buffer.from(
|
|
3267
|
-
|
|
3235
|
+
crypto2.hkdfSync("sha256", masterKey, "", SYNC_HKDF_INFO, 32)
|
|
3268
3236
|
);
|
|
3269
3237
|
}
|
|
3270
3238
|
function isSyncCryptoInitialized() {
|
|
@@ -3278,8 +3246,8 @@ function requireSyncKey() {
|
|
|
3278
3246
|
}
|
|
3279
3247
|
function encryptSyncBlob(data) {
|
|
3280
3248
|
const key = requireSyncKey();
|
|
3281
|
-
const iv =
|
|
3282
|
-
const cipher =
|
|
3249
|
+
const iv = crypto2.randomBytes(IV_LENGTH);
|
|
3250
|
+
const cipher = crypto2.createCipheriv(ALGORITHM, key, iv);
|
|
3283
3251
|
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
3284
3252
|
const tag = cipher.getAuthTag();
|
|
3285
3253
|
return Buffer.concat([iv, encrypted, tag]).toString("base64");
|
|
@@ -3293,7 +3261,7 @@ function decryptSyncBlob(ciphertext) {
|
|
|
3293
3261
|
const iv = combined.subarray(0, IV_LENGTH);
|
|
3294
3262
|
const tag = combined.subarray(combined.length - TAG_LENGTH);
|
|
3295
3263
|
const encrypted = combined.subarray(IV_LENGTH, combined.length - TAG_LENGTH);
|
|
3296
|
-
const decipher =
|
|
3264
|
+
const decipher = crypto2.createDecipheriv(ALGORITHM, key, iv);
|
|
3297
3265
|
decipher.setAuthTag(tag);
|
|
3298
3266
|
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
3299
3267
|
}
|
|
@@ -3358,7 +3326,7 @@ __export(cloud_sync_exports, {
|
|
|
3358
3326
|
recordRosterDeletion: () => recordRosterDeletion
|
|
3359
3327
|
});
|
|
3360
3328
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync12, readdirSync as readdirSync4, mkdirSync as mkdirSync6, appendFileSync as appendFileSync2, unlinkSync as unlinkSync4, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
3361
|
-
import
|
|
3329
|
+
import crypto3 from "crypto";
|
|
3362
3330
|
import path13 from "path";
|
|
3363
3331
|
import { homedir } from "os";
|
|
3364
3332
|
function sqlSafe(v) {
|
|
@@ -3741,7 +3709,7 @@ function buildRosterBlob(paths) {
|
|
|
3741
3709
|
}
|
|
3742
3710
|
const deletedNames = consumeRosterDeletions();
|
|
3743
3711
|
const content = JSON.stringify({ roster, identities, config, deletedNames });
|
|
3744
|
-
const hash =
|
|
3712
|
+
const hash = crypto3.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
3745
3713
|
return { roster, identities, config, deletedNames, version: hash };
|
|
3746
3714
|
}
|
|
3747
3715
|
async function cloudPushRoster(config) {
|
|
@@ -3831,21 +3799,30 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
3831
3799
|
const localEmployees = await loadEmployees(rosterPath);
|
|
3832
3800
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
3833
3801
|
let added = 0;
|
|
3802
|
+
let identitiesUpdated = 0;
|
|
3834
3803
|
for (const remoteEmp of remote.roster) {
|
|
3835
|
-
if (localNames.has(remoteEmp.name))
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3804
|
+
if (!localNames.has(remoteEmp.name)) {
|
|
3805
|
+
localEmployees.push(remoteEmp);
|
|
3806
|
+
localNames.add(remoteEmp.name);
|
|
3807
|
+
added++;
|
|
3808
|
+
try {
|
|
3809
|
+
registerBinSymlinks(remoteEmp.name);
|
|
3810
|
+
} catch {
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
const remoteIdentity = remote.identities[`${remoteEmp.name}.md`];
|
|
3814
|
+
if (remoteIdentity) {
|
|
3840
3815
|
if (!existsSync12(identityDir)) mkdirSync6(identityDir, { recursive: true });
|
|
3841
3816
|
const idPath = path13.join(identityDir, `${remoteEmp.name}.md`);
|
|
3842
|
-
|
|
3843
|
-
|
|
3817
|
+
let localIdentity = null;
|
|
3818
|
+
try {
|
|
3819
|
+
localIdentity = existsSync12(idPath) ? readFileSync9(idPath, "utf-8") : null;
|
|
3820
|
+
} catch {
|
|
3821
|
+
}
|
|
3822
|
+
if (localIdentity !== remoteIdentity) {
|
|
3823
|
+
writeFileSync5(idPath, remoteIdentity, "utf-8");
|
|
3824
|
+
identitiesUpdated++;
|
|
3844
3825
|
}
|
|
3845
|
-
}
|
|
3846
|
-
try {
|
|
3847
|
-
registerBinSymlinks(remoteEmp.name);
|
|
3848
|
-
} catch {
|
|
3849
3826
|
}
|
|
3850
3827
|
}
|
|
3851
3828
|
let removed = 0;
|
|
@@ -3867,7 +3844,7 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
3867
3844
|
} catch {
|
|
3868
3845
|
}
|
|
3869
3846
|
}
|
|
3870
|
-
return { added };
|
|
3847
|
+
return { added, identitiesUpdated };
|
|
3871
3848
|
});
|
|
3872
3849
|
}
|
|
3873
3850
|
async function cloudPushBlob(route, data, metaKey, config) {
|
|
@@ -4592,7 +4569,7 @@ function vectorToBlob(vector) {
|
|
|
4592
4569
|
init_database();
|
|
4593
4570
|
init_notifications();
|
|
4594
4571
|
init_task_scope();
|
|
4595
|
-
import
|
|
4572
|
+
import crypto4 from "crypto";
|
|
4596
4573
|
import { execSync as execSync4 } from "child_process";
|
|
4597
4574
|
import { existsSync as existsSync13, mkdirSync as mkdirSync7, openSync as openSync3, closeSync as closeSync3 } from "fs";
|
|
4598
4575
|
import path14 from "path";
|
|
@@ -4666,7 +4643,7 @@ async function main() {
|
|
|
4666
4643
|
process.exit(0);
|
|
4667
4644
|
}
|
|
4668
4645
|
await writeMemory({
|
|
4669
|
-
id:
|
|
4646
|
+
id: crypto4.randomUUID(),
|
|
4670
4647
|
agent_id: agentId,
|
|
4671
4648
|
agent_role: agentRole,
|
|
4672
4649
|
session_id: `auto-summary-${Date.now()}`,
|
package/dist/index.js
CHANGED
|
@@ -4219,7 +4219,6 @@ import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4
|
|
|
4219
4219
|
import { existsSync as existsSync11 } from "fs";
|
|
4220
4220
|
import path15 from "path";
|
|
4221
4221
|
import os7 from "os";
|
|
4222
|
-
import crypto6 from "crypto";
|
|
4223
4222
|
function getKeyDir() {
|
|
4224
4223
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path15.join(os7.homedir(), ".exe-os");
|
|
4225
4224
|
}
|
|
@@ -5379,7 +5378,7 @@ __export(error_detector_exports, {
|
|
|
5379
5378
|
errorFingerprint: () => errorFingerprint,
|
|
5380
5379
|
isExeOsError: () => isExeOsError
|
|
5381
5380
|
});
|
|
5382
|
-
import
|
|
5381
|
+
import crypto6 from "crypto";
|
|
5383
5382
|
function isRealStderr(stderr) {
|
|
5384
5383
|
const lines = stderr.trim().split("\n");
|
|
5385
5384
|
const meaningful = lines.filter(
|
|
@@ -5450,7 +5449,7 @@ function classifyError(errorText) {
|
|
|
5450
5449
|
}
|
|
5451
5450
|
function errorFingerprint(toolName, errorText) {
|
|
5452
5451
|
const normalized = errorText.replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/g, "TIMESTAMP").replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "UUID").replace(/\/Users\/[^\s]+/g, "PATH").replace(/:\d+:\d+/g, ":LINE:COL").slice(0, 200);
|
|
5453
|
-
return
|
|
5452
|
+
return crypto6.createHash("sha256").update(`${toolName}:${normalized}`).digest("hex").slice(0, 16);
|
|
5454
5453
|
}
|
|
5455
5454
|
var ERROR_PATTERNS, FILE_CONTENT_TOOLS, STDERR_IGNORE_PATTERNS, USER_ERROR_PATTERNS, SYSTEM_BUG_PATTERNS;
|
|
5456
5455
|
var init_error_detector = __esm({
|
|
@@ -6399,10 +6398,10 @@ __export(messaging_exports, {
|
|
|
6399
6398
|
sendMessage: () => sendMessage,
|
|
6400
6399
|
setWsClientSend: () => setWsClientSend
|
|
6401
6400
|
});
|
|
6402
|
-
import
|
|
6401
|
+
import crypto8 from "crypto";
|
|
6403
6402
|
function generateUlid() {
|
|
6404
6403
|
const timestamp = Date.now().toString(36).padStart(10, "0");
|
|
6405
|
-
const random =
|
|
6404
|
+
const random = crypto8.randomBytes(10).toString("hex").slice(0, 16);
|
|
6406
6405
|
return (timestamp + random).toUpperCase();
|
|
6407
6406
|
}
|
|
6408
6407
|
function rowToMessage(row) {
|
|
@@ -9088,11 +9087,11 @@ init_crm_bridge();
|
|
|
9088
9087
|
|
|
9089
9088
|
// src/lib/pipeline-router.ts
|
|
9090
9089
|
init_database();
|
|
9091
|
-
import
|
|
9090
|
+
import crypto7 from "crypto";
|
|
9092
9091
|
async function sinkConversationStore(msg, agentResponse, agentName) {
|
|
9093
9092
|
try {
|
|
9094
9093
|
const client = getClient();
|
|
9095
|
-
const id =
|
|
9094
|
+
const id = crypto7.randomUUID();
|
|
9096
9095
|
const mediaJson = msg.media ? JSON.stringify(msg.media) : null;
|
|
9097
9096
|
await client.execute({
|
|
9098
9097
|
sql: `INSERT INTO conversations
|
|
@@ -9142,7 +9141,7 @@ async function sinkMemory(msg, agentResponse, agentName) {
|
|
|
9142
9141
|
].filter(Boolean).join("\n");
|
|
9143
9142
|
const vector = await embed2(rawText);
|
|
9144
9143
|
await writeMemory2({
|
|
9145
|
-
id:
|
|
9144
|
+
id: crypto7.randomUUID(),
|
|
9146
9145
|
agent_id: agentName ?? "gateway",
|
|
9147
9146
|
agent_role: "gateway",
|
|
9148
9147
|
session_id: `gateway-${msg.platform}`,
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -725,21 +725,30 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
725
725
|
const localEmployees = await loadEmployees(rosterPath);
|
|
726
726
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
727
727
|
let added = 0;
|
|
728
|
+
let identitiesUpdated = 0;
|
|
728
729
|
for (const remoteEmp of remote.roster) {
|
|
729
|
-
if (localNames.has(remoteEmp.name))
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
730
|
+
if (!localNames.has(remoteEmp.name)) {
|
|
731
|
+
localEmployees.push(remoteEmp);
|
|
732
|
+
localNames.add(remoteEmp.name);
|
|
733
|
+
added++;
|
|
734
|
+
try {
|
|
735
|
+
registerBinSymlinks(remoteEmp.name);
|
|
736
|
+
} catch {
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const remoteIdentity = remote.identities[`${remoteEmp.name}.md`];
|
|
740
|
+
if (remoteIdentity) {
|
|
734
741
|
if (!existsSync4(identityDir)) mkdirSync2(identityDir, { recursive: true });
|
|
735
742
|
const idPath = path4.join(identityDir, `${remoteEmp.name}.md`);
|
|
736
|
-
|
|
737
|
-
|
|
743
|
+
let localIdentity = null;
|
|
744
|
+
try {
|
|
745
|
+
localIdentity = existsSync4(idPath) ? readFileSync4(idPath, "utf-8") : null;
|
|
746
|
+
} catch {
|
|
747
|
+
}
|
|
748
|
+
if (localIdentity !== remoteIdentity) {
|
|
749
|
+
writeFileSync2(idPath, remoteIdentity, "utf-8");
|
|
750
|
+
identitiesUpdated++;
|
|
738
751
|
}
|
|
739
|
-
}
|
|
740
|
-
try {
|
|
741
|
-
registerBinSymlinks(remoteEmp.name);
|
|
742
|
-
} catch {
|
|
743
752
|
}
|
|
744
753
|
}
|
|
745
754
|
let removed = 0;
|
|
@@ -761,7 +770,7 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
761
770
|
} catch {
|
|
762
771
|
}
|
|
763
772
|
}
|
|
764
|
-
return { added };
|
|
773
|
+
return { added, identitiesUpdated };
|
|
765
774
|
});
|
|
766
775
|
}
|
|
767
776
|
async function cloudPushBlob(route, data, metaKey, config) {
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -5135,7 +5135,6 @@ import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4
|
|
|
5135
5135
|
import { existsSync as existsSync13 } from "fs";
|
|
5136
5136
|
import path15 from "path";
|
|
5137
5137
|
import os7 from "os";
|
|
5138
|
-
import crypto6 from "crypto";
|
|
5139
5138
|
function getKeyDir() {
|
|
5140
5139
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path15.join(os7.homedir(), ".exe-os");
|
|
5141
5140
|
}
|
|
@@ -5200,65 +5199,34 @@ async function deleteMasterKey() {
|
|
|
5200
5199
|
await unlink(keyPath);
|
|
5201
5200
|
}
|
|
5202
5201
|
}
|
|
5203
|
-
function
|
|
5204
|
-
if (key.length !== 32) {
|
|
5205
|
-
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
5206
|
-
}
|
|
5207
|
-
const hash = crypto6.createHash("sha256").update(key).digest();
|
|
5208
|
-
const checksumByte = hash[0];
|
|
5209
|
-
let bits = "";
|
|
5210
|
-
for (const byte of key) {
|
|
5211
|
-
bits += byte.toString(2).padStart(8, "0");
|
|
5212
|
-
}
|
|
5213
|
-
bits += checksumByte.toString(2).padStart(8, "0");
|
|
5214
|
-
const words = [];
|
|
5215
|
-
let wordlist;
|
|
5202
|
+
async function loadBip39() {
|
|
5216
5203
|
try {
|
|
5217
|
-
|
|
5218
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
5219
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
5204
|
+
return await import("bip39");
|
|
5220
5205
|
} catch {
|
|
5221
|
-
throw new Error(
|
|
5206
|
+
throw new Error(
|
|
5207
|
+
"bip39 package not found. Run: npm install -g bip39\nOr reinstall exe-os: npm install -g @askexenow/exe-os"
|
|
5208
|
+
);
|
|
5222
5209
|
}
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5210
|
+
}
|
|
5211
|
+
async function exportMnemonic(key) {
|
|
5212
|
+
if (key.length !== 32) {
|
|
5213
|
+
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
5226
5214
|
}
|
|
5227
|
-
|
|
5215
|
+
const { entropyToMnemonic } = await loadBip39();
|
|
5216
|
+
return entropyToMnemonic(key.toString("hex"));
|
|
5228
5217
|
}
|
|
5229
|
-
function importMnemonic(mnemonic) {
|
|
5230
|
-
const
|
|
5218
|
+
async function importMnemonic(mnemonic) {
|
|
5219
|
+
const trimmed = mnemonic.trim();
|
|
5220
|
+
const words = trimmed.split(/\s+/);
|
|
5231
5221
|
if (words.length !== 24) {
|
|
5232
5222
|
throw new Error(`Expected 24 words, got ${words.length}`);
|
|
5233
5223
|
}
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
5238
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
5239
|
-
} catch {
|
|
5240
|
-
throw new Error("bip39 package required. Install with: npm install bip39");
|
|
5224
|
+
const { validateMnemonic, mnemonicToEntropy } = await loadBip39();
|
|
5225
|
+
if (!validateMnemonic(trimmed)) {
|
|
5226
|
+
throw new Error("Invalid mnemonic \u2014 check for typos or missing words");
|
|
5241
5227
|
}
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
const index = wordlist.indexOf(word.toLowerCase());
|
|
5245
|
-
if (index === -1) {
|
|
5246
|
-
throw new Error(`Invalid BIP39 word: "${word}"`);
|
|
5247
|
-
}
|
|
5248
|
-
bits += index.toString(2).padStart(11, "0");
|
|
5249
|
-
}
|
|
5250
|
-
const entropyBits = bits.slice(0, 256);
|
|
5251
|
-
const checksumBits = bits.slice(256, 264);
|
|
5252
|
-
const key = Buffer.alloc(32);
|
|
5253
|
-
for (let i = 0; i < 32; i++) {
|
|
5254
|
-
key[i] = parseInt(entropyBits.slice(i * 8, (i + 1) * 8), 2);
|
|
5255
|
-
}
|
|
5256
|
-
const hash = crypto6.createHash("sha256").update(key).digest();
|
|
5257
|
-
const expectedChecksum = hash[0].toString(2).padStart(8, "0");
|
|
5258
|
-
if (checksumBits !== expectedChecksum) {
|
|
5259
|
-
throw new Error("Invalid mnemonic checksum");
|
|
5260
|
-
}
|
|
5261
|
-
return key;
|
|
5228
|
+
const entropy = mnemonicToEntropy(trimmed);
|
|
5229
|
+
return Buffer.from(entropy, "hex");
|
|
5262
5230
|
}
|
|
5263
5231
|
var SERVICE, ACCOUNT;
|
|
5264
5232
|
var init_keychain = __esm({
|
|
@@ -7354,13 +7322,13 @@ __export(graph_rag_exports, {
|
|
|
7354
7322
|
resolveAlias: () => resolveAlias,
|
|
7355
7323
|
storeExtraction: () => storeExtraction
|
|
7356
7324
|
});
|
|
7357
|
-
import
|
|
7325
|
+
import crypto6 from "crypto";
|
|
7358
7326
|
function normalizeEntityName(name) {
|
|
7359
7327
|
return name.replace(/\s*\([^)]*\)\s*/g, "").trim().toLowerCase();
|
|
7360
7328
|
}
|
|
7361
7329
|
function entityId(name, type) {
|
|
7362
7330
|
const normalized = normalizeEntityName(name);
|
|
7363
|
-
return
|
|
7331
|
+
return crypto6.createHash("sha256").update(`${normalized}::${type.toLowerCase()}`).digest("hex").slice(0, 16);
|
|
7364
7332
|
}
|
|
7365
7333
|
async function resolveAlias(client, name) {
|
|
7366
7334
|
const normalized = normalizeEntityName(name);
|
|
@@ -7595,7 +7563,7 @@ async function storeExtraction(client, extraction, memoryId, timestamp) {
|
|
|
7595
7563
|
const targetAlias = await resolveAlias(client, r.target);
|
|
7596
7564
|
const sourceId = sourceAlias ?? entityId(r.source, r.sourceType);
|
|
7597
7565
|
const targetId = targetAlias ?? entityId(r.target, r.targetType);
|
|
7598
|
-
const relId =
|
|
7566
|
+
const relId = crypto6.randomUUID().slice(0, 16);
|
|
7599
7567
|
try {
|
|
7600
7568
|
await client.execute({
|
|
7601
7569
|
sql: `INSERT OR IGNORE INTO entities (id, name, type, first_seen, last_seen)
|
|
@@ -7641,7 +7609,7 @@ async function storeExtraction(client, extraction, memoryId, timestamp) {
|
|
|
7641
7609
|
}
|
|
7642
7610
|
}
|
|
7643
7611
|
for (const h of extraction.hyperedges) {
|
|
7644
|
-
const hId =
|
|
7612
|
+
const hId = crypto6.randomUUID().slice(0, 16);
|
|
7645
7613
|
try {
|
|
7646
7614
|
await client.execute({
|
|
7647
7615
|
sql: `INSERT OR IGNORE INTO hyperedges (id, label, relation, confidence, timestamp)
|
|
@@ -7705,7 +7673,7 @@ async function extractBatch(client, batchSize = 50, model = "claude-haiku-4-5-20
|
|
|
7705
7673
|
totalEntities += stored.entitiesStored;
|
|
7706
7674
|
totalRelationships += stored.relationshipsStored;
|
|
7707
7675
|
}
|
|
7708
|
-
const contentHash =
|
|
7676
|
+
const contentHash = crypto6.createHash("sha256").update(rawContent).digest("hex").slice(0, 32);
|
|
7709
7677
|
await client.execute({
|
|
7710
7678
|
sql: "UPDATE memories SET graph_extracted = 1, content_hash = ?, graph_extracted_hash = ? WHERE id = ?",
|
|
7711
7679
|
args: [contentHash, contentHash, memoryId]
|
|
@@ -7994,16 +7962,16 @@ __export(ws_auth_exports, {
|
|
|
7994
7962
|
deriveWsAuthToken: () => deriveWsAuthToken,
|
|
7995
7963
|
hashAuthToken: () => hashAuthToken
|
|
7996
7964
|
});
|
|
7997
|
-
import
|
|
7965
|
+
import crypto7 from "crypto";
|
|
7998
7966
|
function deriveWsAuthToken(masterKey) {
|
|
7999
|
-
return Buffer.from(
|
|
7967
|
+
return Buffer.from(crypto7.hkdfSync("sha256", masterKey, "", WS_AUTH_HKDF_INFO, 32));
|
|
8000
7968
|
}
|
|
8001
7969
|
function deriveOrgId(masterKey) {
|
|
8002
|
-
const raw = Buffer.from(
|
|
8003
|
-
return
|
|
7970
|
+
const raw = Buffer.from(crypto7.hkdfSync("sha256", masterKey, "", ORG_ID_HKDF_INFO, 32));
|
|
7971
|
+
return crypto7.createHash("sha256").update(raw).digest("hex").slice(0, 32);
|
|
8004
7972
|
}
|
|
8005
7973
|
function hashAuthToken(token) {
|
|
8006
|
-
return
|
|
7974
|
+
return crypto7.createHash("sha256").update(token).digest("hex");
|
|
8007
7975
|
}
|
|
8008
7976
|
var WS_AUTH_HKDF_INFO, ORG_ID_HKDF_INFO;
|
|
8009
7977
|
var init_ws_auth = __esm({
|
|
@@ -8021,7 +7989,7 @@ __export(device_registry_exports, {
|
|
|
8021
7989
|
resolveTargetDevice: () => resolveTargetDevice,
|
|
8022
7990
|
setFriendlyName: () => setFriendlyName
|
|
8023
7991
|
});
|
|
8024
|
-
import
|
|
7992
|
+
import crypto8 from "crypto";
|
|
8025
7993
|
import os8 from "os";
|
|
8026
7994
|
import { readFileSync as readFileSync14, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, existsSync as existsSync16 } from "fs";
|
|
8027
7995
|
import path19 from "path";
|
|
@@ -8038,7 +8006,7 @@ function getDeviceInfo() {
|
|
|
8038
8006
|
}
|
|
8039
8007
|
const hostname = os8.hostname();
|
|
8040
8008
|
const info = {
|
|
8041
|
-
deviceId:
|
|
8009
|
+
deviceId: crypto8.randomUUID(),
|
|
8042
8010
|
friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
|
|
8043
8011
|
hostname
|
|
8044
8012
|
};
|
|
@@ -8286,10 +8254,10 @@ __export(messaging_exports, {
|
|
|
8286
8254
|
sendMessage: () => sendMessage,
|
|
8287
8255
|
setWsClientSend: () => setWsClientSend
|
|
8288
8256
|
});
|
|
8289
|
-
import
|
|
8257
|
+
import crypto9 from "crypto";
|
|
8290
8258
|
function generateUlid() {
|
|
8291
8259
|
const timestamp = Date.now().toString(36).padStart(10, "0");
|
|
8292
|
-
const random =
|
|
8260
|
+
const random = crypto9.randomBytes(10).toString("hex").slice(0, 16);
|
|
8293
8261
|
return (timestamp + random).toUpperCase();
|
|
8294
8262
|
}
|
|
8295
8263
|
function rowToMessage(row) {
|
|
@@ -937,7 +937,6 @@ import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
|
937
937
|
import { existsSync } from "fs";
|
|
938
938
|
import path from "path";
|
|
939
939
|
import os from "os";
|
|
940
|
-
import crypto from "crypto";
|
|
941
940
|
function getKeyDir() {
|
|
942
941
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
943
942
|
}
|
|
@@ -2752,7 +2751,7 @@ __export(file_grep_exports, {
|
|
|
2752
2751
|
import { execSync as execSync2 } from "child_process";
|
|
2753
2752
|
import { readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync5 } from "fs";
|
|
2754
2753
|
import path6 from "path";
|
|
2755
|
-
import
|
|
2754
|
+
import crypto from "crypto";
|
|
2756
2755
|
function hasRipgrep() {
|
|
2757
2756
|
if (_hasRg === null) {
|
|
2758
2757
|
try {
|
|
@@ -2785,7 +2784,7 @@ async function grepProjectFiles(query, projectRoot, options) {
|
|
|
2785
2784
|
const chunkCtx = getChunkContext(hit.filePath, hit.lineNumber);
|
|
2786
2785
|
const prefix = chunkCtx ? `[file: ${hit.filePath}:${hit.lineNumber} in ${chunkCtx}]` : `[file: ${hit.filePath}:${hit.lineNumber}]`;
|
|
2787
2786
|
return {
|
|
2788
|
-
id:
|
|
2787
|
+
id: crypto.createHash("sha256").update(`${hit.filePath}:${hit.lineNumber}`).digest("hex").slice(0, 36),
|
|
2789
2788
|
agent_id: "project",
|
|
2790
2789
|
agent_role: "file",
|
|
2791
2790
|
session_id: "file-grep",
|
package/dist/lib/keychain.js
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/lib/keychain.ts
|
|
9
2
|
import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
10
3
|
import { existsSync } from "fs";
|
|
11
4
|
import path from "path";
|
|
12
5
|
import os from "os";
|
|
13
|
-
import crypto from "crypto";
|
|
14
6
|
var SERVICE = "exe-mem";
|
|
15
7
|
var ACCOUNT = "master-key";
|
|
16
8
|
function getKeyDir() {
|
|
@@ -77,65 +69,34 @@ async function deleteMasterKey() {
|
|
|
77
69
|
await unlink(keyPath);
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
|
-
function
|
|
81
|
-
if (key.length !== 32) {
|
|
82
|
-
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
83
|
-
}
|
|
84
|
-
const hash = crypto.createHash("sha256").update(key).digest();
|
|
85
|
-
const checksumByte = hash[0];
|
|
86
|
-
let bits = "";
|
|
87
|
-
for (const byte of key) {
|
|
88
|
-
bits += byte.toString(2).padStart(8, "0");
|
|
89
|
-
}
|
|
90
|
-
bits += checksumByte.toString(2).padStart(8, "0");
|
|
91
|
-
const words = [];
|
|
92
|
-
let wordlist;
|
|
72
|
+
async function loadBip39() {
|
|
93
73
|
try {
|
|
94
|
-
|
|
95
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
96
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
74
|
+
return await import("bip39");
|
|
97
75
|
} catch {
|
|
98
|
-
throw new Error(
|
|
76
|
+
throw new Error(
|
|
77
|
+
"bip39 package not found. Run: npm install -g bip39\nOr reinstall exe-os: npm install -g @askexenow/exe-os"
|
|
78
|
+
);
|
|
99
79
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
80
|
+
}
|
|
81
|
+
async function exportMnemonic(key) {
|
|
82
|
+
if (key.length !== 32) {
|
|
83
|
+
throw new Error(`Key must be 32 bytes, got ${key.length}`);
|
|
103
84
|
}
|
|
104
|
-
|
|
85
|
+
const { entropyToMnemonic } = await loadBip39();
|
|
86
|
+
return entropyToMnemonic(key.toString("hex"));
|
|
105
87
|
}
|
|
106
|
-
function importMnemonic(mnemonic) {
|
|
107
|
-
const
|
|
88
|
+
async function importMnemonic(mnemonic) {
|
|
89
|
+
const trimmed = mnemonic.trim();
|
|
90
|
+
const words = trimmed.split(/\s+/);
|
|
108
91
|
if (words.length !== 24) {
|
|
109
92
|
throw new Error(`Expected 24 words, got ${words.length}`);
|
|
110
93
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
wordlist = bip39.wordlists?.english ?? bip39.default?.wordlists?.english;
|
|
115
|
-
if (!wordlist) throw new Error("no wordlist");
|
|
116
|
-
} catch {
|
|
117
|
-
throw new Error("bip39 package required. Install with: npm install bip39");
|
|
118
|
-
}
|
|
119
|
-
let bits = "";
|
|
120
|
-
for (const word of words) {
|
|
121
|
-
const index = wordlist.indexOf(word.toLowerCase());
|
|
122
|
-
if (index === -1) {
|
|
123
|
-
throw new Error(`Invalid BIP39 word: "${word}"`);
|
|
124
|
-
}
|
|
125
|
-
bits += index.toString(2).padStart(11, "0");
|
|
126
|
-
}
|
|
127
|
-
const entropyBits = bits.slice(0, 256);
|
|
128
|
-
const checksumBits = bits.slice(256, 264);
|
|
129
|
-
const key = Buffer.alloc(32);
|
|
130
|
-
for (let i = 0; i < 32; i++) {
|
|
131
|
-
key[i] = parseInt(entropyBits.slice(i * 8, (i + 1) * 8), 2);
|
|
132
|
-
}
|
|
133
|
-
const hash = crypto.createHash("sha256").update(key).digest();
|
|
134
|
-
const expectedChecksum = hash[0].toString(2).padStart(8, "0");
|
|
135
|
-
if (checksumBits !== expectedChecksum) {
|
|
136
|
-
throw new Error("Invalid mnemonic checksum");
|
|
94
|
+
const { validateMnemonic, mnemonicToEntropy } = await loadBip39();
|
|
95
|
+
if (!validateMnemonic(trimmed)) {
|
|
96
|
+
throw new Error("Invalid mnemonic \u2014 check for typos or missing words");
|
|
137
97
|
}
|
|
138
|
-
|
|
98
|
+
const entropy = mnemonicToEntropy(trimmed);
|
|
99
|
+
return Buffer.from(entropy, "hex");
|
|
139
100
|
}
|
|
140
101
|
export {
|
|
141
102
|
deleteMasterKey,
|