@askexenow/exe-os 0.8.36 → 0.8.37
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 +9 -1
- package/dist/bin/backfill-responses.js +9 -1
- package/dist/bin/cli.js +255 -31
- package/dist/bin/exe-assign.js +9 -1
- package/dist/bin/exe-boot.js +554 -23
- package/dist/bin/exe-dispatch.js +43 -3
- package/dist/bin/exe-export-behaviors.js +7 -0
- package/dist/bin/exe-gateway.js +57 -9
- package/dist/bin/exe-heartbeat.js +2 -1
- package/dist/bin/exe-kill.js +7 -0
- package/dist/bin/exe-launch-agent.js +8 -1
- package/dist/bin/exe-link.js +503 -12
- package/dist/bin/exe-pending-messages.js +2 -1
- package/dist/bin/exe-pending-reviews.js +2 -1
- package/dist/bin/exe-review.js +9 -1
- package/dist/bin/exe-search.js +9 -1
- package/dist/bin/exe-session-cleanup.js +11 -2
- package/dist/bin/git-sweep.js +9 -1
- package/dist/bin/graph-backfill.js +7 -0
- package/dist/bin/graph-export.js +7 -0
- package/dist/bin/install.js +35 -5
- package/dist/bin/scan-tasks.js +9 -1
- package/dist/bin/shard-migrate.js +7 -0
- package/dist/bin/wiki-sync.js +7 -0
- package/dist/gateway/index.js +57 -9
- package/dist/hooks/bug-report-worker.js +45 -5
- package/dist/hooks/commit-complete.js +9 -1
- package/dist/hooks/error-recall.js +10 -2
- package/dist/hooks/exe-heartbeat-hook.js +1 -1
- package/dist/hooks/ingest-worker.js +56 -8
- package/dist/hooks/ingest.js +1 -1
- package/dist/hooks/instructions-loaded.js +10 -2
- package/dist/hooks/notification.js +10 -2
- package/dist/hooks/post-compact.js +10 -2
- package/dist/hooks/pre-compact.js +10 -2
- package/dist/hooks/pre-tool-use.js +10 -2
- package/dist/hooks/prompt-ingest-worker.js +9 -1
- package/dist/hooks/prompt-submit.js +56 -8
- package/dist/hooks/response-ingest-worker.js +9 -1
- package/dist/hooks/session-end.js +10 -2
- package/dist/hooks/session-start.js +10 -2
- package/dist/hooks/stop.js +10 -2
- package/dist/hooks/subagent-stop.js +10 -2
- package/dist/hooks/summary-worker.js +512 -13
- package/dist/index.js +65 -15
- package/dist/lib/cloud-sync.js +502 -11
- package/dist/lib/exe-daemon.js +73 -23
- package/dist/lib/hybrid-search.js +9 -1
- package/dist/lib/messaging.js +43 -3
- package/dist/lib/store.js +9 -1
- package/dist/lib/tasks.js +47 -7
- package/dist/lib/tmux-routing.js +45 -3
- package/dist/mcp/server.js +73 -16
- package/dist/mcp/tools/create-task.js +48 -8
- package/dist/mcp/tools/deactivate-behavior.js +1 -1
- package/dist/mcp/tools/list-tasks.js +2 -1
- package/dist/mcp/tools/send-message.js +46 -6
- package/dist/mcp/tools/update-task.js +3 -2
- package/dist/runtime/index.js +54 -4
- package/dist/tui/App.js +54 -4
- package/package.json +2 -2
- package/src/commands/exe/afk.md +116 -0
|
@@ -1445,7 +1445,8 @@ async function writeMemory(record) {
|
|
|
1445
1445
|
has_error: record.has_error ? 1 : 0,
|
|
1446
1446
|
raw_text: record.raw_text,
|
|
1447
1447
|
vector: record.vector,
|
|
1448
|
-
version:
|
|
1448
|
+
version: 0,
|
|
1449
|
+
// Placeholder — assigned atomically at flush time
|
|
1449
1450
|
task_id: record.task_id ?? null,
|
|
1450
1451
|
importance: record.importance ?? 5,
|
|
1451
1452
|
status: record.status ?? "active",
|
|
@@ -1479,6 +1480,13 @@ async function flushBatch() {
|
|
|
1479
1480
|
_flushing = true;
|
|
1480
1481
|
try {
|
|
1481
1482
|
const batch = _pendingRecords.slice(0);
|
|
1483
|
+
const client = getClient();
|
|
1484
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1485
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1486
|
+
for (const row of batch) {
|
|
1487
|
+
row.version = baseVersion++;
|
|
1488
|
+
}
|
|
1489
|
+
_nextVersion = baseVersion;
|
|
1482
1490
|
const buildStmt = (row) => {
|
|
1483
1491
|
const hasVector = row.vector !== null;
|
|
1484
1492
|
const taskId = row.task_id ?? null;
|
|
@@ -1444,7 +1444,8 @@ async function writeMemory(record) {
|
|
|
1444
1444
|
has_error: record.has_error ? 1 : 0,
|
|
1445
1445
|
raw_text: record.raw_text,
|
|
1446
1446
|
vector: record.vector,
|
|
1447
|
-
version:
|
|
1447
|
+
version: 0,
|
|
1448
|
+
// Placeholder — assigned atomically at flush time
|
|
1448
1449
|
task_id: record.task_id ?? null,
|
|
1449
1450
|
importance: record.importance ?? 5,
|
|
1450
1451
|
status: record.status ?? "active",
|
|
@@ -1478,6 +1479,13 @@ async function flushBatch() {
|
|
|
1478
1479
|
_flushing = true;
|
|
1479
1480
|
try {
|
|
1480
1481
|
const batch = _pendingRecords.slice(0);
|
|
1482
|
+
const client = getClient();
|
|
1483
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1484
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1485
|
+
for (const row of batch) {
|
|
1486
|
+
row.version = baseVersion++;
|
|
1487
|
+
}
|
|
1488
|
+
_nextVersion = baseVersion;
|
|
1481
1489
|
const buildStmt = (row) => {
|
|
1482
1490
|
const hasVector = row.vector !== null;
|
|
1483
1491
|
const taskId = row.task_id ?? null;
|
package/dist/bin/cli.js
CHANGED
|
@@ -807,26 +807,56 @@ async function mergeHooks(packageRoot, homeDir = os3.homedir()) {
|
|
|
807
807
|
permissions.allow = [];
|
|
808
808
|
}
|
|
809
809
|
const toolNames = [
|
|
810
|
+
// Core memory
|
|
810
811
|
"store_memory",
|
|
811
812
|
"recall_my_memory",
|
|
813
|
+
"commit_to_long_term_memory",
|
|
814
|
+
"consolidate_memories",
|
|
815
|
+
"ask_team_memory",
|
|
816
|
+
"get_session_context",
|
|
817
|
+
// Tasks
|
|
812
818
|
"create_task",
|
|
813
819
|
"list_tasks",
|
|
814
820
|
"get_task",
|
|
815
821
|
"update_task",
|
|
816
822
|
"close_task",
|
|
823
|
+
"checkpoint_task",
|
|
824
|
+
// Behaviors
|
|
817
825
|
"store_behavior",
|
|
818
826
|
"deactivate_behavior",
|
|
819
|
-
"
|
|
827
|
+
"list_behaviors",
|
|
828
|
+
// Identity
|
|
820
829
|
"get_identity",
|
|
821
830
|
"update_identity",
|
|
822
|
-
|
|
823
|
-
"
|
|
831
|
+
// Messaging
|
|
832
|
+
"send_message",
|
|
833
|
+
"acknowledge_messages",
|
|
834
|
+
"send_whatsapp",
|
|
835
|
+
"query_conversations",
|
|
836
|
+
// Reminders + triggers
|
|
824
837
|
"create_reminder",
|
|
825
838
|
"complete_reminder",
|
|
826
839
|
"list_reminders",
|
|
827
|
-
"
|
|
840
|
+
"create_trigger",
|
|
841
|
+
"list_triggers",
|
|
842
|
+
// GraphRAG
|
|
828
843
|
"query_relationships",
|
|
829
|
-
"
|
|
844
|
+
"merge_entities",
|
|
845
|
+
// Documents + wiki
|
|
846
|
+
"ingest_document",
|
|
847
|
+
"list_documents",
|
|
848
|
+
"purge_document",
|
|
849
|
+
"rerank_documents",
|
|
850
|
+
"set_document_importance",
|
|
851
|
+
"create_wiki_page",
|
|
852
|
+
"update_wiki_page",
|
|
853
|
+
"get_wiki_page",
|
|
854
|
+
"list_wiki_pages",
|
|
855
|
+
// System
|
|
856
|
+
"load_skill",
|
|
857
|
+
"apply_starter_pack",
|
|
858
|
+
"resume_employee",
|
|
859
|
+
"deploy_client"
|
|
830
860
|
];
|
|
831
861
|
const allowList = permissions.allow;
|
|
832
862
|
for (const tool of expandDualPrefixTools(toolNames)) {
|
|
@@ -2063,8 +2093,8 @@ function shardExists(projectName) {
|
|
|
2063
2093
|
}
|
|
2064
2094
|
function listShards() {
|
|
2065
2095
|
if (!existsSync6(SHARDS_DIR)) return [];
|
|
2066
|
-
const { readdirSync:
|
|
2067
|
-
return
|
|
2096
|
+
const { readdirSync: readdirSync5 } = __require("fs");
|
|
2097
|
+
return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
2068
2098
|
}
|
|
2069
2099
|
async function ensureShardSchema(client) {
|
|
2070
2100
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
@@ -2329,7 +2359,8 @@ async function writeMemory(record) {
|
|
|
2329
2359
|
has_error: record.has_error ? 1 : 0,
|
|
2330
2360
|
raw_text: record.raw_text,
|
|
2331
2361
|
vector: record.vector,
|
|
2332
|
-
version:
|
|
2362
|
+
version: 0,
|
|
2363
|
+
// Placeholder — assigned atomically at flush time
|
|
2333
2364
|
task_id: record.task_id ?? null,
|
|
2334
2365
|
importance: record.importance ?? 5,
|
|
2335
2366
|
status: record.status ?? "active",
|
|
@@ -2363,6 +2394,13 @@ async function flushBatch() {
|
|
|
2363
2394
|
_flushing = true;
|
|
2364
2395
|
try {
|
|
2365
2396
|
const batch = _pendingRecords.slice(0);
|
|
2397
|
+
const client = getClient();
|
|
2398
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
2399
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
2400
|
+
for (const row of batch) {
|
|
2401
|
+
row.version = baseVersion++;
|
|
2402
|
+
}
|
|
2403
|
+
_nextVersion = baseVersion;
|
|
2366
2404
|
const buildStmt = (row) => {
|
|
2367
2405
|
const hasVector = row.vector !== null;
|
|
2368
2406
|
const taskId = row.task_id ?? null;
|
|
@@ -17943,6 +17981,7 @@ var init_capacity_monitor = __esm({
|
|
|
17943
17981
|
// src/lib/tmux-routing.ts
|
|
17944
17982
|
var tmux_routing_exports = {};
|
|
17945
17983
|
__export(tmux_routing_exports, {
|
|
17984
|
+
acquireSpawnLock: () => acquireSpawnLock2,
|
|
17946
17985
|
employeeSessionName: () => employeeSessionName,
|
|
17947
17986
|
ensureEmployee: () => ensureEmployee,
|
|
17948
17987
|
extractRootExe: () => extractRootExe,
|
|
@@ -17957,6 +17996,7 @@ __export(tmux_routing_exports, {
|
|
|
17957
17996
|
notifyParentExe: () => notifyParentExe,
|
|
17958
17997
|
parseParentExe: () => parseParentExe,
|
|
17959
17998
|
registerParentExe: () => registerParentExe,
|
|
17999
|
+
releaseSpawnLock: () => releaseSpawnLock2,
|
|
17960
18000
|
resolveExeSession: () => resolveExeSession,
|
|
17961
18001
|
sendIntercom: () => sendIntercom,
|
|
17962
18002
|
spawnEmployee: () => spawnEmployee,
|
|
@@ -17967,6 +18007,42 @@ import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirS
|
|
|
17967
18007
|
import path29 from "path";
|
|
17968
18008
|
import os9 from "os";
|
|
17969
18009
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
18010
|
+
import { unlinkSync as unlinkSync7 } from "fs";
|
|
18011
|
+
function spawnLockPath(sessionName) {
|
|
18012
|
+
return path29.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
18013
|
+
}
|
|
18014
|
+
function isProcessAlive(pid) {
|
|
18015
|
+
try {
|
|
18016
|
+
process.kill(pid, 0);
|
|
18017
|
+
return true;
|
|
18018
|
+
} catch {
|
|
18019
|
+
return false;
|
|
18020
|
+
}
|
|
18021
|
+
}
|
|
18022
|
+
function acquireSpawnLock2(sessionName) {
|
|
18023
|
+
if (!existsSync20(SPAWN_LOCK_DIR)) {
|
|
18024
|
+
mkdirSync9(SPAWN_LOCK_DIR, { recursive: true });
|
|
18025
|
+
}
|
|
18026
|
+
const lockFile = spawnLockPath(sessionName);
|
|
18027
|
+
if (existsSync20(lockFile)) {
|
|
18028
|
+
try {
|
|
18029
|
+
const lock = JSON.parse(readFileSync15(lockFile, "utf8"));
|
|
18030
|
+
const age = Date.now() - lock.timestamp;
|
|
18031
|
+
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
18032
|
+
return false;
|
|
18033
|
+
}
|
|
18034
|
+
} catch {
|
|
18035
|
+
}
|
|
18036
|
+
}
|
|
18037
|
+
writeFileSync8(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
18038
|
+
return true;
|
|
18039
|
+
}
|
|
18040
|
+
function releaseSpawnLock2(sessionName) {
|
|
18041
|
+
try {
|
|
18042
|
+
unlinkSync7(spawnLockPath(sessionName));
|
|
18043
|
+
} catch {
|
|
18044
|
+
}
|
|
18045
|
+
}
|
|
17970
18046
|
function resolveBehaviorsExporterScript() {
|
|
17971
18047
|
try {
|
|
17972
18048
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
@@ -18065,10 +18141,10 @@ function isEmployeeAlive(sessionName) {
|
|
|
18065
18141
|
}
|
|
18066
18142
|
function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive = isEmployeeAlive) {
|
|
18067
18143
|
const base = employeeSessionName(employeeName, exeSession);
|
|
18068
|
-
if (!isAlive(base)) return 0;
|
|
18144
|
+
if (!isAlive(base) && acquireSpawnLock2(base)) return 0;
|
|
18069
18145
|
for (let i = 2; i <= maxInstances; i++) {
|
|
18070
18146
|
const candidate = employeeSessionName(employeeName, exeSession, i);
|
|
18071
|
-
if (!isAlive(candidate)) return i;
|
|
18147
|
+
if (!isAlive(candidate) && acquireSpawnLock2(candidate)) return i;
|
|
18072
18148
|
}
|
|
18073
18149
|
return null;
|
|
18074
18150
|
}
|
|
@@ -18432,6 +18508,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18432
18508
|
command: spawnCommand
|
|
18433
18509
|
});
|
|
18434
18510
|
if (spawnResult.error) {
|
|
18511
|
+
releaseSpawnLock2(sessionName);
|
|
18435
18512
|
return { sessionName, error: `tmux new-session failed: ${spawnResult.error}` };
|
|
18436
18513
|
}
|
|
18437
18514
|
transport.pipeLog(sessionName, logFile);
|
|
@@ -18469,6 +18546,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18469
18546
|
}
|
|
18470
18547
|
}
|
|
18471
18548
|
if (!booted) {
|
|
18549
|
+
releaseSpawnLock2(sessionName);
|
|
18472
18550
|
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
|
|
18473
18551
|
}
|
|
18474
18552
|
if (!useExeAgent) {
|
|
@@ -18485,9 +18563,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18485
18563
|
pid: 0,
|
|
18486
18564
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
18487
18565
|
});
|
|
18566
|
+
releaseSpawnLock2(sessionName);
|
|
18488
18567
|
return { sessionName };
|
|
18489
18568
|
}
|
|
18490
|
-
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
18569
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
18491
18570
|
var init_tmux_routing = __esm({
|
|
18492
18571
|
"src/lib/tmux-routing.ts"() {
|
|
18493
18572
|
"use strict";
|
|
@@ -18499,6 +18578,7 @@ var init_tmux_routing = __esm({
|
|
|
18499
18578
|
init_provider_table();
|
|
18500
18579
|
init_intercom_queue();
|
|
18501
18580
|
init_plan_limits();
|
|
18581
|
+
SPAWN_LOCK_DIR = path29.join(os9.homedir(), ".exe-os", "spawn-locks");
|
|
18502
18582
|
SESSION_CACHE = path29.join(os9.homedir(), ".exe-os", "session-cache");
|
|
18503
18583
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
18504
18584
|
VERIFY_PANE_LINES = 200;
|
|
@@ -21747,7 +21827,7 @@ var init_update = __esm({
|
|
|
21747
21827
|
});
|
|
21748
21828
|
|
|
21749
21829
|
// src/bin/cli.ts
|
|
21750
|
-
import { existsSync as existsSync21, readFileSync as readFileSync17 } from "fs";
|
|
21830
|
+
import { existsSync as existsSync21, readFileSync as readFileSync17, writeFileSync as writeFileSync9, readdirSync as readdirSync4, rmSync } from "fs";
|
|
21751
21831
|
import path31 from "path";
|
|
21752
21832
|
import os10 from "os";
|
|
21753
21833
|
var args = process.argv.slice(2);
|
|
@@ -21779,7 +21859,7 @@ if (args.includes("--global")) {
|
|
|
21779
21859
|
await runClaudeCheck();
|
|
21780
21860
|
break;
|
|
21781
21861
|
case "uninstall":
|
|
21782
|
-
await runClaudeUninstall();
|
|
21862
|
+
await runClaudeUninstall(args.slice(2));
|
|
21783
21863
|
break;
|
|
21784
21864
|
default:
|
|
21785
21865
|
await runClaudeInstall();
|
|
@@ -21863,11 +21943,11 @@ async function runClaudeCheck() {
|
|
|
21863
21943
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
21864
21944
|
ok = false;
|
|
21865
21945
|
}
|
|
21866
|
-
const
|
|
21867
|
-
if (existsSync21(
|
|
21868
|
-
console.log("\x1B[32m\u2713\x1B[0m Slash
|
|
21946
|
+
const skillsDir = path31.join(claudeDir, "skills");
|
|
21947
|
+
if (existsSync21(skillsDir)) {
|
|
21948
|
+
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
21869
21949
|
} else {
|
|
21870
|
-
console.log("\x1B[31m\u2717\x1B[0m Slash
|
|
21950
|
+
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
21871
21951
|
ok = false;
|
|
21872
21952
|
}
|
|
21873
21953
|
if (!ok) {
|
|
@@ -21877,11 +21957,16 @@ async function runClaudeCheck() {
|
|
|
21877
21957
|
console.log("\nAll checks passed.");
|
|
21878
21958
|
}
|
|
21879
21959
|
}
|
|
21880
|
-
async function runClaudeUninstall() {
|
|
21881
|
-
const
|
|
21960
|
+
async function runClaudeUninstall(flags = []) {
|
|
21961
|
+
const dryRun = flags.includes("--dry-run");
|
|
21962
|
+
const purge = flags.includes("--purge");
|
|
21963
|
+
const homeDir = os10.homedir();
|
|
21964
|
+
const claudeDir = path31.join(homeDir, ".claude");
|
|
21882
21965
|
const settingsPath = path31.join(claudeDir, "settings.json");
|
|
21883
|
-
const claudeJsonPath = path31.join(
|
|
21966
|
+
const claudeJsonPath = path31.join(homeDir, ".claude.json");
|
|
21967
|
+
const exeOsDir = path31.join(homeDir, ".exe-os");
|
|
21884
21968
|
let removed = 0;
|
|
21969
|
+
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
21885
21970
|
if (existsSync21(settingsPath)) {
|
|
21886
21971
|
const settings = JSON.parse(readFileSync17(settingsPath, "utf8"));
|
|
21887
21972
|
if (settings.hooks) {
|
|
@@ -21903,9 +21988,19 @@ async function runClaudeUninstall() {
|
|
|
21903
21988
|
delete settings.hooks[key];
|
|
21904
21989
|
}
|
|
21905
21990
|
}
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
|
|
21991
|
+
let permCount = 0;
|
|
21992
|
+
if (Array.isArray(settings.permissions?.allow)) {
|
|
21993
|
+
const before = settings.permissions.allow.length;
|
|
21994
|
+
settings.permissions.allow = settings.permissions.allow.filter(
|
|
21995
|
+
(p) => !p.startsWith("mcp__exe-mem__") && !p.startsWith("mcp__exe-os__")
|
|
21996
|
+
);
|
|
21997
|
+
permCount = before - settings.permissions.allow.length;
|
|
21998
|
+
}
|
|
21999
|
+
if (!dryRun) {
|
|
22000
|
+
writeFileSync9(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
22001
|
+
}
|
|
22002
|
+
log("\u2713 Removed exe-os hooks from settings.json");
|
|
22003
|
+
if (permCount > 0) log(`\u2713 Removed ${permCount} MCP permission entries`);
|
|
21909
22004
|
removed++;
|
|
21910
22005
|
}
|
|
21911
22006
|
}
|
|
@@ -21915,25 +22010,154 @@ async function runClaudeUninstall() {
|
|
|
21915
22010
|
let removedMcp = false;
|
|
21916
22011
|
for (const key of ["exe-mem", "exe-os"]) {
|
|
21917
22012
|
if (claudeJson.mcpServers[key]) {
|
|
21918
|
-
delete claudeJson.mcpServers[key];
|
|
22013
|
+
if (!dryRun) delete claudeJson.mcpServers[key];
|
|
21919
22014
|
removedMcp = true;
|
|
21920
22015
|
}
|
|
21921
22016
|
}
|
|
21922
22017
|
if (removedMcp) {
|
|
21923
|
-
|
|
21924
|
-
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
);
|
|
21928
|
-
console.log("Removed exe-os MCP server from claude.json");
|
|
22018
|
+
if (!dryRun) {
|
|
22019
|
+
writeFileSync9(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
22020
|
+
}
|
|
22021
|
+
log("\u2713 Removed exe-os MCP server from claude.json");
|
|
21929
22022
|
removed++;
|
|
21930
22023
|
}
|
|
21931
22024
|
}
|
|
21932
22025
|
}
|
|
22026
|
+
const skillsDir = path31.join(claudeDir, "skills");
|
|
22027
|
+
if (existsSync21(skillsDir)) {
|
|
22028
|
+
let skillCount = 0;
|
|
22029
|
+
try {
|
|
22030
|
+
const entries = readdirSync4(skillsDir);
|
|
22031
|
+
for (const entry of entries) {
|
|
22032
|
+
if (entry.startsWith("exe")) {
|
|
22033
|
+
const fullPath = path31.join(skillsDir, entry);
|
|
22034
|
+
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
22035
|
+
skillCount++;
|
|
22036
|
+
}
|
|
22037
|
+
}
|
|
22038
|
+
} catch {
|
|
22039
|
+
}
|
|
22040
|
+
if (skillCount > 0) {
|
|
22041
|
+
log(`\u2713 Removed ${skillCount} skill directories`);
|
|
22042
|
+
removed++;
|
|
22043
|
+
}
|
|
22044
|
+
}
|
|
22045
|
+
const claudeMdPath = path31.join(claudeDir, "CLAUDE.md");
|
|
22046
|
+
if (existsSync21(claudeMdPath)) {
|
|
22047
|
+
const content = readFileSync17(claudeMdPath, "utf8");
|
|
22048
|
+
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
22049
|
+
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
22050
|
+
const startIdx = content.indexOf(startMarker);
|
|
22051
|
+
const endIdx = content.indexOf(endMarker);
|
|
22052
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
22053
|
+
const cleaned = (content.slice(0, startIdx) + content.slice(endIdx + endMarker.length)).replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
22054
|
+
if (!dryRun) writeFileSync9(claudeMdPath, cleaned);
|
|
22055
|
+
log("\u2713 Removed orchestration block from CLAUDE.md");
|
|
22056
|
+
removed++;
|
|
22057
|
+
}
|
|
22058
|
+
}
|
|
22059
|
+
const agentsDir = path31.join(claudeDir, "agents");
|
|
22060
|
+
if (existsSync21(agentsDir)) {
|
|
22061
|
+
let agentCount = 0;
|
|
22062
|
+
try {
|
|
22063
|
+
const entries = readdirSync4(agentsDir).filter((f) => f.endsWith(".md"));
|
|
22064
|
+
let knownNames = /* @__PURE__ */ new Set();
|
|
22065
|
+
const rosterPath = path31.join(exeOsDir, "exe-employees.json");
|
|
22066
|
+
if (existsSync21(rosterPath)) {
|
|
22067
|
+
try {
|
|
22068
|
+
const roster = JSON.parse(readFileSync17(rosterPath, "utf8"));
|
|
22069
|
+
knownNames = new Set(roster.map((e) => e.name));
|
|
22070
|
+
} catch {
|
|
22071
|
+
}
|
|
22072
|
+
}
|
|
22073
|
+
for (const entry of entries) {
|
|
22074
|
+
const name = entry.replace(/\.md$/, "");
|
|
22075
|
+
if (knownNames.has(name)) {
|
|
22076
|
+
if (!dryRun) rmSync(path31.join(agentsDir, entry), { force: true });
|
|
22077
|
+
agentCount++;
|
|
22078
|
+
}
|
|
22079
|
+
}
|
|
22080
|
+
} catch {
|
|
22081
|
+
}
|
|
22082
|
+
if (agentCount > 0) {
|
|
22083
|
+
log(`\u2713 Removed ${agentCount} agent identity files`);
|
|
22084
|
+
removed++;
|
|
22085
|
+
}
|
|
22086
|
+
}
|
|
22087
|
+
const projectsDir = path31.join(claudeDir, "projects");
|
|
22088
|
+
if (existsSync21(projectsDir)) {
|
|
22089
|
+
let projectCount = 0;
|
|
22090
|
+
try {
|
|
22091
|
+
const projects = readdirSync4(projectsDir);
|
|
22092
|
+
for (const proj of projects) {
|
|
22093
|
+
const projSettings = path31.join(projectsDir, proj, "settings.json");
|
|
22094
|
+
if (!existsSync21(projSettings)) continue;
|
|
22095
|
+
try {
|
|
22096
|
+
const pSettings = JSON.parse(readFileSync17(projSettings, "utf8"));
|
|
22097
|
+
let changed = false;
|
|
22098
|
+
if (Array.isArray(pSettings.permissions?.allow)) {
|
|
22099
|
+
const before = pSettings.permissions.allow.length;
|
|
22100
|
+
pSettings.permissions.allow = pSettings.permissions.allow.filter(
|
|
22101
|
+
(p) => !p.startsWith("mcp__exe-mem__") && !p.startsWith("mcp__exe-os__")
|
|
22102
|
+
);
|
|
22103
|
+
if (pSettings.permissions.allow.length < before) changed = true;
|
|
22104
|
+
}
|
|
22105
|
+
if (changed && !dryRun) {
|
|
22106
|
+
writeFileSync9(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
|
|
22107
|
+
}
|
|
22108
|
+
if (changed) projectCount++;
|
|
22109
|
+
} catch {
|
|
22110
|
+
}
|
|
22111
|
+
}
|
|
22112
|
+
} catch {
|
|
22113
|
+
}
|
|
22114
|
+
if (projectCount > 0) {
|
|
22115
|
+
log(`\u2713 Cleaned exe-os entries from ${projectCount} project settings`);
|
|
22116
|
+
removed++;
|
|
22117
|
+
}
|
|
22118
|
+
}
|
|
22119
|
+
try {
|
|
22120
|
+
const { execSync: execSync13 } = await import("child_process");
|
|
22121
|
+
const exeBinPath = execSync13("which exe", { encoding: "utf-8" }).trim();
|
|
22122
|
+
const binDir = path31.dirname(exeBinPath);
|
|
22123
|
+
let symlinkCount = 0;
|
|
22124
|
+
const rosterPath = path31.join(exeOsDir, "exe-employees.json");
|
|
22125
|
+
if (existsSync21(rosterPath)) {
|
|
22126
|
+
const roster = JSON.parse(readFileSync17(rosterPath, "utf8"));
|
|
22127
|
+
for (const emp of roster) {
|
|
22128
|
+
if (emp.name === "exe") continue;
|
|
22129
|
+
for (const suffix of ["", "-opencode"]) {
|
|
22130
|
+
const linkPath = path31.join(binDir, `${emp.name}${suffix}`);
|
|
22131
|
+
if (existsSync21(linkPath)) {
|
|
22132
|
+
if (!dryRun) rmSync(linkPath, { force: true });
|
|
22133
|
+
symlinkCount++;
|
|
22134
|
+
}
|
|
22135
|
+
}
|
|
22136
|
+
}
|
|
22137
|
+
}
|
|
22138
|
+
if (symlinkCount > 0) {
|
|
22139
|
+
log(`\u2713 Removed ${symlinkCount} employee symlinks`);
|
|
22140
|
+
removed++;
|
|
22141
|
+
}
|
|
22142
|
+
} catch {
|
|
22143
|
+
}
|
|
22144
|
+
if (purge && existsSync21(exeOsDir)) {
|
|
22145
|
+
if (!dryRun) {
|
|
22146
|
+
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
22147
|
+
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
22148
|
+
rmSync(exeOsDir, { recursive: true, force: true });
|
|
22149
|
+
}
|
|
22150
|
+
log("\u2713 Purged ~/.exe-os data directory");
|
|
22151
|
+
removed++;
|
|
22152
|
+
}
|
|
21933
22153
|
if (removed === 0) {
|
|
21934
22154
|
console.log("Nothing to remove \u2014 exe-os was not installed.");
|
|
21935
22155
|
} else {
|
|
21936
|
-
|
|
22156
|
+
if (dryRun) {
|
|
22157
|
+
console.log("\nDry run complete. Re-run without --dry-run to apply.");
|
|
22158
|
+
} else {
|
|
22159
|
+
console.log("\nDone. Run \x1B[36mexe-os claude install\x1B[0m to reinstall.");
|
|
22160
|
+
}
|
|
21937
22161
|
}
|
|
21938
22162
|
}
|
|
21939
22163
|
async function checkForUpdateOnBoot() {
|
package/dist/bin/exe-assign.js
CHANGED
|
@@ -1915,7 +1915,8 @@ async function writeMemory(record) {
|
|
|
1915
1915
|
has_error: record.has_error ? 1 : 0,
|
|
1916
1916
|
raw_text: record.raw_text,
|
|
1917
1917
|
vector: record.vector,
|
|
1918
|
-
version:
|
|
1918
|
+
version: 0,
|
|
1919
|
+
// Placeholder — assigned atomically at flush time
|
|
1919
1920
|
task_id: record.task_id ?? null,
|
|
1920
1921
|
importance: record.importance ?? 5,
|
|
1921
1922
|
status: record.status ?? "active",
|
|
@@ -1949,6 +1950,13 @@ async function flushBatch() {
|
|
|
1949
1950
|
_flushing = true;
|
|
1950
1951
|
try {
|
|
1951
1952
|
const batch = _pendingRecords.slice(0);
|
|
1953
|
+
const client = getClient();
|
|
1954
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
1955
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1956
|
+
for (const row of batch) {
|
|
1957
|
+
row.version = baseVersion++;
|
|
1958
|
+
}
|
|
1959
|
+
_nextVersion = baseVersion;
|
|
1952
1960
|
const buildStmt = (row) => {
|
|
1953
1961
|
const hasVector = row.vector !== null;
|
|
1954
1962
|
const taskId = row.task_id ?? null;
|