@askexenow/exe-os 0.9.38 → 0.9.40
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 +34 -7
- package/dist/bin/backfill-responses.js +34 -7
- package/dist/bin/backfill-vectors.js +34 -7
- package/dist/bin/cleanup-stale-review-tasks.js +35 -8
- package/dist/bin/cli.js +108 -45
- package/dist/bin/exe-agent.js +11 -3
- package/dist/bin/exe-assign.js +34 -7
- package/dist/bin/exe-boot.js +48 -18
- package/dist/bin/exe-call.js +132 -340
- package/dist/bin/exe-dispatch.js +34 -7
- package/dist/bin/exe-doctor.js +37 -10
- package/dist/bin/exe-export-behaviors.js +36 -9
- package/dist/bin/exe-forget.js +34 -7
- package/dist/bin/exe-gateway.js +40 -12
- package/dist/bin/exe-heartbeat.js +35 -8
- package/dist/bin/exe-kill.js +34 -7
- package/dist/bin/exe-launch-agent.js +285 -1079
- package/dist/bin/exe-new-employee.js +29 -10
- package/dist/bin/exe-pending-messages.js +34 -7
- package/dist/bin/exe-pending-notifications.js +34 -7
- package/dist/bin/exe-pending-reviews.js +34 -7
- package/dist/bin/exe-rename.js +41 -13
- package/dist/bin/exe-review.js +34 -7
- package/dist/bin/exe-search.js +36 -9
- package/dist/bin/exe-session-cleanup.js +36 -9
- package/dist/bin/exe-start-codex.js +36 -9
- package/dist/bin/exe-start-opencode.js +36 -9
- package/dist/bin/exe-status.js +35 -8
- package/dist/bin/exe-team.js +34 -7
- package/dist/bin/git-sweep.js +34 -7
- package/dist/bin/graph-backfill.js +34 -7
- package/dist/bin/graph-export.js +34 -7
- package/dist/bin/install.js +2 -1
- package/dist/bin/intercom-check.js +36 -9
- package/dist/bin/scan-tasks.js +34 -7
- package/dist/bin/setup.js +18 -17
- package/dist/bin/shard-migrate.js +34 -7
- package/dist/bin/update.js +36 -3
- package/dist/gateway/index.js +38 -10
- package/dist/hooks/bug-report-worker.js +38 -10
- package/dist/hooks/codex-stop-task-finalizer.js +36 -9
- package/dist/hooks/commit-complete.js +34 -7
- package/dist/hooks/error-recall.js +36 -9
- package/dist/hooks/ingest.js +36 -8
- package/dist/hooks/instructions-loaded.js +42 -10
- package/dist/hooks/notification.js +34 -7
- package/dist/hooks/post-compact.js +34 -7
- package/dist/hooks/post-tool-combined.js +37 -10
- package/dist/hooks/pre-compact.js +35 -8
- package/dist/hooks/pre-tool-use.js +36 -8
- package/dist/hooks/prompt-submit.js +41 -13
- package/dist/hooks/session-end.js +35 -8
- package/dist/hooks/session-start.js +47 -14
- package/dist/hooks/stop.js +35 -8
- package/dist/hooks/subagent-stop.js +34 -7
- package/dist/hooks/summary-worker.js +43 -16
- package/dist/index.js +36 -8
- package/dist/lib/consolidation.js +2 -1
- package/dist/lib/employee-templates.js +2 -1
- package/dist/lib/employees.js +2 -1
- package/dist/lib/exe-daemon.js +136 -36
- package/dist/lib/hybrid-search.js +36 -9
- package/dist/lib/identity.js +8 -3
- package/dist/lib/schedules.js +34 -7
- package/dist/lib/store.js +34 -7
- package/dist/mcp/server.js +133 -33
- package/dist/mcp/tools/create-task.js +10 -4
- package/dist/runtime/index.js +34 -7
- package/dist/tui/App.js +40 -11
- package/package.json +2 -2
package/dist/bin/cli.js
CHANGED
|
@@ -540,7 +540,8 @@ function isMultiInstance(agentName, employees) {
|
|
|
540
540
|
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
541
541
|
}
|
|
542
542
|
function addEmployee(employees, employee) {
|
|
543
|
-
const
|
|
543
|
+
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
544
|
+
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
544
545
|
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
545
546
|
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
546
547
|
}
|
|
@@ -4864,8 +4865,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
4864
4865
|
}
|
|
4865
4866
|
function getCacheAgeMs() {
|
|
4866
4867
|
try {
|
|
4867
|
-
const { statSync:
|
|
4868
|
-
const s =
|
|
4868
|
+
const { statSync: statSync5 } = __require("fs");
|
|
4869
|
+
const s = statSync5(CACHE_PATH);
|
|
4869
4870
|
return Date.now() - s.mtimeMs;
|
|
4870
4871
|
} catch {
|
|
4871
4872
|
return Infinity;
|
|
@@ -7102,7 +7103,7 @@ __export(shard_manager_exports, {
|
|
|
7102
7103
|
shardExists: () => shardExists
|
|
7103
7104
|
});
|
|
7104
7105
|
import path15 from "path";
|
|
7105
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync3 } from "fs";
|
|
7106
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync3, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
7106
7107
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7107
7108
|
function initShardManager(encryptionKey) {
|
|
7108
7109
|
_encryptionKey = encryptionKey;
|
|
@@ -7124,7 +7125,7 @@ function getShardClient(projectName) {
|
|
|
7124
7125
|
if (!_encryptionKey) {
|
|
7125
7126
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
7126
7127
|
}
|
|
7127
|
-
const safeName = projectName
|
|
7128
|
+
const safeName = safeShardName(projectName);
|
|
7128
7129
|
if (!safeName || safeName === "unknown") {
|
|
7129
7130
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
7130
7131
|
}
|
|
@@ -7146,9 +7147,12 @@ function getShardClient(projectName) {
|
|
|
7146
7147
|
return client;
|
|
7147
7148
|
}
|
|
7148
7149
|
function shardExists(projectName) {
|
|
7149
|
-
const safeName = projectName
|
|
7150
|
+
const safeName = safeShardName(projectName);
|
|
7150
7151
|
return existsSync15(path15.join(SHARDS_DIR, `${safeName}.db`));
|
|
7151
7152
|
}
|
|
7153
|
+
function safeShardName(projectName) {
|
|
7154
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7155
|
+
}
|
|
7152
7156
|
function listShards() {
|
|
7153
7157
|
if (!existsSync15(SHARDS_DIR)) return [];
|
|
7154
7158
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -7242,7 +7246,8 @@ async function ensureShardSchema(client) {
|
|
|
7242
7246
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
7243
7247
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
7244
7248
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
7245
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
7249
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
7250
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
7246
7251
|
]) {
|
|
7247
7252
|
try {
|
|
7248
7253
|
await client.execute(col);
|
|
@@ -7338,9 +7343,32 @@ async function ensureShardSchema(client) {
|
|
|
7338
7343
|
}
|
|
7339
7344
|
}
|
|
7340
7345
|
async function getReadyShardClient(projectName) {
|
|
7341
|
-
const
|
|
7342
|
-
|
|
7343
|
-
|
|
7346
|
+
const safeName = safeShardName(projectName);
|
|
7347
|
+
let client = getShardClient(projectName);
|
|
7348
|
+
try {
|
|
7349
|
+
await ensureShardSchema(client);
|
|
7350
|
+
return client;
|
|
7351
|
+
} catch (err) {
|
|
7352
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7353
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
7354
|
+
client.close();
|
|
7355
|
+
_shards.delete(safeName);
|
|
7356
|
+
_shardLastAccess.delete(safeName);
|
|
7357
|
+
const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
|
|
7358
|
+
if (existsSync15(dbPath)) {
|
|
7359
|
+
const stat2 = statSync4(dbPath);
|
|
7360
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7361
|
+
const archivedPath = path15.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7362
|
+
renameSync3(dbPath, archivedPath);
|
|
7363
|
+
process.stderr.write(
|
|
7364
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat2.size} bytes, mtime ${stat2.mtime.toISOString()})
|
|
7365
|
+
`
|
|
7366
|
+
);
|
|
7367
|
+
}
|
|
7368
|
+
client = getShardClient(projectName);
|
|
7369
|
+
await ensureShardSchema(client);
|
|
7370
|
+
return client;
|
|
7371
|
+
}
|
|
7344
7372
|
}
|
|
7345
7373
|
function evictLRU() {
|
|
7346
7374
|
let oldest = null;
|
|
@@ -9264,6 +9292,9 @@ function ensureDir() {
|
|
|
9264
9292
|
function identityPath(agentId) {
|
|
9265
9293
|
return path17.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
9266
9294
|
}
|
|
9295
|
+
function sanitizeIdentityBody(body) {
|
|
9296
|
+
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
9297
|
+
}
|
|
9267
9298
|
function parseFrontmatter(raw) {
|
|
9268
9299
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
9269
9300
|
if (!match) {
|
|
@@ -9276,11 +9307,11 @@ function parseFrontmatter(raw) {
|
|
|
9276
9307
|
created_by: "system",
|
|
9277
9308
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
9278
9309
|
},
|
|
9279
|
-
body: raw
|
|
9310
|
+
body: sanitizeIdentityBody(raw)
|
|
9280
9311
|
};
|
|
9281
9312
|
}
|
|
9282
9313
|
const yamlStr = match[1];
|
|
9283
|
-
const body = match[2]
|
|
9314
|
+
const body = sanitizeIdentityBody(match[2]);
|
|
9284
9315
|
const fm = {};
|
|
9285
9316
|
for (const line of yamlStr.split("\n")) {
|
|
9286
9317
|
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
@@ -9345,7 +9376,9 @@ function listIdentities() {
|
|
|
9345
9376
|
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
9346
9377
|
results.push({
|
|
9347
9378
|
agentId,
|
|
9348
|
-
title
|
|
9379
|
+
// User-facing/team-facing title only. `frontmatter.role` is internal
|
|
9380
|
+
// routing metadata and must not leak as an external title.
|
|
9381
|
+
title: identity.frontmatter.title,
|
|
9349
9382
|
summary
|
|
9350
9383
|
});
|
|
9351
9384
|
}
|
|
@@ -10176,7 +10209,7 @@ __export(intercom_queue_exports, {
|
|
|
10176
10209
|
queueIntercom: () => queueIntercom,
|
|
10177
10210
|
readQueue: () => readQueue
|
|
10178
10211
|
});
|
|
10179
|
-
import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as
|
|
10212
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as renameSync4, existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
|
|
10180
10213
|
import path21 from "path";
|
|
10181
10214
|
import os12 from "os";
|
|
10182
10215
|
function ensureDir2() {
|
|
@@ -10195,7 +10228,7 @@ function writeQueue(queue) {
|
|
|
10195
10228
|
ensureDir2();
|
|
10196
10229
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
10197
10230
|
writeFileSync13(tmp, JSON.stringify(queue, null, 2));
|
|
10198
|
-
|
|
10231
|
+
renameSync4(tmp, QUEUE_PATH);
|
|
10199
10232
|
}
|
|
10200
10233
|
function queueIntercom(targetSession, reason) {
|
|
10201
10234
|
const queue = readQueue();
|
|
@@ -13875,7 +13908,8 @@ __export(employee_templates_exports, {
|
|
|
13875
13908
|
});
|
|
13876
13909
|
function getSessionPrompt(storedPrompt) {
|
|
13877
13910
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
13878
|
-
const
|
|
13911
|
+
const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
13912
|
+
const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
13879
13913
|
const globalBlock = getGlobalProceduresBlock();
|
|
13880
13914
|
return `${globalBlock}${rolePrompt}
|
|
13881
13915
|
${BASE_OPERATING_PROCEDURES}`;
|
|
@@ -14483,7 +14517,7 @@ __export(exe_rename_exports, {
|
|
|
14483
14517
|
main: () => main2,
|
|
14484
14518
|
renameEmployee: () => renameEmployee
|
|
14485
14519
|
});
|
|
14486
|
-
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as
|
|
14520
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as renameSync5, unlinkSync as unlinkSync11, existsSync as existsSync25 } from "fs";
|
|
14487
14521
|
import { execSync as execSync11 } from "child_process";
|
|
14488
14522
|
import path31 from "path";
|
|
14489
14523
|
import { homedir as homedir4 } from "os";
|
|
@@ -14512,7 +14546,8 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
14512
14546
|
const originalName = employee.name;
|
|
14513
14547
|
const originalPrompt = employee.systemPrompt;
|
|
14514
14548
|
employee.name = newName;
|
|
14515
|
-
employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
|
|
14549
|
+
if (originalPrompt) employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
|
|
14550
|
+
else delete employee.systemPrompt;
|
|
14516
14551
|
await saveEmployees(employees, rosterPath);
|
|
14517
14552
|
rollbackStack.push({
|
|
14518
14553
|
description: "restore roster",
|
|
@@ -14530,14 +14565,14 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
14530
14565
|
/^(agent_id:\s*)\S+/m,
|
|
14531
14566
|
`$1${newName}`
|
|
14532
14567
|
);
|
|
14533
|
-
|
|
14568
|
+
renameSync5(oldIdentityPath, newIdentityPath);
|
|
14534
14569
|
writeFileSync17(newIdentityPath, updatedContent, "utf-8");
|
|
14535
14570
|
rollbackStack.push({
|
|
14536
14571
|
description: "restore identity file",
|
|
14537
14572
|
undo: () => {
|
|
14538
14573
|
if (existsSync25(newIdentityPath)) {
|
|
14539
14574
|
writeFileSync17(newIdentityPath, content, "utf-8");
|
|
14540
|
-
|
|
14575
|
+
renameSync5(newIdentityPath, oldIdentityPath);
|
|
14541
14576
|
}
|
|
14542
14577
|
}
|
|
14543
14578
|
});
|
|
@@ -14546,12 +14581,12 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
14546
14581
|
const newAgentPath = path31.join(agentsDir, `${newName}.md`);
|
|
14547
14582
|
if (existsSync25(oldAgentPath)) {
|
|
14548
14583
|
const agentContent = readFileSync21(oldAgentPath, "utf-8");
|
|
14549
|
-
|
|
14584
|
+
renameSync5(oldAgentPath, newAgentPath);
|
|
14550
14585
|
rollbackStack.push({
|
|
14551
14586
|
description: "restore agent file",
|
|
14552
14587
|
undo: () => {
|
|
14553
14588
|
if (existsSync25(newAgentPath)) {
|
|
14554
|
-
|
|
14589
|
+
renameSync5(newAgentPath, oldAgentPath);
|
|
14555
14590
|
writeFileSync17(oldAgentPath, agentContent, "utf-8");
|
|
14556
14591
|
}
|
|
14557
14592
|
}
|
|
@@ -14680,7 +14715,7 @@ var init_exe_rename = __esm({
|
|
|
14680
14715
|
});
|
|
14681
14716
|
|
|
14682
14717
|
// src/lib/model-downloader.ts
|
|
14683
|
-
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as
|
|
14718
|
+
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync6 } from "fs";
|
|
14684
14719
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
14685
14720
|
import { createHash as createHash4 } from "crypto";
|
|
14686
14721
|
import path32 from "path";
|
|
@@ -14738,7 +14773,7 @@ async function downloadModel(opts) {
|
|
|
14738
14773
|
`SHA256 mismatch: expected ${EXPECTED_SHA256}, got ${actualHash}`
|
|
14739
14774
|
);
|
|
14740
14775
|
}
|
|
14741
|
-
|
|
14776
|
+
renameSync6(tmpPath, destPath);
|
|
14742
14777
|
return destPath;
|
|
14743
14778
|
} catch (err) {
|
|
14744
14779
|
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
@@ -15542,8 +15577,8 @@ async function validateModel(log) {
|
|
|
15542
15577
|
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
15543
15578
|
const modelPath = path34.join(MODELS_DIR, LOCAL_FILENAME);
|
|
15544
15579
|
if (existsSync28(modelPath)) {
|
|
15545
|
-
const { statSync:
|
|
15546
|
-
const size =
|
|
15580
|
+
const { statSync: statSync5 } = await import("fs");
|
|
15581
|
+
const size = statSync5(modelPath).size;
|
|
15547
15582
|
if (size > 300 * 1e6) {
|
|
15548
15583
|
log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
|
|
15549
15584
|
return;
|
|
@@ -15964,15 +15999,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
15964
15999
|
cooName = (cooNameInput || DEFAULT_COORDINATOR_TEMPLATE_NAME2).toLowerCase();
|
|
15965
16000
|
let employees = await loadEmployees2(EMPLOYEES_PATH2).catch(() => []);
|
|
15966
16001
|
if (!employees.some((e) => e.name === cooName)) {
|
|
15967
|
-
const { DEFAULT_EXE: DEFAULT_EXE2, personalizePrompt: personalizePrompt2 } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
|
|
15968
16002
|
const cooEmployee = {
|
|
15969
16003
|
name: cooName,
|
|
15970
16004
|
role: "COO",
|
|
15971
|
-
systemPrompt: personalizePrompt2(
|
|
15972
|
-
DEFAULT_EXE2.systemPrompt,
|
|
15973
|
-
DEFAULT_COORDINATOR_TEMPLATE_NAME2,
|
|
15974
|
-
cooName
|
|
15975
|
-
),
|
|
15976
16005
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15977
16006
|
templateName: DEFAULT_COORDINATOR_TEMPLATE_NAME2,
|
|
15978
16007
|
templateVersion: 1
|
|
@@ -16066,12 +16095,12 @@ async function runSetupWizard(opts = {}) {
|
|
|
16066
16095
|
const ctoNameInput = await ask2(rl, `Name your CTO (default: ${ctoDefault}): `);
|
|
16067
16096
|
const ctoName = (ctoNameInput || ctoDefault).toLowerCase();
|
|
16068
16097
|
if (!employees.some((e) => e.name === ctoName)) {
|
|
16069
|
-
const { personalizePrompt: personalizeCto } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
|
|
16070
16098
|
const ctoEmployee = {
|
|
16071
16099
|
name: ctoName,
|
|
16072
16100
|
role: "CTO",
|
|
16073
|
-
|
|
16074
|
-
|
|
16101
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16102
|
+
templateName: ctoDefault,
|
|
16103
|
+
templateVersion: 1
|
|
16075
16104
|
};
|
|
16076
16105
|
employees = addEmployee2(employees, ctoEmployee);
|
|
16077
16106
|
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
@@ -16089,12 +16118,12 @@ async function runSetupWizard(opts = {}) {
|
|
|
16089
16118
|
const cmoNameInput = await ask2(rl, `Name your CMO (default: ${cmoDefault}): `);
|
|
16090
16119
|
const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
|
|
16091
16120
|
if (!employees.some((e) => e.name === cmoName)) {
|
|
16092
|
-
const { personalizePrompt: personalizeCmo } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
|
|
16093
16121
|
const cmoEmployee = {
|
|
16094
16122
|
name: cmoName,
|
|
16095
16123
|
role: "CMO",
|
|
16096
|
-
|
|
16097
|
-
|
|
16124
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16125
|
+
templateName: cmoDefault,
|
|
16126
|
+
templateVersion: 1
|
|
16098
16127
|
};
|
|
16099
16128
|
employees = addEmployee2(employees, cmoEmployee);
|
|
16100
16129
|
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
@@ -16217,7 +16246,21 @@ function resolveDataDir2() {
|
|
|
16217
16246
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
16218
16247
|
return path35.join(os17.homedir(), ".exe-os");
|
|
16219
16248
|
}
|
|
16220
|
-
|
|
16249
|
+
function externalBackupTargets(homeDir) {
|
|
16250
|
+
return [
|
|
16251
|
+
{ name: "claude.json", path: path35.join(homeDir, ".claude.json") },
|
|
16252
|
+
{ name: "claude-settings.json", path: path35.join(homeDir, ".claude", "settings.json") },
|
|
16253
|
+
{ name: "claude-CLAUDE.md", path: path35.join(homeDir, ".claude", "CLAUDE.md") },
|
|
16254
|
+
{ name: "tmux.conf", path: path35.join(homeDir, ".tmux.conf") },
|
|
16255
|
+
{ name: "zshrc", path: path35.join(homeDir, ".zshrc") },
|
|
16256
|
+
{ name: "bashrc", path: path35.join(homeDir, ".bashrc") },
|
|
16257
|
+
{ name: "ghostty-config", path: path35.join(homeDir, ".config", "ghostty", "config") },
|
|
16258
|
+
{ name: "codex-config.toml", path: path35.join(homeDir, ".codex", "config.toml") },
|
|
16259
|
+
{ name: "codex-hooks.json", path: path35.join(homeDir, ".codex", "hooks.json") },
|
|
16260
|
+
{ name: "opencode-config.json", path: path35.join(homeDir, ".config", "opencode", "opencode.json") }
|
|
16261
|
+
];
|
|
16262
|
+
}
|
|
16263
|
+
async function createUpdateBackup(currentVersion, dataDir, homeDir = os17.homedir()) {
|
|
16221
16264
|
const dir = dataDir ?? resolveDataDir2();
|
|
16222
16265
|
const backupDir = path35.join(dir, BACKUP_DIR_NAME);
|
|
16223
16266
|
if (existsSync29(backupDir)) {
|
|
@@ -16245,10 +16288,19 @@ async function createUpdateBackup(currentVersion, dataDir) {
|
|
|
16245
16288
|
backedUpFiles.push(entry.name);
|
|
16246
16289
|
}
|
|
16247
16290
|
}
|
|
16291
|
+
const externalFiles = [];
|
|
16292
|
+
const externalDir = path35.join(backupDir, "external");
|
|
16293
|
+
for (const target of externalBackupTargets(homeDir)) {
|
|
16294
|
+
if (!existsSync29(target.path)) continue;
|
|
16295
|
+
await mkdir7(externalDir, { recursive: true });
|
|
16296
|
+
await copyFile(target.path, path35.join(externalDir, target.name));
|
|
16297
|
+
externalFiles.push(target);
|
|
16298
|
+
}
|
|
16248
16299
|
const manifest = {
|
|
16249
16300
|
version: currentVersion,
|
|
16250
16301
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16251
|
-
files: backedUpFiles
|
|
16302
|
+
files: backedUpFiles,
|
|
16303
|
+
...externalFiles.length > 0 ? { externalFiles } : {}
|
|
16252
16304
|
};
|
|
16253
16305
|
await writeFile7(
|
|
16254
16306
|
path35.join(backupDir, "manifest.json"),
|
|
@@ -16279,6 +16331,12 @@ async function restoreFromBackup(dataDir) {
|
|
|
16279
16331
|
await copyFile(src, dest);
|
|
16280
16332
|
}
|
|
16281
16333
|
}
|
|
16334
|
+
for (const external of manifest.externalFiles ?? []) {
|
|
16335
|
+
const src = path35.join(backupDir, "external", external.name);
|
|
16336
|
+
if (!existsSync29(src)) continue;
|
|
16337
|
+
await mkdir7(path35.dirname(external.path), { recursive: true });
|
|
16338
|
+
await copyFile(src, external.path);
|
|
16339
|
+
}
|
|
16282
16340
|
return manifest;
|
|
16283
16341
|
}
|
|
16284
16342
|
async function deleteBackup(dataDir) {
|
|
@@ -16296,8 +16354,12 @@ var init_update_backup = __esm({
|
|
|
16296
16354
|
BACKUP_TARGETS = [
|
|
16297
16355
|
{ name: "config.json", type: "file" },
|
|
16298
16356
|
{ name: "exe-employees.json", type: "file" },
|
|
16357
|
+
{ name: "agent-config.json", type: "file" },
|
|
16299
16358
|
{ name: "master.key", type: "file" },
|
|
16300
|
-
{ name: "
|
|
16359
|
+
{ name: "tmux.conf", type: "file" },
|
|
16360
|
+
{ name: "identity", type: "dir" },
|
|
16361
|
+
{ name: "shards", type: "dir" },
|
|
16362
|
+
{ name: "mcp-configs", type: "dir" }
|
|
16301
16363
|
// All .db files (SQLCipher databases) — matched dynamically
|
|
16302
16364
|
];
|
|
16303
16365
|
}
|
|
@@ -16536,7 +16598,7 @@ var init_update = __esm({
|
|
|
16536
16598
|
|
|
16537
16599
|
// src/lib/stack-update.ts
|
|
16538
16600
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
16539
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync25, renameSync as
|
|
16601
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync25, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "fs";
|
|
16540
16602
|
import http from "http";
|
|
16541
16603
|
import https from "https";
|
|
16542
16604
|
import path37 from "path";
|
|
@@ -16644,7 +16706,7 @@ async function runStackUpdate(options) {
|
|
|
16644
16706
|
const patched = patchEnv(envRaw, updates);
|
|
16645
16707
|
const tmp = `${options.envFile}.tmp-${process.pid}`;
|
|
16646
16708
|
writeFileSync20(tmp, patched, { mode: 384 });
|
|
16647
|
-
|
|
16709
|
+
renameSync7(tmp, options.envFile);
|
|
16648
16710
|
const composeArgs = ["compose", "--file", options.composeFile, "--env-file", options.envFile];
|
|
16649
16711
|
try {
|
|
16650
16712
|
exec2("docker", [...composeArgs, "pull"]);
|
|
@@ -32111,7 +32173,7 @@ async function runActivate(key) {
|
|
|
32111
32173
|
}
|
|
32112
32174
|
const { saveLicense: saveLicense2, mirrorLicenseKey: mirrorLicenseKey2, validateLicense: validateLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
32113
32175
|
const { loadEmployees: loadEmployees2, saveEmployees: saveEmployees2, addEmployee: addEmployee2, registerBinSymlinks: registerBinSymlinks2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
32114
|
-
const { getTemplateByRole: getTemplateByRole2
|
|
32176
|
+
const { getTemplateByRole: getTemplateByRole2 } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
|
|
32115
32177
|
const { getTemplate: getIdentityTemplate } = await Promise.resolve().then(() => (init_identity_templates(), identity_templates_exports));
|
|
32116
32178
|
const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
32117
32179
|
const { createInterface: createInterface5 } = await import("readline");
|
|
@@ -32143,7 +32205,8 @@ async function runActivate(key) {
|
|
|
32143
32205
|
if (create3.toLowerCase() === "n") return;
|
|
32144
32206
|
const nameInput = await ask3(`Name your ${role} [${defaultName}]: `);
|
|
32145
32207
|
const name = nameInput || defaultName;
|
|
32146
|
-
const
|
|
32208
|
+
const { systemPrompt: _templatePrompt, ...templateMeta } = template;
|
|
32209
|
+
const emp = { ...templateMeta, name, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
32147
32210
|
employees = addEmployee2(employees, emp);
|
|
32148
32211
|
await saveEmployees2(employees);
|
|
32149
32212
|
registerBinSymlinks2(name);
|
package/dist/bin/exe-agent.js
CHANGED
|
@@ -107,7 +107,7 @@ var init_config = __esm({
|
|
|
107
107
|
|
|
108
108
|
// src/bin/exe-agent.ts
|
|
109
109
|
import { createInterface } from "readline";
|
|
110
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
110
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
111
111
|
import path10 from "path";
|
|
112
112
|
import os5 from "os";
|
|
113
113
|
|
|
@@ -1613,7 +1613,8 @@ When you need to assign work to another employee (e.g., CTO assigns to an engine
|
|
|
1613
1613
|
var PROCEDURES_MARKER = "EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES";
|
|
1614
1614
|
function getSessionPrompt(storedPrompt) {
|
|
1615
1615
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
1616
|
-
const
|
|
1616
|
+
const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
1617
|
+
const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
1617
1618
|
const globalBlock = getGlobalProceduresBlock();
|
|
1618
1619
|
return `${globalBlock}${rolePrompt}
|
|
1619
1620
|
${BASE_OPERATING_PROCEDURES}`;
|
|
@@ -2259,9 +2260,16 @@ function parseArgs(argv) {
|
|
|
2259
2260
|
}
|
|
2260
2261
|
function loadEmployee(name) {
|
|
2261
2262
|
try {
|
|
2263
|
+
const identityPath = path10.join(os5.homedir(), ".exe-os", "identity", `${name}.md`);
|
|
2262
2264
|
const rosterPath = path10.join(os5.homedir(), ".exe-os", "exe-employees.json");
|
|
2263
2265
|
const roster = JSON.parse(readFileSync3(rosterPath, "utf8"));
|
|
2264
|
-
|
|
2266
|
+
const employee = roster.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
2267
|
+
if (!employee) return null;
|
|
2268
|
+
if (existsSync4(identityPath)) {
|
|
2269
|
+
const identity = readFileSync3(identityPath, "utf8").trim();
|
|
2270
|
+
if (identity.length > 0) return { role: employee.role, systemPrompt: identity };
|
|
2271
|
+
}
|
|
2272
|
+
return employee.systemPrompt ? { role: employee.role, systemPrompt: employee.systemPrompt } : null;
|
|
2265
2273
|
} catch {
|
|
2266
2274
|
return null;
|
|
2267
2275
|
}
|
package/dist/bin/exe-assign.js
CHANGED
|
@@ -2751,7 +2751,7 @@ __export(shard_manager_exports, {
|
|
|
2751
2751
|
shardExists: () => shardExists
|
|
2752
2752
|
});
|
|
2753
2753
|
import path7 from "path";
|
|
2754
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2754
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
2755
2755
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2756
2756
|
function initShardManager(encryptionKey) {
|
|
2757
2757
|
_encryptionKey = encryptionKey;
|
|
@@ -2773,7 +2773,7 @@ function getShardClient(projectName) {
|
|
|
2773
2773
|
if (!_encryptionKey) {
|
|
2774
2774
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2775
2775
|
}
|
|
2776
|
-
const safeName = projectName
|
|
2776
|
+
const safeName = safeShardName(projectName);
|
|
2777
2777
|
if (!safeName || safeName === "unknown") {
|
|
2778
2778
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2779
2779
|
}
|
|
@@ -2795,9 +2795,12 @@ function getShardClient(projectName) {
|
|
|
2795
2795
|
return client;
|
|
2796
2796
|
}
|
|
2797
2797
|
function shardExists(projectName) {
|
|
2798
|
-
const safeName = projectName
|
|
2798
|
+
const safeName = safeShardName(projectName);
|
|
2799
2799
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2800
2800
|
}
|
|
2801
|
+
function safeShardName(projectName) {
|
|
2802
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2803
|
+
}
|
|
2801
2804
|
function listShards() {
|
|
2802
2805
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
2803
2806
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -2891,7 +2894,8 @@ async function ensureShardSchema(client) {
|
|
|
2891
2894
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
2892
2895
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
2893
2896
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
2894
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
2897
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
2898
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
2895
2899
|
]) {
|
|
2896
2900
|
try {
|
|
2897
2901
|
await client.execute(col);
|
|
@@ -2987,9 +2991,32 @@ async function ensureShardSchema(client) {
|
|
|
2987
2991
|
}
|
|
2988
2992
|
}
|
|
2989
2993
|
async function getReadyShardClient(projectName) {
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
2994
|
+
const safeName = safeShardName(projectName);
|
|
2995
|
+
let client = getShardClient(projectName);
|
|
2996
|
+
try {
|
|
2997
|
+
await ensureShardSchema(client);
|
|
2998
|
+
return client;
|
|
2999
|
+
} catch (err) {
|
|
3000
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3001
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3002
|
+
client.close();
|
|
3003
|
+
_shards.delete(safeName);
|
|
3004
|
+
_shardLastAccess.delete(safeName);
|
|
3005
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3006
|
+
if (existsSync7(dbPath)) {
|
|
3007
|
+
const stat = statSync2(dbPath);
|
|
3008
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3009
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3010
|
+
renameSync3(dbPath, archivedPath);
|
|
3011
|
+
process.stderr.write(
|
|
3012
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3013
|
+
`
|
|
3014
|
+
);
|
|
3015
|
+
}
|
|
3016
|
+
client = getShardClient(projectName);
|
|
3017
|
+
await ensureShardSchema(client);
|
|
3018
|
+
return client;
|
|
3019
|
+
}
|
|
2993
3020
|
}
|
|
2994
3021
|
function evictLRU() {
|
|
2995
3022
|
let oldest = null;
|