@askexenow/exe-os 0.9.66 → 0.9.67
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/deploy/stack-manifests/v0.9.json +54 -5
- package/dist/bin/age-ontology-load.js +61 -0
- package/dist/bin/agentic-ontology-backfill.js +4708 -0
- package/dist/bin/agentic-reflection-backfill.js +4144 -0
- package/dist/bin/{exe-link.js → agentic-semantic-label.js} +1523 -2275
- package/dist/bin/backfill-conversations.js +506 -20
- package/dist/bin/backfill-responses.js +506 -20
- package/dist/bin/backfill-vectors.js +233 -20
- package/dist/bin/bulk-sync-postgres.js +4876 -0
- package/dist/bin/cleanup-stale-review-tasks.js +507 -21
- package/dist/bin/cli.js +2450 -1530
- package/dist/bin/exe-assign.js +506 -20
- package/dist/bin/exe-boot.js +410 -60
- package/dist/bin/exe-cloud.js +795 -105
- package/dist/bin/exe-dispatch.js +516 -22
- package/dist/bin/exe-doctor.js +587 -30
- package/dist/bin/exe-export-behaviors.js +518 -24
- package/dist/bin/exe-forget.js +507 -21
- package/dist/bin/exe-gateway.js +571 -25
- package/dist/bin/exe-heartbeat.js +518 -24
- package/dist/bin/exe-kill.js +507 -21
- package/dist/bin/exe-launch-agent.js +2312 -1069
- package/dist/bin/exe-new-employee.js +197 -165
- package/dist/bin/exe-pending-messages.js +507 -21
- package/dist/bin/exe-pending-notifications.js +507 -21
- package/dist/bin/exe-pending-reviews.js +507 -21
- package/dist/bin/exe-rename.js +507 -21
- package/dist/bin/exe-review.js +507 -21
- package/dist/bin/exe-search.js +518 -24
- package/dist/bin/exe-session-cleanup.js +516 -22
- package/dist/bin/exe-settings.js +4 -0
- package/dist/bin/exe-start-codex.js +682 -143
- package/dist/bin/exe-start-opencode.js +627 -79
- package/dist/bin/exe-status.js +507 -21
- package/dist/bin/exe-team.js +507 -21
- package/dist/bin/git-sweep.js +516 -22
- package/dist/bin/graph-backfill.js +558 -21
- package/dist/bin/graph-export.js +507 -21
- package/dist/bin/graph-layer-benchmark.js +109 -0
- package/dist/bin/install.js +305 -288
- package/dist/bin/intercom-check.js +516 -22
- package/dist/bin/postgres-agentic-reflection-backfill.js +187 -0
- package/dist/bin/postgres-agentic-semantic-backfill.js +237 -0
- package/dist/bin/scan-tasks.js +516 -22
- package/dist/bin/setup.js +412 -62
- package/dist/bin/shard-migrate.js +506 -20
- package/dist/gateway/index.js +569 -23
- package/dist/hooks/bug-report-worker.js +519 -25
- package/dist/hooks/codex-stop-task-finalizer.js +516 -22
- package/dist/hooks/commit-complete.js +516 -22
- package/dist/hooks/error-recall.js +518 -24
- package/dist/hooks/ingest.js +516 -22
- package/dist/hooks/instructions-loaded.js +507 -21
- package/dist/hooks/notification.js +507 -21
- package/dist/hooks/post-compact.js +507 -21
- package/dist/hooks/post-tool-combined.js +519 -25
- package/dist/hooks/pre-compact.js +516 -22
- package/dist/hooks/pre-tool-use.js +507 -21
- package/dist/hooks/prompt-submit.js +519 -25
- package/dist/hooks/session-end.js +516 -22
- package/dist/hooks/session-start.js +520 -26
- package/dist/hooks/stop.js +517 -23
- package/dist/hooks/subagent-stop.js +507 -21
- package/dist/hooks/summary-worker.js +411 -61
- package/dist/index.js +569 -23
- package/dist/lib/cloud-sync.js +391 -53
- package/dist/lib/config.js +13 -1
- package/dist/lib/consolidation.js +1 -1
- package/dist/lib/database.js +124 -0
- package/dist/lib/db.js +124 -0
- package/dist/lib/device-registry.js +124 -0
- package/dist/lib/embedder.js +13 -1
- package/dist/lib/exe-daemon.js +2184 -561
- package/dist/lib/hybrid-search.js +518 -24
- package/dist/lib/identity.js +3 -0
- package/dist/lib/keychain.js +178 -22
- package/dist/lib/messaging.js +3 -0
- package/dist/lib/reminders.js +3 -0
- package/dist/lib/schedules.js +233 -20
- package/dist/lib/skill-learning.js +16 -1
- package/dist/lib/store.js +506 -20
- package/dist/lib/tasks.js +16 -1
- package/dist/lib/tmux-routing.js +16 -1
- package/dist/lib/token-spend.js +3 -0
- package/dist/mcp/server.js +1757 -428
- package/dist/mcp/tools/complete-reminder.js +3 -0
- package/dist/mcp/tools/create-reminder.js +3 -0
- package/dist/mcp/tools/create-task.js +16 -1
- package/dist/mcp/tools/deactivate-behavior.js +3 -0
- package/dist/mcp/tools/list-reminders.js +3 -0
- package/dist/mcp/tools/list-tasks.js +3 -0
- package/dist/mcp/tools/send-message.js +3 -0
- package/dist/mcp/tools/update-task.js +16 -1
- package/dist/runtime/index.js +516 -22
- package/dist/tui/App.js +594 -29
- package/package.json +8 -5
- package/src/commands/exe/cloud.md +6 -10
- package/stack.release.json +3 -3
- package/src/commands/exe/link.md +0 -18
|
@@ -222,6 +222,10 @@ async function loadConfig() {
|
|
|
222
222
|
if (config.dbPath.startsWith("~")) {
|
|
223
223
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
224
224
|
}
|
|
225
|
+
const envDbPath = path.join(dir, "memories.db");
|
|
226
|
+
if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
|
|
227
|
+
config.dbPath = envDbPath;
|
|
228
|
+
}
|
|
225
229
|
return config;
|
|
226
230
|
} catch {
|
|
227
231
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
@@ -1665,6 +1669,9 @@ function getClient() {
|
|
|
1665
1669
|
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
1666
1670
|
return _daemonClient;
|
|
1667
1671
|
}
|
|
1672
|
+
if (!_resilientClient) {
|
|
1673
|
+
return _adapterClient;
|
|
1674
|
+
}
|
|
1668
1675
|
return _resilientClient;
|
|
1669
1676
|
}
|
|
1670
1677
|
async function initDaemonClient() {
|
|
@@ -2697,6 +2704,127 @@ async function ensureSchema() {
|
|
|
2697
2704
|
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2698
2705
|
END;
|
|
2699
2706
|
`);
|
|
2707
|
+
await client.executeMultiple(`
|
|
2708
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
2709
|
+
id TEXT PRIMARY KEY,
|
|
2710
|
+
agent_id TEXT NOT NULL,
|
|
2711
|
+
project_name TEXT,
|
|
2712
|
+
started_at TEXT NOT NULL,
|
|
2713
|
+
last_event_at TEXT NOT NULL,
|
|
2714
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2715
|
+
properties TEXT DEFAULT '{}'
|
|
2716
|
+
);
|
|
2717
|
+
|
|
2718
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
|
|
2719
|
+
ON agent_sessions(agent_id, started_at);
|
|
2720
|
+
|
|
2721
|
+
CREATE TABLE IF NOT EXISTS agent_goals (
|
|
2722
|
+
id TEXT PRIMARY KEY,
|
|
2723
|
+
statement TEXT NOT NULL,
|
|
2724
|
+
owner_agent_id TEXT,
|
|
2725
|
+
project_name TEXT,
|
|
2726
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
2727
|
+
priority INTEGER NOT NULL DEFAULT 5,
|
|
2728
|
+
success_criteria TEXT,
|
|
2729
|
+
parent_goal_id TEXT,
|
|
2730
|
+
due_at TEXT,
|
|
2731
|
+
achieved_at TEXT,
|
|
2732
|
+
supersedes_id TEXT,
|
|
2733
|
+
created_at TEXT NOT NULL,
|
|
2734
|
+
updated_at TEXT NOT NULL,
|
|
2735
|
+
source_memory_id TEXT
|
|
2736
|
+
);
|
|
2737
|
+
|
|
2738
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
|
|
2739
|
+
ON agent_goals(project_name, status, priority);
|
|
2740
|
+
|
|
2741
|
+
CREATE TABLE IF NOT EXISTS agent_events (
|
|
2742
|
+
id TEXT PRIMARY KEY,
|
|
2743
|
+
event_type TEXT NOT NULL,
|
|
2744
|
+
occurred_at TEXT NOT NULL,
|
|
2745
|
+
sequence_index INTEGER NOT NULL,
|
|
2746
|
+
actor_agent_id TEXT,
|
|
2747
|
+
agent_role TEXT,
|
|
2748
|
+
project_name TEXT,
|
|
2749
|
+
session_id TEXT,
|
|
2750
|
+
task_id TEXT,
|
|
2751
|
+
goal_id TEXT,
|
|
2752
|
+
parent_event_id TEXT,
|
|
2753
|
+
intention TEXT,
|
|
2754
|
+
outcome TEXT,
|
|
2755
|
+
evidence_memory_id TEXT,
|
|
2756
|
+
impact TEXT,
|
|
2757
|
+
payload TEXT DEFAULT '{}',
|
|
2758
|
+
created_at TEXT NOT NULL
|
|
2759
|
+
);
|
|
2760
|
+
|
|
2761
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_time
|
|
2762
|
+
ON agent_events(occurred_at, sequence_index);
|
|
2763
|
+
|
|
2764
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
|
|
2765
|
+
ON agent_events(session_id, sequence_index);
|
|
2766
|
+
|
|
2767
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
|
|
2768
|
+
ON agent_events(goal_id, occurred_at);
|
|
2769
|
+
|
|
2770
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_memory
|
|
2771
|
+
ON agent_events(evidence_memory_id);
|
|
2772
|
+
|
|
2773
|
+
CREATE TABLE IF NOT EXISTS agent_goal_links (
|
|
2774
|
+
id TEXT PRIMARY KEY,
|
|
2775
|
+
goal_id TEXT NOT NULL,
|
|
2776
|
+
link_type TEXT NOT NULL,
|
|
2777
|
+
target_id TEXT NOT NULL,
|
|
2778
|
+
target_type TEXT NOT NULL,
|
|
2779
|
+
created_at TEXT NOT NULL
|
|
2780
|
+
);
|
|
2781
|
+
|
|
2782
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
|
|
2783
|
+
ON agent_goal_links(goal_id, target_type);
|
|
2784
|
+
|
|
2785
|
+
CREATE TABLE IF NOT EXISTS agent_semantic_labels (
|
|
2786
|
+
id TEXT PRIMARY KEY,
|
|
2787
|
+
source_memory_id TEXT NOT NULL,
|
|
2788
|
+
event_id TEXT,
|
|
2789
|
+
labeler TEXT NOT NULL,
|
|
2790
|
+
schema_version INTEGER NOT NULL DEFAULT 1,
|
|
2791
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2792
|
+
labels TEXT NOT NULL,
|
|
2793
|
+
created_at TEXT NOT NULL,
|
|
2794
|
+
updated_at TEXT NOT NULL
|
|
2795
|
+
);
|
|
2796
|
+
|
|
2797
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
|
|
2798
|
+
ON agent_semantic_labels(source_memory_id, labeler);
|
|
2799
|
+
|
|
2800
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
|
|
2801
|
+
ON agent_semantic_labels(event_id);
|
|
2802
|
+
|
|
2803
|
+
CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
|
|
2804
|
+
id TEXT PRIMARY KEY,
|
|
2805
|
+
project_name TEXT,
|
|
2806
|
+
session_id TEXT,
|
|
2807
|
+
window_start_at TEXT NOT NULL,
|
|
2808
|
+
window_end_at TEXT NOT NULL,
|
|
2809
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2810
|
+
goal_count INTEGER NOT NULL DEFAULT 0,
|
|
2811
|
+
success_count INTEGER NOT NULL DEFAULT 0,
|
|
2812
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
2813
|
+
risk_count INTEGER NOT NULL DEFAULT 0,
|
|
2814
|
+
summary TEXT NOT NULL,
|
|
2815
|
+
learnings TEXT NOT NULL DEFAULT '[]',
|
|
2816
|
+
next_actions TEXT NOT NULL DEFAULT '[]',
|
|
2817
|
+
evidence_event_ids TEXT NOT NULL DEFAULT '[]',
|
|
2818
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2819
|
+
created_at TEXT NOT NULL
|
|
2820
|
+
);
|
|
2821
|
+
|
|
2822
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
|
|
2823
|
+
ON agent_reflection_checkpoints(project_name, window_end_at);
|
|
2824
|
+
|
|
2825
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
|
|
2826
|
+
ON agent_reflection_checkpoints(session_id, window_end_at);
|
|
2827
|
+
`);
|
|
2700
2828
|
try {
|
|
2701
2829
|
await client.execute({
|
|
2702
2830
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -2860,7 +2988,7 @@ __export(shard_manager_exports, {
|
|
|
2860
2988
|
shardExists: () => shardExists
|
|
2861
2989
|
});
|
|
2862
2990
|
import path7 from "path";
|
|
2863
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as
|
|
2991
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
|
|
2864
2992
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2865
2993
|
function initShardManager(encryptionKey) {
|
|
2866
2994
|
_encryptionKey = encryptionKey;
|
|
@@ -2924,7 +3052,7 @@ async function auditShardHealth(options = {}) {
|
|
|
2924
3052
|
const shards = [];
|
|
2925
3053
|
for (const name of names) {
|
|
2926
3054
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
2927
|
-
const stat =
|
|
3055
|
+
const stat = statSync3(dbPath);
|
|
2928
3056
|
const item = {
|
|
2929
3057
|
name,
|
|
2930
3058
|
path: dbPath,
|
|
@@ -3177,7 +3305,7 @@ async function getReadyShardClient(projectName) {
|
|
|
3177
3305
|
_shardLastAccess.delete(safeName);
|
|
3178
3306
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3179
3307
|
if (existsSync7(dbPath)) {
|
|
3180
|
-
const stat =
|
|
3308
|
+
const stat = statSync3(dbPath);
|
|
3181
3309
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3182
3310
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3183
3311
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3532,11 +3660,12 @@ init_database();
|
|
|
3532
3660
|
|
|
3533
3661
|
// src/lib/keychain.ts
|
|
3534
3662
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3535
|
-
import { existsSync as existsSync6 } from "fs";
|
|
3663
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3536
3664
|
import { execSync as execSync2 } from "child_process";
|
|
3537
3665
|
import path6 from "path";
|
|
3538
3666
|
import os5 from "os";
|
|
3539
|
-
var SERVICE = "exe-
|
|
3667
|
+
var SERVICE = "exe-os";
|
|
3668
|
+
var LEGACY_SERVICE = "exe-mem";
|
|
3540
3669
|
var ACCOUNT = "master-key";
|
|
3541
3670
|
function getKeyDir() {
|
|
3542
3671
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path6.join(os5.homedir(), ".exe-os");
|
|
@@ -3544,29 +3673,79 @@ function getKeyDir() {
|
|
|
3544
3673
|
function getKeyPath() {
|
|
3545
3674
|
return path6.join(getKeyDir(), "master.key");
|
|
3546
3675
|
}
|
|
3547
|
-
function
|
|
3676
|
+
function nativeKeychainAllowed() {
|
|
3677
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
3678
|
+
}
|
|
3679
|
+
var linuxSecretAvailability = null;
|
|
3680
|
+
function linuxSecretAvailable() {
|
|
3681
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3682
|
+
if (process.platform !== "linux") return false;
|
|
3683
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3684
|
+
try {
|
|
3685
|
+
execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3686
|
+
} catch {
|
|
3687
|
+
linuxSecretAvailability = false;
|
|
3688
|
+
return false;
|
|
3689
|
+
}
|
|
3690
|
+
try {
|
|
3691
|
+
execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3692
|
+
linuxSecretAvailability = true;
|
|
3693
|
+
} catch {
|
|
3694
|
+
linuxSecretAvailability = false;
|
|
3695
|
+
}
|
|
3696
|
+
return linuxSecretAvailability;
|
|
3697
|
+
}
|
|
3698
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
3699
|
+
if (process.platform !== "linux") return false;
|
|
3700
|
+
try {
|
|
3701
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3702
|
+
const st = statSync2(keyPath);
|
|
3703
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3704
|
+
if (uid === 0) return true;
|
|
3705
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
3706
|
+
return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
|
|
3707
|
+
} catch {
|
|
3708
|
+
return false;
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
function macKeychainGet(service = SERVICE) {
|
|
3712
|
+
if (!nativeKeychainAllowed()) return null;
|
|
3548
3713
|
if (process.platform !== "darwin") return null;
|
|
3549
3714
|
try {
|
|
3550
3715
|
return execSync2(
|
|
3551
|
-
`security find-generic-password -s "${
|
|
3716
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3552
3717
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3553
3718
|
).trim();
|
|
3554
3719
|
} catch {
|
|
3555
3720
|
return null;
|
|
3556
3721
|
}
|
|
3557
3722
|
}
|
|
3558
|
-
function macKeychainSet(value) {
|
|
3723
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
3724
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3559
3725
|
if (process.platform !== "darwin") return false;
|
|
3560
3726
|
try {
|
|
3561
3727
|
try {
|
|
3562
3728
|
execSync2(
|
|
3563
|
-
`security delete-generic-password -s "${
|
|
3729
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3564
3730
|
{ timeout: 5e3 }
|
|
3565
3731
|
);
|
|
3566
3732
|
} catch {
|
|
3567
3733
|
}
|
|
3568
3734
|
execSync2(
|
|
3569
|
-
`security add-generic-password -s "${
|
|
3735
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3736
|
+
{ timeout: 5e3 }
|
|
3737
|
+
);
|
|
3738
|
+
return true;
|
|
3739
|
+
} catch {
|
|
3740
|
+
return false;
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
function macKeychainDelete(service = SERVICE) {
|
|
3744
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3745
|
+
if (process.platform !== "darwin") return false;
|
|
3746
|
+
try {
|
|
3747
|
+
execSync2(
|
|
3748
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3570
3749
|
{ timeout: 5e3 }
|
|
3571
3750
|
);
|
|
3572
3751
|
return true;
|
|
@@ -3574,22 +3753,35 @@ function macKeychainSet(value) {
|
|
|
3574
3753
|
return false;
|
|
3575
3754
|
}
|
|
3576
3755
|
}
|
|
3577
|
-
function linuxSecretGet() {
|
|
3578
|
-
if (
|
|
3756
|
+
function linuxSecretGet(service = SERVICE) {
|
|
3757
|
+
if (!linuxSecretAvailable()) return null;
|
|
3579
3758
|
try {
|
|
3580
3759
|
return execSync2(
|
|
3581
|
-
`secret-tool lookup service "${
|
|
3760
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3582
3761
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3583
3762
|
).trim();
|
|
3584
3763
|
} catch {
|
|
3585
3764
|
return null;
|
|
3586
3765
|
}
|
|
3587
3766
|
}
|
|
3588
|
-
function linuxSecretSet(value) {
|
|
3767
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
3768
|
+
if (!linuxSecretAvailable()) return false;
|
|
3769
|
+
try {
|
|
3770
|
+
execSync2(
|
|
3771
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3772
|
+
{ timeout: 5e3 }
|
|
3773
|
+
);
|
|
3774
|
+
return true;
|
|
3775
|
+
} catch {
|
|
3776
|
+
return false;
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
3780
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3589
3781
|
if (process.platform !== "linux") return false;
|
|
3590
3782
|
try {
|
|
3591
3783
|
execSync2(
|
|
3592
|
-
`
|
|
3784
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3593
3785
|
{ timeout: 5e3 }
|
|
3594
3786
|
);
|
|
3595
3787
|
return true;
|
|
@@ -3598,6 +3790,7 @@ function linuxSecretSet(value) {
|
|
|
3598
3790
|
}
|
|
3599
3791
|
}
|
|
3600
3792
|
async function tryKeytar() {
|
|
3793
|
+
if (!nativeKeychainAllowed()) return null;
|
|
3601
3794
|
try {
|
|
3602
3795
|
return await import("keytar");
|
|
3603
3796
|
} catch {
|
|
@@ -3672,7 +3865,19 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
3672
3865
|
return "plaintext";
|
|
3673
3866
|
}
|
|
3674
3867
|
async function getMasterKey() {
|
|
3675
|
-
|
|
3868
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
3869
|
+
if (!nativeValue) {
|
|
3870
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
3871
|
+
if (legacyValue) {
|
|
3872
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
3873
|
+
if (migrated) {
|
|
3874
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
3875
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
3876
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
3877
|
+
}
|
|
3878
|
+
nativeValue = legacyValue;
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3676
3881
|
if (nativeValue) {
|
|
3677
3882
|
return Buffer.from(nativeValue, "base64");
|
|
3678
3883
|
}
|
|
@@ -3680,12 +3885,17 @@ async function getMasterKey() {
|
|
|
3680
3885
|
if (keytar) {
|
|
3681
3886
|
try {
|
|
3682
3887
|
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3683
|
-
|
|
3684
|
-
|
|
3888
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
3889
|
+
if (legacyKeytarValue) {
|
|
3890
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
3685
3891
|
if (migrated) {
|
|
3686
3892
|
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
3893
|
+
try {
|
|
3894
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
3895
|
+
} catch {
|
|
3896
|
+
}
|
|
3687
3897
|
}
|
|
3688
|
-
return Buffer.from(
|
|
3898
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
3689
3899
|
}
|
|
3690
3900
|
} catch {
|
|
3691
3901
|
}
|
|
@@ -3710,7 +3920,7 @@ async function getMasterKey() {
|
|
|
3710
3920
|
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
3711
3921
|
if (!decrypted) {
|
|
3712
3922
|
process.stderr.write(
|
|
3713
|
-
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os
|
|
3923
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
3714
3924
|
);
|
|
3715
3925
|
return null;
|
|
3716
3926
|
}
|
|
@@ -3719,6 +3929,9 @@ async function getMasterKey() {
|
|
|
3719
3929
|
b64Value = content;
|
|
3720
3930
|
}
|
|
3721
3931
|
const key = Buffer.from(b64Value, "base64");
|
|
3932
|
+
if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
3933
|
+
return key;
|
|
3934
|
+
}
|
|
3722
3935
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
3723
3936
|
if (migrated) {
|
|
3724
3937
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|