@askexenow/exe-os 0.8.32 → 0.8.36
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 +332 -348
- package/dist/bin/backfill-responses.js +72 -12
- package/dist/bin/backfill-vectors.js +72 -12
- package/dist/bin/cleanup-stale-review-tasks.js +63 -3
- package/dist/bin/cli.js +1518 -1122
- package/dist/bin/exe-agent.js +4 -4
- package/dist/bin/exe-assign.js +80 -18
- package/dist/bin/exe-boot.js +408 -89
- package/dist/bin/exe-call.js +83 -24
- package/dist/bin/exe-dispatch.js +18 -10
- package/dist/bin/exe-doctor.js +63 -3
- package/dist/bin/exe-export-behaviors.js +64 -3
- package/dist/bin/exe-forget.js +69 -4
- package/dist/bin/exe-gateway.js +121 -36
- package/dist/bin/exe-heartbeat.js +77 -13
- package/dist/bin/exe-kill.js +64 -3
- package/dist/bin/exe-launch-agent.js +162 -35
- package/dist/bin/exe-link.js +946 -0
- package/dist/bin/exe-new-employee.js +121 -36
- package/dist/bin/exe-pending-messages.js +72 -7
- package/dist/bin/exe-pending-notifications.js +63 -3
- package/dist/bin/exe-pending-reviews.js +75 -10
- package/dist/bin/exe-rename.js +1287 -0
- package/dist/bin/exe-review.js +64 -4
- package/dist/bin/exe-search.js +79 -13
- package/dist/bin/exe-session-cleanup.js +91 -26
- package/dist/bin/exe-status.js +64 -4
- package/dist/bin/exe-team.js +64 -4
- package/dist/bin/git-sweep.js +71 -4
- package/dist/bin/graph-backfill.js +64 -3
- package/dist/bin/graph-export.js +64 -3
- package/dist/bin/install.js +3 -3
- package/dist/bin/scan-tasks.js +71 -4
- package/dist/bin/setup.js +156 -38
- package/dist/bin/shard-migrate.js +64 -3
- package/dist/bin/wiki-sync.js +64 -3
- package/dist/gateway/index.js +122 -37
- package/dist/hooks/bug-report-worker.js +209 -23
- package/dist/hooks/commit-complete.js +71 -4
- package/dist/hooks/error-recall.js +79 -13
- package/dist/hooks/ingest-worker.js +129 -43
- package/dist/hooks/instructions-loaded.js +71 -4
- package/dist/hooks/notification.js +71 -4
- package/dist/hooks/post-compact.js +71 -4
- package/dist/hooks/pre-compact.js +71 -4
- package/dist/hooks/pre-tool-use.js +413 -194
- package/dist/hooks/prompt-ingest-worker.js +82 -22
- package/dist/hooks/prompt-submit.js +103 -37
- package/dist/hooks/response-ingest-worker.js +87 -22
- package/dist/hooks/session-end.js +71 -4
- package/dist/hooks/session-start.js +79 -13
- package/dist/hooks/stop.js +71 -4
- package/dist/hooks/subagent-stop.js +71 -4
- package/dist/hooks/summary-worker.js +303 -50
- package/dist/index.js +134 -46
- package/dist/lib/cloud-sync.js +209 -15
- package/dist/lib/consolidation.js +4 -4
- package/dist/lib/database.js +64 -2
- package/dist/lib/device-registry.js +70 -3
- package/dist/lib/employee-templates.js +48 -22
- package/dist/lib/employees.js +34 -1
- package/dist/lib/exe-daemon.js +136 -53
- package/dist/lib/hybrid-search.js +79 -13
- package/dist/lib/identity-templates.js +57 -6
- package/dist/lib/identity.js +3 -3
- package/dist/lib/messaging.js +22 -14
- package/dist/lib/reminders.js +3 -3
- package/dist/lib/schedules.js +63 -3
- package/dist/lib/skill-learning.js +3 -3
- package/dist/lib/status-brief.js +63 -5
- package/dist/lib/store.js +64 -3
- package/dist/lib/task-router.js +4 -2
- package/dist/lib/tasks.js +48 -21
- package/dist/lib/tmux-routing.js +47 -20
- package/dist/mcp/server.js +727 -58
- package/dist/mcp/tools/complete-reminder.js +3 -3
- package/dist/mcp/tools/create-reminder.js +3 -3
- package/dist/mcp/tools/create-task.js +151 -24
- package/dist/mcp/tools/deactivate-behavior.js +3 -3
- package/dist/mcp/tools/list-reminders.js +3 -3
- package/dist/mcp/tools/list-tasks.js +17 -8
- package/dist/mcp/tools/send-message.js +24 -16
- package/dist/mcp/tools/update-task.js +25 -16
- package/dist/runtime/index.js +112 -24
- package/dist/tui/App.js +139 -36
- package/package.json +6 -2
- package/src/commands/exe/rename.md +12 -0
package/dist/tui/App.js
CHANGED
|
@@ -39,6 +39,61 @@ var init_devtools = __esm({
|
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
// src/lib/db-retry.ts
|
|
43
|
+
function isBusyError(err) {
|
|
44
|
+
if (err instanceof Error) {
|
|
45
|
+
const msg = err.message.toLowerCase();
|
|
46
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function delay(ms) {
|
|
51
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
52
|
+
}
|
|
53
|
+
async function retryOnBusy(fn, label) {
|
|
54
|
+
let lastError;
|
|
55
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
56
|
+
try {
|
|
57
|
+
return await fn();
|
|
58
|
+
} catch (err) {
|
|
59
|
+
lastError = err;
|
|
60
|
+
if (!isBusyError(err) || attempt === MAX_RETRIES) {
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
64
|
+
const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
|
|
65
|
+
process.stderr.write(
|
|
66
|
+
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
|
|
67
|
+
`
|
|
68
|
+
);
|
|
69
|
+
await delay(backoff + jitter);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
throw lastError;
|
|
73
|
+
}
|
|
74
|
+
function wrapWithRetry(client) {
|
|
75
|
+
return new Proxy(client, {
|
|
76
|
+
get(target, prop, receiver) {
|
|
77
|
+
if (prop === "execute") {
|
|
78
|
+
return (sql) => retryOnBusy(() => target.execute(sql), "execute");
|
|
79
|
+
}
|
|
80
|
+
if (prop === "batch") {
|
|
81
|
+
return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
|
|
82
|
+
}
|
|
83
|
+
return Reflect.get(target, prop, receiver);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
88
|
+
var init_db_retry = __esm({
|
|
89
|
+
"src/lib/db-retry.ts"() {
|
|
90
|
+
"use strict";
|
|
91
|
+
MAX_RETRIES = 3;
|
|
92
|
+
BASE_DELAY_MS = 200;
|
|
93
|
+
MAX_JITTER_MS = 300;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
42
97
|
// src/lib/database.ts
|
|
43
98
|
var database_exports = {};
|
|
44
99
|
__export(database_exports, {
|
|
@@ -46,6 +101,7 @@ __export(database_exports, {
|
|
|
46
101
|
disposeTurso: () => disposeTurso,
|
|
47
102
|
ensureSchema: () => ensureSchema,
|
|
48
103
|
getClient: () => getClient,
|
|
104
|
+
getRawClient: () => getRawClient,
|
|
49
105
|
initDatabase: () => initDatabase,
|
|
50
106
|
initTurso: () => initTurso,
|
|
51
107
|
isInitialized: () => isInitialized
|
|
@@ -55,6 +111,7 @@ async function initDatabase(config) {
|
|
|
55
111
|
if (_client) {
|
|
56
112
|
_client.close();
|
|
57
113
|
_client = null;
|
|
114
|
+
_resilientClient = null;
|
|
58
115
|
}
|
|
59
116
|
const opts = {
|
|
60
117
|
url: `file:${config.dbPath}`
|
|
@@ -63,20 +120,27 @@ async function initDatabase(config) {
|
|
|
63
120
|
opts.encryptionKey = config.encryptionKey;
|
|
64
121
|
}
|
|
65
122
|
_client = createClient(opts);
|
|
123
|
+
_resilientClient = wrapWithRetry(_client);
|
|
66
124
|
}
|
|
67
125
|
function isInitialized() {
|
|
68
126
|
return _client !== null;
|
|
69
127
|
}
|
|
70
128
|
function getClient() {
|
|
129
|
+
if (!_resilientClient) {
|
|
130
|
+
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
131
|
+
}
|
|
132
|
+
return _resilientClient;
|
|
133
|
+
}
|
|
134
|
+
function getRawClient() {
|
|
71
135
|
if (!_client) {
|
|
72
136
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
73
137
|
}
|
|
74
138
|
return _client;
|
|
75
139
|
}
|
|
76
140
|
async function ensureSchema() {
|
|
77
|
-
const client =
|
|
141
|
+
const client = getRawClient();
|
|
78
142
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
79
|
-
await client.execute("PRAGMA busy_timeout =
|
|
143
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
80
144
|
try {
|
|
81
145
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
82
146
|
} catch {
|
|
@@ -869,13 +933,16 @@ async function disposeDatabase() {
|
|
|
869
933
|
if (_client) {
|
|
870
934
|
_client.close();
|
|
871
935
|
_client = null;
|
|
936
|
+
_resilientClient = null;
|
|
872
937
|
}
|
|
873
938
|
}
|
|
874
|
-
var _client, initTurso, disposeTurso;
|
|
939
|
+
var _client, _resilientClient, initTurso, disposeTurso;
|
|
875
940
|
var init_database = __esm({
|
|
876
941
|
"src/lib/database.ts"() {
|
|
877
942
|
"use strict";
|
|
943
|
+
init_db_retry();
|
|
878
944
|
_client = null;
|
|
945
|
+
_resilientClient = null;
|
|
879
946
|
initTurso = initDatabase;
|
|
880
947
|
disposeTurso = disposeDatabase;
|
|
881
948
|
}
|
|
@@ -3755,13 +3822,18 @@ __export(employees_exports, {
|
|
|
3755
3822
|
EMPLOYEES_PATH: () => EMPLOYEES_PATH,
|
|
3756
3823
|
addEmployee: () => addEmployee,
|
|
3757
3824
|
getEmployee: () => getEmployee,
|
|
3825
|
+
getEmployeeByRole: () => getEmployeeByRole,
|
|
3826
|
+
getEmployeeNamesByRole: () => getEmployeeNamesByRole,
|
|
3827
|
+
hasRole: () => hasRole,
|
|
3828
|
+
isMultiInstance: () => isMultiInstance,
|
|
3758
3829
|
loadEmployees: () => loadEmployees,
|
|
3830
|
+
loadEmployeesSync: () => loadEmployeesSync,
|
|
3759
3831
|
registerBinSymlinks: () => registerBinSymlinks,
|
|
3760
3832
|
saveEmployees: () => saveEmployees,
|
|
3761
3833
|
validateEmployeeName: () => validateEmployeeName
|
|
3762
3834
|
});
|
|
3763
3835
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
3764
|
-
import { existsSync as existsSync5, symlinkSync, readlinkSync } from "fs";
|
|
3836
|
+
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync5 } from "fs";
|
|
3765
3837
|
import { execSync as execSync3 } from "child_process";
|
|
3766
3838
|
import path10 from "path";
|
|
3767
3839
|
function validateEmployeeName(name) {
|
|
@@ -3794,9 +3866,36 @@ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
|
3794
3866
|
await mkdir2(path10.dirname(employeesPath), { recursive: true });
|
|
3795
3867
|
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
3796
3868
|
}
|
|
3869
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
3870
|
+
if (!existsSync5(employeesPath)) return [];
|
|
3871
|
+
try {
|
|
3872
|
+
return JSON.parse(readFileSync5(employeesPath, "utf-8"));
|
|
3873
|
+
} catch {
|
|
3874
|
+
return [];
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3797
3877
|
function getEmployee(employees, name) {
|
|
3798
3878
|
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
3799
3879
|
}
|
|
3880
|
+
function getEmployeeByRole(employees, role) {
|
|
3881
|
+
const lower = role.toLowerCase();
|
|
3882
|
+
return employees.find((e) => e.role.toLowerCase() === lower);
|
|
3883
|
+
}
|
|
3884
|
+
function getEmployeeNamesByRole(employees, role) {
|
|
3885
|
+
const lower = role.toLowerCase();
|
|
3886
|
+
return employees.filter((e) => e.role.toLowerCase() === lower).map((e) => e.name);
|
|
3887
|
+
}
|
|
3888
|
+
function hasRole(agentName, role) {
|
|
3889
|
+
const employees = loadEmployeesSync();
|
|
3890
|
+
const emp = getEmployee(employees, agentName);
|
|
3891
|
+
return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
|
|
3892
|
+
}
|
|
3893
|
+
function isMultiInstance(agentName, employees) {
|
|
3894
|
+
const roster = employees ?? loadEmployeesSync();
|
|
3895
|
+
const emp = getEmployee(roster, agentName);
|
|
3896
|
+
if (!emp) return false;
|
|
3897
|
+
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
3898
|
+
}
|
|
3800
3899
|
function addEmployee(employees, employee) {
|
|
3801
3900
|
const normalized = { ...employee, name: employee.name.toLowerCase() };
|
|
3802
3901
|
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
@@ -3839,12 +3938,13 @@ function registerBinSymlinks(name) {
|
|
|
3839
3938
|
}
|
|
3840
3939
|
return { created, skipped, errors };
|
|
3841
3940
|
}
|
|
3842
|
-
var EMPLOYEES_PATH;
|
|
3941
|
+
var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
|
|
3843
3942
|
var init_employees = __esm({
|
|
3844
3943
|
"src/lib/employees.ts"() {
|
|
3845
3944
|
"use strict";
|
|
3846
3945
|
init_config();
|
|
3847
3946
|
EMPLOYEES_PATH = path10.join(EXE_AI_DIR, "exe-employees.json");
|
|
3947
|
+
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
3848
3948
|
}
|
|
3849
3949
|
});
|
|
3850
3950
|
|
|
@@ -3918,12 +4018,14 @@ var init_task_router = __esm({
|
|
|
3918
4018
|
},
|
|
3919
4019
|
tierRules: {
|
|
3920
4020
|
junior: {
|
|
3921
|
-
eligible: [
|
|
4021
|
+
eligible: [],
|
|
4022
|
+
// resolved dynamically from roster (Principal Engineer role)
|
|
3922
4023
|
reviewRequired: false,
|
|
3923
4024
|
manualOnly: false
|
|
3924
4025
|
},
|
|
3925
4026
|
standard: {
|
|
3926
|
-
eligible: [
|
|
4027
|
+
eligible: [],
|
|
4028
|
+
// resolved dynamically from roster (Principal Engineer role)
|
|
3927
4029
|
reviewRequired: false,
|
|
3928
4030
|
manualOnly: false
|
|
3929
4031
|
},
|
|
@@ -4167,7 +4269,7 @@ var init_provider_table = __esm({
|
|
|
4167
4269
|
});
|
|
4168
4270
|
|
|
4169
4271
|
// src/lib/intercom-queue.ts
|
|
4170
|
-
import { readFileSync as
|
|
4272
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
4171
4273
|
import path11 from "path";
|
|
4172
4274
|
import os4 from "os";
|
|
4173
4275
|
function ensureDir() {
|
|
@@ -4177,7 +4279,7 @@ function ensureDir() {
|
|
|
4177
4279
|
function readQueue() {
|
|
4178
4280
|
try {
|
|
4179
4281
|
if (!existsSync6(QUEUE_PATH)) return [];
|
|
4180
|
-
return JSON.parse(
|
|
4282
|
+
return JSON.parse(readFileSync6(QUEUE_PATH, "utf8"));
|
|
4181
4283
|
} catch {
|
|
4182
4284
|
return [];
|
|
4183
4285
|
}
|
|
@@ -4216,12 +4318,12 @@ var init_intercom_queue = __esm({
|
|
|
4216
4318
|
});
|
|
4217
4319
|
|
|
4218
4320
|
// src/lib/plan-limits.ts
|
|
4219
|
-
import { readFileSync as
|
|
4321
|
+
import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
|
|
4220
4322
|
import path12 from "path";
|
|
4221
4323
|
function getLicenseSync() {
|
|
4222
4324
|
try {
|
|
4223
4325
|
if (!existsSync7(CACHE_PATH2)) return freeLicense();
|
|
4224
|
-
const raw = JSON.parse(
|
|
4326
|
+
const raw = JSON.parse(readFileSync7(CACHE_PATH2, "utf8"));
|
|
4225
4327
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
4226
4328
|
const parts = raw.token.split(".");
|
|
4227
4329
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -4260,7 +4362,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
4260
4362
|
let count = 0;
|
|
4261
4363
|
try {
|
|
4262
4364
|
if (existsSync7(filePath)) {
|
|
4263
|
-
const raw =
|
|
4365
|
+
const raw = readFileSync7(filePath, "utf8");
|
|
4264
4366
|
const employees = JSON.parse(raw);
|
|
4265
4367
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
4266
4368
|
}
|
|
@@ -4298,7 +4400,7 @@ import crypto from "crypto";
|
|
|
4298
4400
|
import path13 from "path";
|
|
4299
4401
|
import os5 from "os";
|
|
4300
4402
|
import {
|
|
4301
|
-
readFileSync as
|
|
4403
|
+
readFileSync as readFileSync8,
|
|
4302
4404
|
readdirSync,
|
|
4303
4405
|
unlinkSync,
|
|
4304
4406
|
existsSync as existsSync8,
|
|
@@ -4384,7 +4486,7 @@ import crypto3 from "crypto";
|
|
|
4384
4486
|
import path14 from "path";
|
|
4385
4487
|
import { execSync as execSync6 } from "child_process";
|
|
4386
4488
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4387
|
-
import { existsSync as existsSync9, readFileSync as
|
|
4489
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
4388
4490
|
async function writeCheckpoint(input) {
|
|
4389
4491
|
const client = getClient();
|
|
4390
4492
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -4761,7 +4863,7 @@ async function ensureGitignoreExe(baseDir) {
|
|
|
4761
4863
|
const gitignorePath = path14.join(baseDir, ".gitignore");
|
|
4762
4864
|
try {
|
|
4763
4865
|
if (existsSync9(gitignorePath)) {
|
|
4764
|
-
const content =
|
|
4866
|
+
const content = readFileSync9(gitignorePath, "utf-8");
|
|
4765
4867
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
4766
4868
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
4767
4869
|
} else {
|
|
@@ -5137,7 +5239,7 @@ async function dispatchTaskToEmployee(input) {
|
|
|
5137
5239
|
} else {
|
|
5138
5240
|
const projectDir = input.projectDir ?? process.cwd();
|
|
5139
5241
|
const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
|
|
5140
|
-
autoInstance: input.assignedTo
|
|
5242
|
+
autoInstance: isMultiInstance(input.assignedTo)
|
|
5141
5243
|
});
|
|
5142
5244
|
if (result.status === "failed") {
|
|
5143
5245
|
process.stderr.write(
|
|
@@ -5172,6 +5274,7 @@ var init_tasks_notify = __esm({
|
|
|
5172
5274
|
init_session_key();
|
|
5173
5275
|
init_notifications();
|
|
5174
5276
|
init_transport();
|
|
5277
|
+
init_employees();
|
|
5175
5278
|
}
|
|
5176
5279
|
});
|
|
5177
5280
|
|
|
@@ -5945,7 +6048,7 @@ __export(tmux_routing_exports, {
|
|
|
5945
6048
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
5946
6049
|
});
|
|
5947
6050
|
import { execFileSync as execFileSync3, execSync as execSync8 } from "child_process";
|
|
5948
|
-
import { readFileSync as
|
|
6051
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync11, appendFileSync } from "fs";
|
|
5949
6052
|
import path19 from "path";
|
|
5950
6053
|
import os6 from "os";
|
|
5951
6054
|
import { fileURLToPath } from "url";
|
|
@@ -6012,7 +6115,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
6012
6115
|
}
|
|
6013
6116
|
function getParentExe(sessionKey) {
|
|
6014
6117
|
try {
|
|
6015
|
-
const data = JSON.parse(
|
|
6118
|
+
const data = JSON.parse(readFileSync10(path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
6016
6119
|
return data.parentExe || null;
|
|
6017
6120
|
} catch {
|
|
6018
6121
|
return null;
|
|
@@ -6020,7 +6123,7 @@ function getParentExe(sessionKey) {
|
|
|
6020
6123
|
}
|
|
6021
6124
|
function getDispatchedBy(sessionKey) {
|
|
6022
6125
|
try {
|
|
6023
|
-
const data = JSON.parse(
|
|
6126
|
+
const data = JSON.parse(readFileSync10(
|
|
6024
6127
|
path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
6025
6128
|
"utf8"
|
|
6026
6129
|
));
|
|
@@ -6083,7 +6186,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
6083
6186
|
function readDebounceState() {
|
|
6084
6187
|
try {
|
|
6085
6188
|
if (!existsSync11(DEBOUNCE_FILE)) return {};
|
|
6086
|
-
return JSON.parse(
|
|
6189
|
+
return JSON.parse(readFileSync10(DEBOUNCE_FILE, "utf8"));
|
|
6087
6190
|
} catch {
|
|
6088
6191
|
return {};
|
|
6089
6192
|
}
|
|
@@ -6283,7 +6386,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6283
6386
|
const claudeJsonPath = path19.join(os6.homedir(), ".claude.json");
|
|
6284
6387
|
let claudeJson = {};
|
|
6285
6388
|
try {
|
|
6286
|
-
claudeJson = JSON.parse(
|
|
6389
|
+
claudeJson = JSON.parse(readFileSync10(claudeJsonPath, "utf8"));
|
|
6287
6390
|
} catch {
|
|
6288
6391
|
}
|
|
6289
6392
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -6301,7 +6404,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6301
6404
|
const settingsPath = path19.join(projSettingsDir, "settings.json");
|
|
6302
6405
|
let settings = {};
|
|
6303
6406
|
try {
|
|
6304
|
-
settings = JSON.parse(
|
|
6407
|
+
settings = JSON.parse(readFileSync10(settingsPath, "utf8"));
|
|
6305
6408
|
} catch {
|
|
6306
6409
|
}
|
|
6307
6410
|
const perms = settings.permissions ?? {};
|
|
@@ -7370,7 +7473,7 @@ function listShards() {
|
|
|
7370
7473
|
}
|
|
7371
7474
|
async function ensureShardSchema(client) {
|
|
7372
7475
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
7373
|
-
await client.execute("PRAGMA busy_timeout =
|
|
7476
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
7374
7477
|
try {
|
|
7375
7478
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
7376
7479
|
} catch {
|
|
@@ -14635,7 +14738,7 @@ function CommandCenterView({
|
|
|
14635
14738
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
14636
14739
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
14637
14740
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
14638
|
-
const { readFileSync:
|
|
14741
|
+
const { readFileSync: readFileSync11, existsSync: existsSync14 } = await import("fs");
|
|
14639
14742
|
const { join } = await import("path");
|
|
14640
14743
|
const { homedir } = await import("os");
|
|
14641
14744
|
const configPath = join(homedir(), ".exe-os", "config.json");
|
|
@@ -14643,7 +14746,7 @@ function CommandCenterView({
|
|
|
14643
14746
|
let providerConfigs = {};
|
|
14644
14747
|
if (existsSync14(configPath)) {
|
|
14645
14748
|
try {
|
|
14646
|
-
const raw = JSON.parse(
|
|
14749
|
+
const raw = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
14647
14750
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
14648
14751
|
if (raw.providers && typeof raw.providers === "object") {
|
|
14649
14752
|
providerConfigs = raw.providers;
|
|
@@ -14704,7 +14807,7 @@ function CommandCenterView({
|
|
|
14704
14807
|
const markerDir = join(homedir(), ".exe-os", "session-cache");
|
|
14705
14808
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
14706
14809
|
for (const f of agentFiles) {
|
|
14707
|
-
const data = JSON.parse(
|
|
14810
|
+
const data = JSON.parse(readFileSync11(join(markerDir, f), "utf8"));
|
|
14708
14811
|
if (data.agentRole) {
|
|
14709
14812
|
agentRole = data.agentRole;
|
|
14710
14813
|
break;
|
|
@@ -16397,12 +16500,12 @@ async function loadGatewayConfig() {
|
|
|
16397
16500
|
state.running = false;
|
|
16398
16501
|
}
|
|
16399
16502
|
try {
|
|
16400
|
-
const { existsSync: existsSync14, readFileSync:
|
|
16503
|
+
const { existsSync: existsSync14, readFileSync: readFileSync11 } = await import("fs");
|
|
16401
16504
|
const { join } = await import("path");
|
|
16402
16505
|
const home = process.env.HOME ?? "";
|
|
16403
16506
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
16404
16507
|
if (existsSync14(configPath)) {
|
|
16405
|
-
const raw = JSON.parse(
|
|
16508
|
+
const raw = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
16406
16509
|
state.port = raw.port ?? 3100;
|
|
16407
16510
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
16408
16511
|
if (raw.adapters) {
|
|
@@ -16872,12 +16975,12 @@ function TeamView({ onBack }) {
|
|
|
16872
16975
|
setMembers(teamData);
|
|
16873
16976
|
setDbError(false);
|
|
16874
16977
|
try {
|
|
16875
|
-
const { existsSync: existsSync14, readFileSync:
|
|
16978
|
+
const { existsSync: existsSync14, readFileSync: readFileSync11 } = await import("fs");
|
|
16876
16979
|
const { join } = await import("path");
|
|
16877
16980
|
const home = process.env.HOME ?? "";
|
|
16878
16981
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
16879
16982
|
if (existsSync14(gatewayConfig)) {
|
|
16880
|
-
const raw = JSON.parse(
|
|
16983
|
+
const raw = JSON.parse(readFileSync11(gatewayConfig, "utf8"));
|
|
16881
16984
|
if (raw.agents && raw.agents.length > 0) {
|
|
16882
16985
|
setExternals(raw.agents.map((a) => ({
|
|
16883
16986
|
name: a.name,
|
|
@@ -17413,14 +17516,14 @@ function SettingsView({ onBack }) {
|
|
|
17413
17516
|
try {
|
|
17414
17517
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
17415
17518
|
const roster = await loadEmployees2();
|
|
17416
|
-
const { existsSync: existsSync14, readFileSync:
|
|
17519
|
+
const { existsSync: existsSync14, readFileSync: readFileSync11 } = await import("fs");
|
|
17417
17520
|
const { join } = await import("path");
|
|
17418
17521
|
const home = process.env.HOME ?? "";
|
|
17419
17522
|
const configPath = join(home, ".exe-os", "config.json");
|
|
17420
17523
|
let empConfig = {};
|
|
17421
17524
|
if (existsSync14(configPath)) {
|
|
17422
17525
|
try {
|
|
17423
|
-
const raw = JSON.parse(
|
|
17526
|
+
const raw = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
17424
17527
|
if (raw.employees && typeof raw.employees === "object") {
|
|
17425
17528
|
empConfig = raw.employees;
|
|
17426
17529
|
}
|
|
@@ -17435,7 +17538,7 @@ function SettingsView({ onBack }) {
|
|
|
17435
17538
|
} catch {
|
|
17436
17539
|
}
|
|
17437
17540
|
try {
|
|
17438
|
-
const { existsSync: existsSync14, readFileSync:
|
|
17541
|
+
const { existsSync: existsSync14, readFileSync: readFileSync11 } = await import("fs");
|
|
17439
17542
|
const { join } = await import("path");
|
|
17440
17543
|
const home = process.env.HOME ?? "";
|
|
17441
17544
|
const ccSettingsPath = join(home, ".claude", "settings.json");
|
|
@@ -17443,7 +17546,7 @@ function SettingsView({ onBack }) {
|
|
|
17443
17546
|
let hooksWired = false;
|
|
17444
17547
|
if (installed) {
|
|
17445
17548
|
try {
|
|
17446
|
-
const settings = JSON.parse(
|
|
17549
|
+
const settings = JSON.parse(readFileSync11(ccSettingsPath, "utf8"));
|
|
17447
17550
|
const hooks = settings.hooks;
|
|
17448
17551
|
if (hooks) {
|
|
17449
17552
|
hooksWired = Object.values(hooks).flat().some((h) => h.command?.includes("exe-os") || h.command?.includes("exe-mem"));
|
|
@@ -17455,13 +17558,13 @@ function SettingsView({ onBack }) {
|
|
|
17455
17558
|
} catch {
|
|
17456
17559
|
}
|
|
17457
17560
|
try {
|
|
17458
|
-
const { existsSync: existsSync14, readFileSync:
|
|
17561
|
+
const { existsSync: existsSync14, readFileSync: readFileSync11 } = await import("fs");
|
|
17459
17562
|
const { join } = await import("path");
|
|
17460
17563
|
const home = process.env.HOME ?? "";
|
|
17461
17564
|
const licensePath = join(home, ".exe-os", "license.json");
|
|
17462
17565
|
if (existsSync14(licensePath)) {
|
|
17463
17566
|
try {
|
|
17464
|
-
const lic = JSON.parse(
|
|
17567
|
+
const lic = JSON.parse(readFileSync11(licensePath, "utf8"));
|
|
17465
17568
|
setLicense({ valid: lic.valid !== false, detail: lic.plan ?? "licensed" });
|
|
17466
17569
|
} catch {
|
|
17467
17570
|
setLicense({ valid: false, detail: "invalid license file" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.36",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "CC-BY-NC-4.0",
|
|
6
6
|
"type": "module",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"exe-os-install": "./dist/bin/install.js",
|
|
28
28
|
"exe-agent": "./dist/bin/exe-agent.js",
|
|
29
29
|
"exe-os-backfill-responses": "./dist/bin/backfill-responses.js",
|
|
30
|
+
"exe-os-backfill-conversations": "./dist/bin/backfill-conversations.js",
|
|
30
31
|
"exe-os-repo-drift": "./dist/bin/exe-repo-drift.js",
|
|
31
32
|
"exe-kill": "./dist/bin/exe-kill.js",
|
|
32
33
|
"exe-os-list-providers": "./dist/bin/list-providers.js",
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
"test:watch": "vitest",
|
|
66
67
|
"typecheck": "tsc --noEmit",
|
|
67
68
|
"build": "tsup",
|
|
68
|
-
"deploy": "tsup && npm install -g . && node dist/bin/install.js --global",
|
|
69
|
+
"deploy": "node dist/bin/pre-build-guard.js 2>/dev/null; tsup && npm install -g . && node dist/bin/install.js --global && echo '[exe-os] Deploy complete. MCP servers will auto-reconnect on next tool call.'",
|
|
69
70
|
"postinstall": "node dist/bin/install.js --global 2>/dev/null || true",
|
|
70
71
|
"prepublishOnly": "npm run typecheck && npm run build && npx vitest run --exclude 'tests/tui/**' --exclude 'tests/lib/tmux-routing.test.ts' --exclude 'tests/lib/intercom-routing.test.ts' --exclude 'tests/gateway/**' --exclude 'tests/installer/setup-wizard.test.ts' --exclude 'tests/mcp/ingest-document.test.ts' --exclude 'tests/lib/hybrid-search.test.ts'"
|
|
71
72
|
},
|
|
@@ -74,6 +75,9 @@
|
|
|
74
75
|
"@discordjs/voice": "^0.19.2",
|
|
75
76
|
"@libsql/client": "^0.14.0",
|
|
76
77
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
78
|
+
"@opentelemetry/api": "^1.9.1",
|
|
79
|
+
"@opentelemetry/sdk-node": "^0.215.0",
|
|
80
|
+
"@opentelemetry/sdk-trace-base": "^2.7.0",
|
|
77
81
|
"@slack/bolt": "^4.7.0",
|
|
78
82
|
"@slack/web-api": "^7.15.1",
|
|
79
83
|
"@types/react": "^19.2.14",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Rename an employee across all systems (roster, identity, agent file, symlinks, DB)
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
argument-hint: <oldName> <newName>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Atomically rename an employee. Updates roster, identity file, agent file, bin symlinks, and all database references.
|
|
8
|
+
|
|
9
|
+
Run this command:
|
|
10
|
+
```bash
|
|
11
|
+
node "$(npm root -g)/@askexenow/exe-os/dist/bin/exe-rename.js" $ARGUMENTS
|
|
12
|
+
```
|