@askexenow/exe-os 0.9.37 → 0.9.39
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 +55 -0
- package/dist/bin/backfill-conversations.js +36 -9
- package/dist/bin/backfill-responses.js +36 -9
- package/dist/bin/backfill-vectors.js +36 -9
- package/dist/bin/cleanup-stale-review-tasks.js +37 -10
- package/dist/bin/cli.js +624 -204
- package/dist/bin/exe-agent.js +13 -5
- package/dist/bin/exe-assign.js +36 -9
- package/dist/bin/exe-boot.js +50 -20
- package/dist/bin/exe-call.js +134 -342
- package/dist/bin/exe-dispatch.js +36 -9
- package/dist/bin/exe-doctor.js +39 -12
- package/dist/bin/exe-export-behaviors.js +38 -11
- package/dist/bin/exe-forget.js +36 -9
- package/dist/bin/exe-gateway.js +64 -15
- package/dist/bin/exe-heartbeat.js +37 -10
- package/dist/bin/exe-kill.js +36 -9
- package/dist/bin/exe-launch-agent.js +287 -1081
- package/dist/bin/exe-new-employee.js +100 -14
- package/dist/bin/exe-pending-messages.js +36 -9
- package/dist/bin/exe-pending-notifications.js +36 -9
- package/dist/bin/exe-pending-reviews.js +36 -9
- package/dist/bin/exe-rename.js +1780 -204
- package/dist/bin/exe-review.js +36 -9
- package/dist/bin/exe-search.js +38 -11
- package/dist/bin/exe-session-cleanup.js +38 -11
- package/dist/bin/exe-start-codex.js +38 -11
- package/dist/bin/exe-start-opencode.js +38 -11
- package/dist/bin/exe-status.js +37 -10
- package/dist/bin/exe-team.js +36 -9
- package/dist/bin/git-sweep.js +36 -9
- package/dist/bin/graph-backfill.js +36 -9
- package/dist/bin/graph-export.js +36 -9
- package/dist/bin/install.js +70 -3
- package/dist/bin/intercom-check.js +38 -11
- package/dist/bin/scan-tasks.js +36 -9
- package/dist/bin/setup.js +20 -19
- package/dist/bin/shard-migrate.js +36 -9
- package/dist/bin/stack-update.js +308 -0
- package/dist/gateway/index.js +62 -13
- package/dist/hooks/bug-report-worker.js +40 -12
- package/dist/hooks/codex-stop-task-finalizer.js +38 -11
- package/dist/hooks/commit-complete.js +36 -9
- package/dist/hooks/error-recall.js +38 -11
- package/dist/hooks/ingest.js +38 -10
- package/dist/hooks/instructions-loaded.js +44 -12
- package/dist/hooks/notification.js +36 -9
- package/dist/hooks/post-compact.js +36 -9
- package/dist/hooks/post-tool-combined.js +39 -12
- package/dist/hooks/pre-compact.js +37 -10
- package/dist/hooks/pre-tool-use.js +38 -10
- package/dist/hooks/prompt-submit.js +43 -15
- package/dist/hooks/session-end.js +37 -10
- package/dist/hooks/session-start.js +49 -16
- package/dist/hooks/stop.js +37 -10
- package/dist/hooks/subagent-stop.js +36 -9
- package/dist/hooks/summary-worker.js +45 -18
- package/dist/index.js +60 -11
- package/dist/lib/consolidation.js +2 -1
- package/dist/lib/employee-templates.js +4 -3
- package/dist/lib/employees.js +2 -1
- package/dist/lib/exe-daemon.js +11229 -10537
- package/dist/lib/hybrid-search.js +38 -11
- package/dist/lib/identity.js +8 -3
- package/dist/lib/schedules.js +36 -9
- package/dist/lib/store.js +36 -9
- package/dist/mcp/server.js +6873 -6249
- package/dist/mcp/tools/create-task.js +10 -4
- package/dist/runtime/index.js +36 -9
- package/dist/tui/App.js +42 -13
- package/package.json +4 -1
- package/stack.release.json +31 -0
- package/stack.release.schema.json +31 -0
|
@@ -302,7 +302,8 @@ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
function addEmployee(employees, employee) {
|
|
305
|
-
const
|
|
305
|
+
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
306
|
+
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
306
307
|
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
307
308
|
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
308
309
|
}
|
|
@@ -1034,6 +1035,9 @@ function ensureDir() {
|
|
|
1034
1035
|
function identityPath(agentId) {
|
|
1035
1036
|
return path8.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
1036
1037
|
}
|
|
1038
|
+
function sanitizeIdentityBody(body) {
|
|
1039
|
+
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
1040
|
+
}
|
|
1037
1041
|
function parseFrontmatter(raw) {
|
|
1038
1042
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
1039
1043
|
if (!match) {
|
|
@@ -1046,11 +1050,11 @@ function parseFrontmatter(raw) {
|
|
|
1046
1050
|
created_by: "system",
|
|
1047
1051
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1048
1052
|
},
|
|
1049
|
-
body: raw
|
|
1053
|
+
body: sanitizeIdentityBody(raw)
|
|
1050
1054
|
};
|
|
1051
1055
|
}
|
|
1052
1056
|
const yamlStr = match[1];
|
|
1053
|
-
const body = match[2]
|
|
1057
|
+
const body = sanitizeIdentityBody(match[2]);
|
|
1054
1058
|
const fm = {};
|
|
1055
1059
|
for (const line of yamlStr.split("\n")) {
|
|
1056
1060
|
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
@@ -1115,7 +1119,9 @@ function listIdentities() {
|
|
|
1115
1119
|
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
1116
1120
|
results.push({
|
|
1117
1121
|
agentId,
|
|
1118
|
-
title
|
|
1122
|
+
// User-facing/team-facing title only. `frontmatter.role` is internal
|
|
1123
|
+
// routing metadata and must not leak as an external title.
|
|
1124
|
+
title: identity.frontmatter.title,
|
|
1119
1125
|
summary
|
|
1120
1126
|
});
|
|
1121
1127
|
}
|
|
@@ -1256,6 +1262,7 @@ var installer_exports = {};
|
|
|
1256
1262
|
__export(installer_exports, {
|
|
1257
1263
|
cleanOldShellFunctions: () => cleanOldShellFunctions,
|
|
1258
1264
|
copySlashCommands: () => copySlashCommands,
|
|
1265
|
+
detectMcpNameCollisions: () => detectMcpNameCollisions,
|
|
1259
1266
|
installStatusLine: () => installStatusLine,
|
|
1260
1267
|
mergeHooks: () => mergeHooks,
|
|
1261
1268
|
registerMcpServer: () => registerMcpServer,
|
|
@@ -1341,6 +1348,60 @@ name: ${skillName}
|
|
|
1341
1348
|
await writeFile3(destPath, content);
|
|
1342
1349
|
return true;
|
|
1343
1350
|
}
|
|
1351
|
+
function readJsonFile(filePath) {
|
|
1352
|
+
try {
|
|
1353
|
+
return JSON.parse(readFileSync9(filePath, "utf-8"));
|
|
1354
|
+
} catch {
|
|
1355
|
+
return null;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
function findAncestorMcpJsons(startDir, homeDir) {
|
|
1359
|
+
const files = [];
|
|
1360
|
+
let dir = path11.resolve(startDir);
|
|
1361
|
+
const root = path11.parse(dir).root;
|
|
1362
|
+
const stop = path11.resolve(homeDir);
|
|
1363
|
+
while (dir !== root) {
|
|
1364
|
+
const candidate = path11.join(dir, ".mcp.json");
|
|
1365
|
+
if (existsSync11(candidate)) files.push(candidate);
|
|
1366
|
+
if (dir === stop) break;
|
|
1367
|
+
dir = path11.dirname(dir);
|
|
1368
|
+
}
|
|
1369
|
+
return files;
|
|
1370
|
+
}
|
|
1371
|
+
function pathApplies(projectPath, cwd) {
|
|
1372
|
+
const project = path11.resolve(projectPath);
|
|
1373
|
+
const current = path11.resolve(cwd);
|
|
1374
|
+
return current === project || current.startsWith(project + path11.sep);
|
|
1375
|
+
}
|
|
1376
|
+
function detectMcpNameCollisions(homeDir = os7.homedir(), cwd = process.cwd()) {
|
|
1377
|
+
const claudeJsonPath = path11.join(homeDir, ".claude.json");
|
|
1378
|
+
if (!existsSync11(claudeJsonPath)) return [];
|
|
1379
|
+
const claudeJson = readJsonFile(claudeJsonPath);
|
|
1380
|
+
if (!claudeJson?.projects) return [];
|
|
1381
|
+
const collisions = [];
|
|
1382
|
+
const mcpJsons = findAncestorMcpJsons(cwd, homeDir);
|
|
1383
|
+
if (mcpJsons.length === 0) return [];
|
|
1384
|
+
for (const [projectPath, projectConfig] of Object.entries(claudeJson.projects)) {
|
|
1385
|
+
if (!pathApplies(projectPath, cwd)) continue;
|
|
1386
|
+
const projectServerNames = new Set(Object.keys(projectConfig.mcpServers ?? {}));
|
|
1387
|
+
if (projectServerNames.size === 0) continue;
|
|
1388
|
+
const enabled = new Set(projectConfig.enabledMcpjsonServers ?? []);
|
|
1389
|
+
for (const mcpJsonPath of mcpJsons) {
|
|
1390
|
+
const mcpJson = readJsonFile(mcpJsonPath);
|
|
1391
|
+
const mcpServerNames = Object.keys(mcpJson?.mcpServers ?? {});
|
|
1392
|
+
for (const serverName of mcpServerNames) {
|
|
1393
|
+
if (!projectServerNames.has(serverName)) continue;
|
|
1394
|
+
collisions.push({
|
|
1395
|
+
mcpJsonPath,
|
|
1396
|
+
projectPath,
|
|
1397
|
+
serverName,
|
|
1398
|
+
disabledInMcpJson: !enabled.has(serverName)
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
return collisions;
|
|
1404
|
+
}
|
|
1344
1405
|
async function registerMcpServer(packageRoot, homeDir = os7.homedir()) {
|
|
1345
1406
|
const claudeJsonPath = path11.join(homeDir, ".claude.json");
|
|
1346
1407
|
let claudeJson = {};
|
|
@@ -1369,12 +1430,26 @@ async function registerMcpServer(packageRoot, homeDir = os7.homedir()) {
|
|
|
1369
1430
|
if (osMatches) {
|
|
1370
1431
|
await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
|
|
1371
1432
|
await migratePermissionsToExeOs(path11.join(homeDir, ".claude", "settings.json"));
|
|
1433
|
+
const collisions2 = detectMcpNameCollisions(homeDir, packageRoot).filter((c) => c.serverName === MCP_PRIMARY_KEY || c.serverName === MCP_LEGACY_KEY);
|
|
1434
|
+
for (const c of collisions2) {
|
|
1435
|
+
process.stderr.write(
|
|
1436
|
+
`exe-os: WARNING Claude Code MCP name collision: ${c.serverName} exists in ${c.mcpJsonPath} and ~/.claude.json project ${c.projectPath}. Remove or rename the .mcp.json entry if tools do not surface.
|
|
1437
|
+
`
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1372
1440
|
return false;
|
|
1373
1441
|
}
|
|
1374
1442
|
claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
|
|
1375
1443
|
await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
1376
1444
|
await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
|
|
1377
1445
|
await migratePermissionsToExeOs(path11.join(homeDir, ".claude", "settings.json"));
|
|
1446
|
+
const collisions = detectMcpNameCollisions(homeDir, packageRoot).filter((c) => c.serverName === MCP_PRIMARY_KEY || c.serverName === MCP_LEGACY_KEY);
|
|
1447
|
+
for (const c of collisions) {
|
|
1448
|
+
process.stderr.write(
|
|
1449
|
+
`exe-os: WARNING Claude Code MCP name collision: ${c.serverName} exists in ${c.mcpJsonPath} and ~/.claude.json project ${c.projectPath}. Remove or rename the .mcp.json entry if tools do not surface.
|
|
1450
|
+
`
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1378
1453
|
return true;
|
|
1379
1454
|
}
|
|
1380
1455
|
async function cleanSettingsJsonMcp(settingsPath) {
|
|
@@ -1676,8 +1751,6 @@ async function mergeHooks(packageRoot, homeDir = os7.homedir()) {
|
|
|
1676
1751
|
"purge_document",
|
|
1677
1752
|
"rerank_documents",
|
|
1678
1753
|
"set_document_importance",
|
|
1679
|
-
"create_wiki_page",
|
|
1680
|
-
"update_wiki_page",
|
|
1681
1754
|
"get_wiki_page",
|
|
1682
1755
|
"list_wiki_pages",
|
|
1683
1756
|
// System
|
|
@@ -2382,7 +2455,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
2382
2455
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
2383
2456
|
domain: "tool-use",
|
|
2384
2457
|
priority: "p1",
|
|
2385
|
-
content: "
|
|
2458
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
2386
2459
|
},
|
|
2387
2460
|
{
|
|
2388
2461
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -2400,7 +2473,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
2400
2473
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
2401
2474
|
domain: "tool-use",
|
|
2402
2475
|
priority: "p1",
|
|
2403
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
2476
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
2404
2477
|
}
|
|
2405
2478
|
];
|
|
2406
2479
|
var PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -3112,11 +3185,12 @@ async function main() {
|
|
|
3112
3185
|
);
|
|
3113
3186
|
process.exit(1);
|
|
3114
3187
|
}
|
|
3188
|
+
const rolePrompt = template ? personalizePrompt(template.systemPrompt, template.name, name) : buildCustomEmployeePrompt(name, "specialist");
|
|
3115
3189
|
if (template) {
|
|
3190
|
+
const { systemPrompt: _templatePrompt, ...templateMeta } = template;
|
|
3116
3191
|
newEmployee = {
|
|
3117
|
-
...
|
|
3192
|
+
...templateMeta,
|
|
3118
3193
|
name,
|
|
3119
|
-
systemPrompt: personalizePrompt(template.systemPrompt, template.name, name),
|
|
3120
3194
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3121
3195
|
templateName: effectiveTemplate,
|
|
3122
3196
|
templateVersion: TEMPLATE_VERSION
|
|
@@ -3125,7 +3199,6 @@ async function main() {
|
|
|
3125
3199
|
newEmployee = {
|
|
3126
3200
|
name,
|
|
3127
3201
|
role: "specialist",
|
|
3128
|
-
systemPrompt: buildCustomEmployeePrompt(name, "specialist"),
|
|
3129
3202
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3130
3203
|
templateName: "custom",
|
|
3131
3204
|
templateVersion: TEMPLATE_VERSION
|
|
@@ -3160,13 +3233,26 @@ async function main() {
|
|
|
3160
3233
|
};
|
|
3161
3234
|
const templateKey = roleMap[effectiveTemplate] ?? null;
|
|
3162
3235
|
const identityTemplate = templateKey ? getIdentityTemplate(templateKey) : null;
|
|
3236
|
+
const idPath = identityPath2(name);
|
|
3237
|
+
const dir = path12.dirname(idPath);
|
|
3238
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
3163
3239
|
if (identityTemplate) {
|
|
3164
|
-
const idPath = identityPath2(name);
|
|
3165
|
-
const dir = path12.dirname(idPath);
|
|
3166
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
3167
3240
|
const content = identityTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`);
|
|
3168
3241
|
fs.writeFileSync(idPath, content, "utf-8");
|
|
3169
3242
|
console.log(`Identity doc written: ~/.exe-os/identity/${name}.md`);
|
|
3243
|
+
} else if (!fs.existsSync(idPath)) {
|
|
3244
|
+
const content = `---
|
|
3245
|
+
role: specialist
|
|
3246
|
+
title: Specialist
|
|
3247
|
+
agent_id: ${name}
|
|
3248
|
+
org_level: specialist
|
|
3249
|
+
created_by: exe-new-employee
|
|
3250
|
+
updated_at: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
3251
|
+
---
|
|
3252
|
+
|
|
3253
|
+
${rolePrompt}`;
|
|
3254
|
+
fs.writeFileSync(idPath, content, "utf-8");
|
|
3255
|
+
console.log(`Identity doc written: ~/.exe-os/identity/${name}.md`);
|
|
3170
3256
|
}
|
|
3171
3257
|
} catch {
|
|
3172
3258
|
}
|
|
@@ -3669,7 +3669,7 @@ __export(shard_manager_exports, {
|
|
|
3669
3669
|
shardExists: () => shardExists
|
|
3670
3670
|
});
|
|
3671
3671
|
import path13 from "path";
|
|
3672
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync2 } from "fs";
|
|
3672
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readdirSync as readdirSync2, renameSync as renameSync4, statSync as statSync2 } from "fs";
|
|
3673
3673
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3674
3674
|
function initShardManager(encryptionKey) {
|
|
3675
3675
|
_encryptionKey = encryptionKey;
|
|
@@ -3691,7 +3691,7 @@ function getShardClient(projectName) {
|
|
|
3691
3691
|
if (!_encryptionKey) {
|
|
3692
3692
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3693
3693
|
}
|
|
3694
|
-
const safeName = projectName
|
|
3694
|
+
const safeName = safeShardName(projectName);
|
|
3695
3695
|
if (!safeName || safeName === "unknown") {
|
|
3696
3696
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3697
3697
|
}
|
|
@@ -3713,9 +3713,12 @@ function getShardClient(projectName) {
|
|
|
3713
3713
|
return client;
|
|
3714
3714
|
}
|
|
3715
3715
|
function shardExists(projectName) {
|
|
3716
|
-
const safeName = projectName
|
|
3716
|
+
const safeName = safeShardName(projectName);
|
|
3717
3717
|
return existsSync12(path13.join(SHARDS_DIR, `${safeName}.db`));
|
|
3718
3718
|
}
|
|
3719
|
+
function safeShardName(projectName) {
|
|
3720
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3721
|
+
}
|
|
3719
3722
|
function listShards() {
|
|
3720
3723
|
if (!existsSync12(SHARDS_DIR)) return [];
|
|
3721
3724
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3809,7 +3812,8 @@ async function ensureShardSchema(client) {
|
|
|
3809
3812
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3810
3813
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3811
3814
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3812
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3815
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3816
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3813
3817
|
]) {
|
|
3814
3818
|
try {
|
|
3815
3819
|
await client.execute(col);
|
|
@@ -3905,9 +3909,32 @@ async function ensureShardSchema(client) {
|
|
|
3905
3909
|
}
|
|
3906
3910
|
}
|
|
3907
3911
|
async function getReadyShardClient(projectName) {
|
|
3908
|
-
const
|
|
3909
|
-
|
|
3910
|
-
|
|
3912
|
+
const safeName = safeShardName(projectName);
|
|
3913
|
+
let client = getShardClient(projectName);
|
|
3914
|
+
try {
|
|
3915
|
+
await ensureShardSchema(client);
|
|
3916
|
+
return client;
|
|
3917
|
+
} catch (err) {
|
|
3918
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3919
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3920
|
+
client.close();
|
|
3921
|
+
_shards.delete(safeName);
|
|
3922
|
+
_shardLastAccess.delete(safeName);
|
|
3923
|
+
const dbPath = path13.join(SHARDS_DIR, `${safeName}.db`);
|
|
3924
|
+
if (existsSync12(dbPath)) {
|
|
3925
|
+
const stat = statSync2(dbPath);
|
|
3926
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3927
|
+
const archivedPath = path13.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3928
|
+
renameSync4(dbPath, archivedPath);
|
|
3929
|
+
process.stderr.write(
|
|
3930
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3931
|
+
`
|
|
3932
|
+
);
|
|
3933
|
+
}
|
|
3934
|
+
client = getShardClient(projectName);
|
|
3935
|
+
await ensureShardSchema(client);
|
|
3936
|
+
return client;
|
|
3937
|
+
}
|
|
3911
3938
|
}
|
|
3912
3939
|
function evictLRU() {
|
|
3913
3940
|
let oldest = null;
|
|
@@ -4128,7 +4155,7 @@ var init_platform_procedures = __esm({
|
|
|
4128
4155
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
4129
4156
|
domain: "tool-use",
|
|
4130
4157
|
priority: "p1",
|
|
4131
|
-
content: "
|
|
4158
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
4132
4159
|
},
|
|
4133
4160
|
{
|
|
4134
4161
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -4146,7 +4173,7 @@ var init_platform_procedures = __esm({
|
|
|
4146
4173
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
4147
4174
|
domain: "tool-use",
|
|
4148
4175
|
priority: "p1",
|
|
4149
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
4176
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
4150
4177
|
}
|
|
4151
4178
|
];
|
|
4152
4179
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -3735,7 +3735,7 @@ __export(shard_manager_exports, {
|
|
|
3735
3735
|
shardExists: () => shardExists
|
|
3736
3736
|
});
|
|
3737
3737
|
import path14 from "path";
|
|
3738
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
|
|
3738
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync3, renameSync as renameSync4, statSync as statSync2 } from "fs";
|
|
3739
3739
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3740
3740
|
function initShardManager(encryptionKey) {
|
|
3741
3741
|
_encryptionKey = encryptionKey;
|
|
@@ -3757,7 +3757,7 @@ function getShardClient(projectName) {
|
|
|
3757
3757
|
if (!_encryptionKey) {
|
|
3758
3758
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3759
3759
|
}
|
|
3760
|
-
const safeName = projectName
|
|
3760
|
+
const safeName = safeShardName(projectName);
|
|
3761
3761
|
if (!safeName || safeName === "unknown") {
|
|
3762
3762
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3763
3763
|
}
|
|
@@ -3779,9 +3779,12 @@ function getShardClient(projectName) {
|
|
|
3779
3779
|
return client;
|
|
3780
3780
|
}
|
|
3781
3781
|
function shardExists(projectName) {
|
|
3782
|
-
const safeName = projectName
|
|
3782
|
+
const safeName = safeShardName(projectName);
|
|
3783
3783
|
return existsSync13(path14.join(SHARDS_DIR, `${safeName}.db`));
|
|
3784
3784
|
}
|
|
3785
|
+
function safeShardName(projectName) {
|
|
3786
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3787
|
+
}
|
|
3785
3788
|
function listShards() {
|
|
3786
3789
|
if (!existsSync13(SHARDS_DIR)) return [];
|
|
3787
3790
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3875,7 +3878,8 @@ async function ensureShardSchema(client) {
|
|
|
3875
3878
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3876
3879
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3877
3880
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3878
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3881
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3882
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3879
3883
|
]) {
|
|
3880
3884
|
try {
|
|
3881
3885
|
await client.execute(col);
|
|
@@ -3971,9 +3975,32 @@ async function ensureShardSchema(client) {
|
|
|
3971
3975
|
}
|
|
3972
3976
|
}
|
|
3973
3977
|
async function getReadyShardClient(projectName) {
|
|
3974
|
-
const
|
|
3975
|
-
|
|
3976
|
-
|
|
3978
|
+
const safeName = safeShardName(projectName);
|
|
3979
|
+
let client = getShardClient(projectName);
|
|
3980
|
+
try {
|
|
3981
|
+
await ensureShardSchema(client);
|
|
3982
|
+
return client;
|
|
3983
|
+
} catch (err) {
|
|
3984
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3985
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3986
|
+
client.close();
|
|
3987
|
+
_shards.delete(safeName);
|
|
3988
|
+
_shardLastAccess.delete(safeName);
|
|
3989
|
+
const dbPath = path14.join(SHARDS_DIR, `${safeName}.db`);
|
|
3990
|
+
if (existsSync13(dbPath)) {
|
|
3991
|
+
const stat = statSync2(dbPath);
|
|
3992
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3993
|
+
const archivedPath = path14.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3994
|
+
renameSync4(dbPath, archivedPath);
|
|
3995
|
+
process.stderr.write(
|
|
3996
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3997
|
+
`
|
|
3998
|
+
);
|
|
3999
|
+
}
|
|
4000
|
+
client = getShardClient(projectName);
|
|
4001
|
+
await ensureShardSchema(client);
|
|
4002
|
+
return client;
|
|
4003
|
+
}
|
|
3977
4004
|
}
|
|
3978
4005
|
function evictLRU() {
|
|
3979
4006
|
let oldest = null;
|
|
@@ -4194,7 +4221,7 @@ var init_platform_procedures = __esm({
|
|
|
4194
4221
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
4195
4222
|
domain: "tool-use",
|
|
4196
4223
|
priority: "p1",
|
|
4197
|
-
content: "
|
|
4224
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
4198
4225
|
},
|
|
4199
4226
|
{
|
|
4200
4227
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -4212,7 +4239,7 @@ var init_platform_procedures = __esm({
|
|
|
4212
4239
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
4213
4240
|
domain: "tool-use",
|
|
4214
4241
|
priority: "p1",
|
|
4215
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
4242
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
4216
4243
|
}
|
|
4217
4244
|
];
|
|
4218
4245
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -3774,7 +3774,7 @@ __export(shard_manager_exports, {
|
|
|
3774
3774
|
shardExists: () => shardExists
|
|
3775
3775
|
});
|
|
3776
3776
|
import path15 from "path";
|
|
3777
|
-
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
|
|
3777
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync2 } from "fs";
|
|
3778
3778
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3779
3779
|
function initShardManager(encryptionKey) {
|
|
3780
3780
|
_encryptionKey = encryptionKey;
|
|
@@ -3796,7 +3796,7 @@ function getShardClient(projectName) {
|
|
|
3796
3796
|
if (!_encryptionKey) {
|
|
3797
3797
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3798
3798
|
}
|
|
3799
|
-
const safeName = projectName
|
|
3799
|
+
const safeName = safeShardName(projectName);
|
|
3800
3800
|
if (!safeName || safeName === "unknown") {
|
|
3801
3801
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3802
3802
|
}
|
|
@@ -3818,9 +3818,12 @@ function getShardClient(projectName) {
|
|
|
3818
3818
|
return client;
|
|
3819
3819
|
}
|
|
3820
3820
|
function shardExists(projectName) {
|
|
3821
|
-
const safeName = projectName
|
|
3821
|
+
const safeName = safeShardName(projectName);
|
|
3822
3822
|
return existsSync14(path15.join(SHARDS_DIR, `${safeName}.db`));
|
|
3823
3823
|
}
|
|
3824
|
+
function safeShardName(projectName) {
|
|
3825
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3826
|
+
}
|
|
3824
3827
|
function listShards() {
|
|
3825
3828
|
if (!existsSync14(SHARDS_DIR)) return [];
|
|
3826
3829
|
return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3914,7 +3917,8 @@ async function ensureShardSchema(client) {
|
|
|
3914
3917
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3915
3918
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3916
3919
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3917
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3920
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3921
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3918
3922
|
]) {
|
|
3919
3923
|
try {
|
|
3920
3924
|
await client.execute(col);
|
|
@@ -4010,9 +4014,32 @@ async function ensureShardSchema(client) {
|
|
|
4010
4014
|
}
|
|
4011
4015
|
}
|
|
4012
4016
|
async function getReadyShardClient(projectName) {
|
|
4013
|
-
const
|
|
4014
|
-
|
|
4015
|
-
|
|
4017
|
+
const safeName = safeShardName(projectName);
|
|
4018
|
+
let client = getShardClient(projectName);
|
|
4019
|
+
try {
|
|
4020
|
+
await ensureShardSchema(client);
|
|
4021
|
+
return client;
|
|
4022
|
+
} catch (err) {
|
|
4023
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4024
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
4025
|
+
client.close();
|
|
4026
|
+
_shards.delete(safeName);
|
|
4027
|
+
_shardLastAccess.delete(safeName);
|
|
4028
|
+
const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
|
|
4029
|
+
if (existsSync14(dbPath)) {
|
|
4030
|
+
const stat = statSync2(dbPath);
|
|
4031
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4032
|
+
const archivedPath = path15.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4033
|
+
renameSync4(dbPath, archivedPath);
|
|
4034
|
+
process.stderr.write(
|
|
4035
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
4036
|
+
`
|
|
4037
|
+
);
|
|
4038
|
+
}
|
|
4039
|
+
client = getShardClient(projectName);
|
|
4040
|
+
await ensureShardSchema(client);
|
|
4041
|
+
return client;
|
|
4042
|
+
}
|
|
4016
4043
|
}
|
|
4017
4044
|
function evictLRU() {
|
|
4018
4045
|
let oldest = null;
|
|
@@ -4233,7 +4260,7 @@ var init_platform_procedures = __esm({
|
|
|
4233
4260
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
4234
4261
|
domain: "tool-use",
|
|
4235
4262
|
priority: "p1",
|
|
4236
|
-
content: "
|
|
4263
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
4237
4264
|
},
|
|
4238
4265
|
{
|
|
4239
4266
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -4251,7 +4278,7 @@ var init_platform_procedures = __esm({
|
|
|
4251
4278
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
4252
4279
|
domain: "tool-use",
|
|
4253
4280
|
priority: "p1",
|
|
4254
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
4281
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
4255
4282
|
}
|
|
4256
4283
|
];
|
|
4257
4284
|
PLATFORM_PROCEDURE_TITLES = new Set(
|