@askexenow/exe-os 0.9.38 → 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/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 +72 -42
- 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/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 +1 -1
package/dist/lib/store.js
CHANGED
|
@@ -2600,7 +2600,7 @@ __export(shard_manager_exports, {
|
|
|
2600
2600
|
shardExists: () => shardExists
|
|
2601
2601
|
});
|
|
2602
2602
|
import path7 from "path";
|
|
2603
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2603
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
2604
2604
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2605
2605
|
function initShardManager(encryptionKey) {
|
|
2606
2606
|
_encryptionKey = encryptionKey;
|
|
@@ -2622,7 +2622,7 @@ function getShardClient(projectName) {
|
|
|
2622
2622
|
if (!_encryptionKey) {
|
|
2623
2623
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2624
2624
|
}
|
|
2625
|
-
const safeName = projectName
|
|
2625
|
+
const safeName = safeShardName(projectName);
|
|
2626
2626
|
if (!safeName || safeName === "unknown") {
|
|
2627
2627
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2628
2628
|
}
|
|
@@ -2644,9 +2644,12 @@ function getShardClient(projectName) {
|
|
|
2644
2644
|
return client;
|
|
2645
2645
|
}
|
|
2646
2646
|
function shardExists(projectName) {
|
|
2647
|
-
const safeName = projectName
|
|
2647
|
+
const safeName = safeShardName(projectName);
|
|
2648
2648
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2649
2649
|
}
|
|
2650
|
+
function safeShardName(projectName) {
|
|
2651
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2652
|
+
}
|
|
2650
2653
|
function listShards() {
|
|
2651
2654
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
2652
2655
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -2740,7 +2743,8 @@ async function ensureShardSchema(client) {
|
|
|
2740
2743
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
2741
2744
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
2742
2745
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
2743
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
2746
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
2747
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
2744
2748
|
]) {
|
|
2745
2749
|
try {
|
|
2746
2750
|
await client.execute(col);
|
|
@@ -2836,9 +2840,32 @@ async function ensureShardSchema(client) {
|
|
|
2836
2840
|
}
|
|
2837
2841
|
}
|
|
2838
2842
|
async function getReadyShardClient(projectName) {
|
|
2839
|
-
const
|
|
2840
|
-
|
|
2841
|
-
|
|
2843
|
+
const safeName = safeShardName(projectName);
|
|
2844
|
+
let client = getShardClient(projectName);
|
|
2845
|
+
try {
|
|
2846
|
+
await ensureShardSchema(client);
|
|
2847
|
+
return client;
|
|
2848
|
+
} catch (err) {
|
|
2849
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2850
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
2851
|
+
client.close();
|
|
2852
|
+
_shards.delete(safeName);
|
|
2853
|
+
_shardLastAccess.delete(safeName);
|
|
2854
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
2855
|
+
if (existsSync7(dbPath)) {
|
|
2856
|
+
const stat = statSync2(dbPath);
|
|
2857
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2858
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
2859
|
+
renameSync3(dbPath, archivedPath);
|
|
2860
|
+
process.stderr.write(
|
|
2861
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
2862
|
+
`
|
|
2863
|
+
);
|
|
2864
|
+
}
|
|
2865
|
+
client = getShardClient(projectName);
|
|
2866
|
+
await ensureShardSchema(client);
|
|
2867
|
+
return client;
|
|
2868
|
+
}
|
|
2842
2869
|
}
|
|
2843
2870
|
function evictLRU() {
|
|
2844
2871
|
let oldest = null;
|
package/dist/mcp/server.js
CHANGED
|
@@ -1171,7 +1171,8 @@ function isMultiInstance(agentName, employees) {
|
|
|
1171
1171
|
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
1172
1172
|
}
|
|
1173
1173
|
function addEmployee(employees, employee) {
|
|
1174
|
-
const
|
|
1174
|
+
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
1175
|
+
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
1175
1176
|
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
1176
1177
|
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
1177
1178
|
}
|
|
@@ -3797,7 +3798,7 @@ __export(shard_manager_exports, {
|
|
|
3797
3798
|
shardExists: () => shardExists
|
|
3798
3799
|
});
|
|
3799
3800
|
import path8 from "path";
|
|
3800
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
3801
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
3801
3802
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3802
3803
|
function initShardManager(encryptionKey) {
|
|
3803
3804
|
_encryptionKey = encryptionKey;
|
|
@@ -3819,7 +3820,7 @@ function getShardClient(projectName) {
|
|
|
3819
3820
|
if (!_encryptionKey) {
|
|
3820
3821
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3821
3822
|
}
|
|
3822
|
-
const safeName = projectName
|
|
3823
|
+
const safeName = safeShardName(projectName);
|
|
3823
3824
|
if (!safeName || safeName === "unknown") {
|
|
3824
3825
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3825
3826
|
}
|
|
@@ -3841,9 +3842,12 @@ function getShardClient(projectName) {
|
|
|
3841
3842
|
return client;
|
|
3842
3843
|
}
|
|
3843
3844
|
function shardExists(projectName) {
|
|
3844
|
-
const safeName = projectName
|
|
3845
|
+
const safeName = safeShardName(projectName);
|
|
3845
3846
|
return existsSync8(path8.join(SHARDS_DIR, `${safeName}.db`));
|
|
3846
3847
|
}
|
|
3848
|
+
function safeShardName(projectName) {
|
|
3849
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3850
|
+
}
|
|
3847
3851
|
function listShards() {
|
|
3848
3852
|
if (!existsSync8(SHARDS_DIR)) return [];
|
|
3849
3853
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3937,7 +3941,8 @@ async function ensureShardSchema(client) {
|
|
|
3937
3941
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3938
3942
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3939
3943
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3940
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3944
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3945
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3941
3946
|
]) {
|
|
3942
3947
|
try {
|
|
3943
3948
|
await client.execute(col);
|
|
@@ -4033,9 +4038,32 @@ async function ensureShardSchema(client) {
|
|
|
4033
4038
|
}
|
|
4034
4039
|
}
|
|
4035
4040
|
async function getReadyShardClient(projectName) {
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
|
|
4041
|
+
const safeName = safeShardName(projectName);
|
|
4042
|
+
let client = getShardClient(projectName);
|
|
4043
|
+
try {
|
|
4044
|
+
await ensureShardSchema(client);
|
|
4045
|
+
return client;
|
|
4046
|
+
} catch (err) {
|
|
4047
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4048
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
4049
|
+
client.close();
|
|
4050
|
+
_shards.delete(safeName);
|
|
4051
|
+
_shardLastAccess.delete(safeName);
|
|
4052
|
+
const dbPath = path8.join(SHARDS_DIR, `${safeName}.db`);
|
|
4053
|
+
if (existsSync8(dbPath)) {
|
|
4054
|
+
const stat = statSync2(dbPath);
|
|
4055
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4056
|
+
const archivedPath = path8.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4057
|
+
renameSync3(dbPath, archivedPath);
|
|
4058
|
+
process.stderr.write(
|
|
4059
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
4060
|
+
`
|
|
4061
|
+
);
|
|
4062
|
+
}
|
|
4063
|
+
client = getShardClient(projectName);
|
|
4064
|
+
await ensureShardSchema(client);
|
|
4065
|
+
return client;
|
|
4066
|
+
}
|
|
4039
4067
|
}
|
|
4040
4068
|
function evictLRU() {
|
|
4041
4069
|
let oldest = null;
|
|
@@ -5242,7 +5270,7 @@ __export(file_grep_exports, {
|
|
|
5242
5270
|
grepProjectFiles: () => grepProjectFiles
|
|
5243
5271
|
});
|
|
5244
5272
|
import { execSync as execSync4 } from "child_process";
|
|
5245
|
-
import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as
|
|
5273
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync3, existsSync as existsSync10 } from "fs";
|
|
5246
5274
|
import path11 from "path";
|
|
5247
5275
|
import crypto2 from "crypto";
|
|
5248
5276
|
function hasRipgrep() {
|
|
@@ -5359,7 +5387,7 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
|
|
|
5359
5387
|
for (const filePath of files.slice(0, MAX_FILES)) {
|
|
5360
5388
|
const absPath = path11.join(projectRoot, filePath);
|
|
5361
5389
|
try {
|
|
5362
|
-
const stat =
|
|
5390
|
+
const stat = statSync3(absPath);
|
|
5363
5391
|
if (stat.size > MAX_FILE_SIZE) continue;
|
|
5364
5392
|
const content = readFileSync6(absPath, "utf8");
|
|
5365
5393
|
const lines = content.split("\n");
|
|
@@ -7181,8 +7209,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
7181
7209
|
}
|
|
7182
7210
|
function getCacheAgeMs() {
|
|
7183
7211
|
try {
|
|
7184
|
-
const { statSync:
|
|
7185
|
-
const s =
|
|
7212
|
+
const { statSync: statSync7 } = __require("fs");
|
|
7213
|
+
const s = statSync7(CACHE_PATH);
|
|
7186
7214
|
return Date.now() - s.mtimeMs;
|
|
7187
7215
|
} catch {
|
|
7188
7216
|
return Infinity;
|
|
@@ -8293,7 +8321,7 @@ __export(intercom_queue_exports, {
|
|
|
8293
8321
|
queueIntercom: () => queueIntercom,
|
|
8294
8322
|
readQueue: () => readQueue
|
|
8295
8323
|
});
|
|
8296
|
-
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, renameSync as
|
|
8324
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, renameSync as renameSync4, existsSync as existsSync14, mkdirSync as mkdirSync6 } from "fs";
|
|
8297
8325
|
import path18 from "path";
|
|
8298
8326
|
import os8 from "os";
|
|
8299
8327
|
function ensureDir() {
|
|
@@ -8312,7 +8340,7 @@ function writeQueue(queue) {
|
|
|
8312
8340
|
ensureDir();
|
|
8313
8341
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
8314
8342
|
writeFileSync9(tmp, JSON.stringify(queue, null, 2));
|
|
8315
|
-
|
|
8343
|
+
renameSync4(tmp, QUEUE_PATH);
|
|
8316
8344
|
}
|
|
8317
8345
|
function queueIntercom(targetSession, reason) {
|
|
8318
8346
|
const queue = readQueue();
|
|
@@ -11397,6 +11425,9 @@ function ensureDir2() {
|
|
|
11397
11425
|
function identityPath(agentId) {
|
|
11398
11426
|
return path25.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
11399
11427
|
}
|
|
11428
|
+
function sanitizeIdentityBody(body) {
|
|
11429
|
+
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
11430
|
+
}
|
|
11400
11431
|
function parseFrontmatter(raw) {
|
|
11401
11432
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
11402
11433
|
if (!match) {
|
|
@@ -11409,11 +11440,11 @@ function parseFrontmatter(raw) {
|
|
|
11409
11440
|
created_by: "system",
|
|
11410
11441
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
11411
11442
|
},
|
|
11412
|
-
body: raw
|
|
11443
|
+
body: sanitizeIdentityBody(raw)
|
|
11413
11444
|
};
|
|
11414
11445
|
}
|
|
11415
11446
|
const yamlStr = match[1];
|
|
11416
|
-
const body = match[2]
|
|
11447
|
+
const body = sanitizeIdentityBody(match[2]);
|
|
11417
11448
|
const fm = {};
|
|
11418
11449
|
for (const line of yamlStr.split("\n")) {
|
|
11419
11450
|
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
@@ -11478,7 +11509,9 @@ function listIdentities() {
|
|
|
11478
11509
|
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
11479
11510
|
results.push({
|
|
11480
11511
|
agentId,
|
|
11481
|
-
title
|
|
11512
|
+
// User-facing/team-facing title only. `frontmatter.role` is internal
|
|
11513
|
+
// routing metadata and must not leak as an external title.
|
|
11514
|
+
title: identity.frontmatter.title,
|
|
11482
11515
|
summary
|
|
11483
11516
|
});
|
|
11484
11517
|
}
|
|
@@ -12369,7 +12402,7 @@ __export(db_backup_exports, {
|
|
|
12369
12402
|
listBackups: () => listBackups,
|
|
12370
12403
|
rotateBackups: () => rotateBackups
|
|
12371
12404
|
});
|
|
12372
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync15, readdirSync as readdirSync12, unlinkSync as unlinkSync9, statSync as
|
|
12405
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync15, readdirSync as readdirSync12, unlinkSync as unlinkSync9, statSync as statSync5 } from "fs";
|
|
12373
12406
|
import path37 from "path";
|
|
12374
12407
|
function findActiveDb() {
|
|
12375
12408
|
for (const name of DB_NAMES) {
|
|
@@ -12413,7 +12446,7 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
|
12413
12446
|
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
12414
12447
|
const filePath = path37.join(BACKUP_DIR, file);
|
|
12415
12448
|
try {
|
|
12416
|
-
const stat =
|
|
12449
|
+
const stat = statSync5(filePath);
|
|
12417
12450
|
if (stat.mtimeMs < cutoff) {
|
|
12418
12451
|
unlinkSync9(filePath);
|
|
12419
12452
|
deleted++;
|
|
@@ -12431,7 +12464,7 @@ function listBackups() {
|
|
|
12431
12464
|
const files = readdirSync12(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
12432
12465
|
return files.map((name) => {
|
|
12433
12466
|
const p = path37.join(BACKUP_DIR, name);
|
|
12434
|
-
const stat =
|
|
12467
|
+
const stat = statSync5(p);
|
|
12435
12468
|
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
12436
12469
|
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
12437
12470
|
} catch {
|
|
@@ -12762,6 +12795,12 @@ init_hybrid_search();
|
|
|
12762
12795
|
init_store();
|
|
12763
12796
|
init_active_agent();
|
|
12764
12797
|
import { z } from "zod";
|
|
12798
|
+
function formatMemoryBody(rawText, maxChars) {
|
|
12799
|
+
if (rawText.length <= maxChars) return rawText;
|
|
12800
|
+
const marker = ` \u2026 [truncated; +${rawText.length - maxChars} chars \u2014 re-call with max_chars up to 20000 for more]`;
|
|
12801
|
+
const sliceLen = Math.max(0, maxChars - marker.length);
|
|
12802
|
+
return `${rawText.slice(0, sliceLen)}${marker}`;
|
|
12803
|
+
}
|
|
12765
12804
|
function formatSourceLine(record) {
|
|
12766
12805
|
const doc2 = record.document_metadata;
|
|
12767
12806
|
if (!doc2) return "";
|
|
@@ -12787,6 +12826,7 @@ function registerRecallMyMemory(server2) {
|
|
|
12787
12826
|
has_error: z.boolean().optional().describe("Filter for error-containing memories"),
|
|
12788
12827
|
tool_name: z.string().optional().describe("Filter by tool name (Bash, Write, etc)"),
|
|
12789
12828
|
limit: z.coerce.number().optional().default(10).describe("Max results to return"),
|
|
12829
|
+
max_chars: z.coerce.number().int().min(100).max(2e4).optional().default(2e3).describe("Max characters to include per memory result. Use a higher value for canonical plans/runbooks."),
|
|
12790
12830
|
since: z.string().optional().describe("ISO 8601 timestamp \u2014 only return memories at or after this time"),
|
|
12791
12831
|
include_archived: z.boolean().optional().default(false).describe(
|
|
12792
12832
|
"Include deprecated (archived) memories alongside active ones. Default false."
|
|
@@ -12808,6 +12848,7 @@ function registerRecallMyMemory(server2) {
|
|
|
12808
12848
|
has_error,
|
|
12809
12849
|
tool_name,
|
|
12810
12850
|
limit,
|
|
12851
|
+
max_chars,
|
|
12811
12852
|
since,
|
|
12812
12853
|
include_archived,
|
|
12813
12854
|
workspace_id,
|
|
@@ -12853,7 +12894,7 @@ function registerRecallMyMemory(server2) {
|
|
|
12853
12894
|
}
|
|
12854
12895
|
const formatted = results.map((r) => {
|
|
12855
12896
|
const header = `[${r.timestamp}] ${r.tool_name} (${r.project_name})${r.has_error ? " [ERROR]" : ""}`;
|
|
12856
|
-
const body = r.raw_text
|
|
12897
|
+
const body = formatMemoryBody(r.raw_text, max_chars ?? 2e3);
|
|
12857
12898
|
const parts = [header];
|
|
12858
12899
|
if (r.source_path) {
|
|
12859
12900
|
const typeTag = r.source_type && r.source_type !== "text" ? ` [${r.source_type}]` : "";
|
|
@@ -12892,6 +12933,12 @@ init_hybrid_search();
|
|
|
12892
12933
|
init_active_agent();
|
|
12893
12934
|
init_employees();
|
|
12894
12935
|
import { z as z2 } from "zod";
|
|
12936
|
+
function formatMemoryBody2(rawText, maxChars) {
|
|
12937
|
+
if (rawText.length <= maxChars) return rawText;
|
|
12938
|
+
const marker = ` \u2026 [truncated; +${rawText.length - maxChars} chars \u2014 re-call with max_chars up to 20000 for more]`;
|
|
12939
|
+
const sliceLen = Math.max(0, maxChars - marker.length);
|
|
12940
|
+
return `${rawText.slice(0, sliceLen)}${marker}`;
|
|
12941
|
+
}
|
|
12895
12942
|
function canSeeRaw(queryingRole, targetRole) {
|
|
12896
12943
|
if (queryingRole === "COO") return true;
|
|
12897
12944
|
if (queryingRole === "CTO" && [
|
|
@@ -12916,6 +12963,7 @@ function registerAskTeamMemory(server2) {
|
|
|
12916
12963
|
query: z2.string().describe("What to search for"),
|
|
12917
12964
|
project_name: z2.string().optional().describe("Filter by project name"),
|
|
12918
12965
|
limit: z2.coerce.number().optional().default(10).describe("Max results to return"),
|
|
12966
|
+
max_chars: z2.coerce.number().int().min(100).max(2e4).optional().default(2e3).describe("Max characters to include per memory result. Use a higher value for canonical plans/runbooks."),
|
|
12919
12967
|
since: z2.string().optional().describe("ISO 8601 timestamp \u2014 only return memories at or after this time"),
|
|
12920
12968
|
include_archived: z2.boolean().optional().default(false).describe(
|
|
12921
12969
|
"Include deprecated (archived) memories alongside active ones. Default false."
|
|
@@ -12926,7 +12974,7 @@ function registerAskTeamMemory(server2) {
|
|
|
12926
12974
|
retrieval_mode: z2.enum(RETRIEVAL_MODES).optional().default("all").describe(`Typed retrieval mode. Raw visibility is still ACL-gated. ${formatRetrievalModes()}`)
|
|
12927
12975
|
}
|
|
12928
12976
|
},
|
|
12929
|
-
async ({ team_member, query, project_name, limit, since, include_archived, include_raw: _include_raw, retrieval_mode }) => {
|
|
12977
|
+
async ({ team_member, query, project_name, limit, max_chars, since, include_archived, include_raw: _include_raw, retrieval_mode }) => {
|
|
12930
12978
|
try {
|
|
12931
12979
|
const { agentId: queryingAgentId, agentRole: queryingAgentRole } = getActiveAgent();
|
|
12932
12980
|
const employees = loadEmployeesSync();
|
|
@@ -12959,7 +13007,7 @@ function registerAskTeamMemory(server2) {
|
|
|
12959
13007
|
}
|
|
12960
13008
|
const formatted = results.map(
|
|
12961
13009
|
(r) => `[${r.timestamp}] ${r.tool_name} (${r.project_name})${r.has_error ? " [ERROR]" : ""}
|
|
12962
|
-
${r.raw_text
|
|
13010
|
+
${formatMemoryBody2(r.raw_text, max_chars ?? 2e3)}`
|
|
12963
13011
|
).join("\n\n---\n\n");
|
|
12964
13012
|
return {
|
|
12965
13013
|
content: [
|
|
@@ -13201,7 +13249,8 @@ var MAX_SNIPPET = 500;
|
|
|
13201
13249
|
var ALL_SOURCES = ["memory", "conversations", "wiki"];
|
|
13202
13250
|
function truncate(text3, max) {
|
|
13203
13251
|
if (text3.length <= max) return text3;
|
|
13204
|
-
|
|
13252
|
+
const marker = ` \u2026 [truncated; +${text3.length - max} chars]`;
|
|
13253
|
+
return text3.slice(0, Math.max(0, max - marker.length)) + marker;
|
|
13205
13254
|
}
|
|
13206
13255
|
async function searchMemories2(query, agentId, limit) {
|
|
13207
13256
|
const { hybridSearch: hybridSearch2 } = await Promise.resolve().then(() => (init_hybrid_search(), hybrid_search_exports));
|
|
@@ -13422,6 +13471,12 @@ ${formatted.join("\n\n---\n\n")}`
|
|
|
13422
13471
|
// src/mcp/tools/get-session-context.ts
|
|
13423
13472
|
init_database();
|
|
13424
13473
|
import { z as z6 } from "zod";
|
|
13474
|
+
function formatMemoryBody3(rawText, maxChars) {
|
|
13475
|
+
if (rawText.length <= maxChars) return rawText;
|
|
13476
|
+
const marker = ` \u2026 [truncated; +${rawText.length - maxChars} chars \u2014 re-call with max_chars up to 20000 for more]`;
|
|
13477
|
+
const sliceLen = Math.max(0, maxChars - marker.length);
|
|
13478
|
+
return `${rawText.slice(0, sliceLen)}${marker}`;
|
|
13479
|
+
}
|
|
13425
13480
|
function registerGetSessionContext(server2) {
|
|
13426
13481
|
server2.registerTool(
|
|
13427
13482
|
"get_session_context",
|
|
@@ -13433,10 +13488,11 @@ function registerGetSessionContext(server2) {
|
|
|
13433
13488
|
target_timestamp: z6.string().describe(
|
|
13434
13489
|
"ISO 8601 timestamp to center the context window around"
|
|
13435
13490
|
),
|
|
13436
|
-
window_size: z6.number().optional().default(3).describe("Number of memories before and after the target")
|
|
13491
|
+
window_size: z6.number().optional().default(3).describe("Number of memories before and after the target"),
|
|
13492
|
+
max_chars: z6.coerce.number().int().min(100).max(2e4).optional().default(2e3).describe("Max characters to include per memory result.")
|
|
13437
13493
|
}
|
|
13438
13494
|
},
|
|
13439
|
-
async ({ session_id, target_timestamp, window_size }) => {
|
|
13495
|
+
async ({ session_id, target_timestamp, window_size, max_chars }) => {
|
|
13440
13496
|
const client = getClient();
|
|
13441
13497
|
const result = await client.execute({
|
|
13442
13498
|
sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
|
|
@@ -13482,7 +13538,7 @@ function registerGetSessionContext(server2) {
|
|
|
13482
13538
|
const windowMemories = sorted.slice(start, end);
|
|
13483
13539
|
const formatted = windowMemories.map(
|
|
13484
13540
|
(r) => `[${r.timestamp}] ${r.tool_name} (${r.project_name})${r.has_error ? " [ERROR]" : ""}
|
|
13485
|
-
${r.raw_text
|
|
13541
|
+
${formatMemoryBody3(r.raw_text, max_chars ?? 2e3)}`
|
|
13486
13542
|
).join("\n\n---\n\n");
|
|
13487
13543
|
return {
|
|
13488
13544
|
content: [
|
|
@@ -14117,8 +14173,43 @@ ${lines.join("\n")}`
|
|
|
14117
14173
|
// src/mcp/tools/get-task.ts
|
|
14118
14174
|
init_tasks();
|
|
14119
14175
|
init_database();
|
|
14176
|
+
init_task_scope();
|
|
14120
14177
|
init_employees();
|
|
14121
14178
|
import { z as z13 } from "zod";
|
|
14179
|
+
async function diagnoseMissingTask(client, identifier) {
|
|
14180
|
+
const shortUuid = /^[a-f0-9]{7,12}$/i.test(identifier);
|
|
14181
|
+
const args = [];
|
|
14182
|
+
const clauses = [];
|
|
14183
|
+
if (shortUuid) {
|
|
14184
|
+
clauses.push("id LIKE ?");
|
|
14185
|
+
args.push(`${identifier}%`);
|
|
14186
|
+
}
|
|
14187
|
+
clauses.push("task_file LIKE ?");
|
|
14188
|
+
args.push(`%${identifier}%`);
|
|
14189
|
+
clauses.push("title LIKE ?");
|
|
14190
|
+
args.push(`%${identifier}%`);
|
|
14191
|
+
const result = await client.execute({
|
|
14192
|
+
sql: `SELECT id, title, status, assigned_to, project_name, session_scope, task_file
|
|
14193
|
+
FROM tasks
|
|
14194
|
+
WHERE ${clauses.map((c) => `(${c})`).join(" OR ")}
|
|
14195
|
+
ORDER BY updated_at DESC
|
|
14196
|
+
LIMIT 10`,
|
|
14197
|
+
args
|
|
14198
|
+
});
|
|
14199
|
+
if (result.rows.length === 0) return null;
|
|
14200
|
+
const scoped = sessionScopeFilter();
|
|
14201
|
+
const scopeNote = scoped.args.length > 0 ? `Current session scope appears to be ${String(scoped.args[0])}. get_task is session-scoped by default.` : "No current session scope detected.";
|
|
14202
|
+
const matches = result.rows.map((r) => {
|
|
14203
|
+
const id = String(r.id);
|
|
14204
|
+
return `- ${id.slice(0, 8)} ${String(r.title)} [${String(r.status)}] assigned_to=${String(r.assigned_to)} project=${String(r.project_name)} session_scope=${String(r.session_scope ?? "NULL")}`;
|
|
14205
|
+
}).join("\n");
|
|
14206
|
+
return `Task not found in the current scoped lookup, but similar task rows exist. ${scopeNote}
|
|
14207
|
+
|
|
14208
|
+
Matches across all scopes/statuses:
|
|
14209
|
+
${matches}
|
|
14210
|
+
|
|
14211
|
+
Use the full UUID from the matching row, switch to the owning coordinator session, or list tasks with the correct project/session scope.`;
|
|
14212
|
+
}
|
|
14122
14213
|
function registerGetTask(server2) {
|
|
14123
14214
|
server2.registerTool(
|
|
14124
14215
|
"get_task",
|
|
@@ -14131,7 +14222,16 @@ function registerGetTask(server2) {
|
|
|
14131
14222
|
},
|
|
14132
14223
|
async ({ task_id }) => {
|
|
14133
14224
|
const client = getClient();
|
|
14134
|
-
|
|
14225
|
+
let row;
|
|
14226
|
+
try {
|
|
14227
|
+
row = await resolveTask(client, task_id);
|
|
14228
|
+
} catch (err) {
|
|
14229
|
+
const fallback = await diagnoseMissingTask(client, task_id);
|
|
14230
|
+
if (fallback) {
|
|
14231
|
+
return { content: [{ type: "text", text: fallback }], isError: true };
|
|
14232
|
+
}
|
|
14233
|
+
throw err;
|
|
14234
|
+
}
|
|
14135
14235
|
const contextText = row.context ? String(row.context) : "";
|
|
14136
14236
|
const hasEmbeddedMandatoryReminder = contextText.includes('update_task with status "done"') || contextText.includes("update_task(done)");
|
|
14137
14237
|
const lines = [
|
|
@@ -18568,7 +18668,7 @@ function registerImportOrchestration(server2) {
|
|
|
18568
18668
|
|
|
18569
18669
|
// src/mcp/tools/load-skill.ts
|
|
18570
18670
|
import { z as z50 } from "zod";
|
|
18571
|
-
import { readFileSync as readFileSync21, readdirSync as readdirSync9, statSync as
|
|
18671
|
+
import { readFileSync as readFileSync21, readdirSync as readdirSync9, statSync as statSync4 } from "fs";
|
|
18572
18672
|
import path32 from "path";
|
|
18573
18673
|
import { homedir as homedir2 } from "os";
|
|
18574
18674
|
var SKILLS_DIR = path32.join(homedir2(), ".claude", "skills");
|
|
@@ -18578,9 +18678,9 @@ function listAvailableSkills() {
|
|
|
18578
18678
|
return entries.filter((entry) => {
|
|
18579
18679
|
try {
|
|
18580
18680
|
const entryPath = path32.join(SKILLS_DIR, entry);
|
|
18581
|
-
if (!
|
|
18681
|
+
if (!statSync4(entryPath).isDirectory()) return false;
|
|
18582
18682
|
const skillFile = path32.join(entryPath, "SKILL.md");
|
|
18583
|
-
|
|
18683
|
+
statSync4(skillFile);
|
|
18584
18684
|
return true;
|
|
18585
18685
|
} catch {
|
|
18586
18686
|
return false;
|
|
@@ -21392,7 +21492,7 @@ import { z as z70 } from "zod";
|
|
|
21392
21492
|
|
|
21393
21493
|
// src/lib/cloud-sync.ts
|
|
21394
21494
|
init_database();
|
|
21395
|
-
import { readFileSync as readFileSync26, writeFileSync as writeFileSync20, existsSync as existsSync32, readdirSync as readdirSync13, mkdirSync as mkdirSync17, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as
|
|
21495
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync20, existsSync as existsSync32, readdirSync as readdirSync13, mkdirSync as mkdirSync17, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync6 } from "fs";
|
|
21396
21496
|
import crypto17 from "crypto";
|
|
21397
21497
|
import path40 from "path";
|
|
21398
21498
|
import { homedir as homedir6 } from "os";
|
|
@@ -21959,7 +22059,7 @@ async function cloudSync(config2) {
|
|
|
21959
22059
|
const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
|
|
21960
22060
|
const latestBackup = getLatestBackup2();
|
|
21961
22061
|
if (latestBackup) {
|
|
21962
|
-
const backupSize =
|
|
22062
|
+
const backupSize = statSync6(latestBackup).size;
|
|
21963
22063
|
const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
|
|
21964
22064
|
if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
|
|
21965
22065
|
const backupData = readFileSync26(latestBackup);
|
|
@@ -546,7 +546,8 @@ function isMultiInstance(agentName, employees) {
|
|
|
546
546
|
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
547
547
|
}
|
|
548
548
|
function addEmployee(employees, employee) {
|
|
549
|
-
const
|
|
549
|
+
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
550
|
+
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
550
551
|
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
551
552
|
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
552
553
|
}
|
|
@@ -4808,6 +4809,9 @@ function ensureDir2() {
|
|
|
4808
4809
|
function identityPath(agentId) {
|
|
4809
4810
|
return path19.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
4810
4811
|
}
|
|
4812
|
+
function sanitizeIdentityBody(body) {
|
|
4813
|
+
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
4814
|
+
}
|
|
4811
4815
|
function parseFrontmatter(raw) {
|
|
4812
4816
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
4813
4817
|
if (!match) {
|
|
@@ -4820,11 +4824,11 @@ function parseFrontmatter(raw) {
|
|
|
4820
4824
|
created_by: "system",
|
|
4821
4825
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4822
4826
|
},
|
|
4823
|
-
body: raw
|
|
4827
|
+
body: sanitizeIdentityBody(raw)
|
|
4824
4828
|
};
|
|
4825
4829
|
}
|
|
4826
4830
|
const yamlStr = match[1];
|
|
4827
|
-
const body = match[2]
|
|
4831
|
+
const body = sanitizeIdentityBody(match[2]);
|
|
4828
4832
|
const fm = {};
|
|
4829
4833
|
for (const line of yamlStr.split("\n")) {
|
|
4830
4834
|
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
@@ -4889,7 +4893,9 @@ function listIdentities() {
|
|
|
4889
4893
|
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
4890
4894
|
results.push({
|
|
4891
4895
|
agentId,
|
|
4892
|
-
title
|
|
4896
|
+
// User-facing/team-facing title only. `frontmatter.role` is internal
|
|
4897
|
+
// routing metadata and must not leak as an external title.
|
|
4898
|
+
title: identity.frontmatter.title,
|
|
4893
4899
|
summary
|
|
4894
4900
|
});
|
|
4895
4901
|
}
|
package/dist/runtime/index.js
CHANGED
|
@@ -6984,7 +6984,7 @@ __export(shard_manager_exports, {
|
|
|
6984
6984
|
shardExists: () => shardExists
|
|
6985
6985
|
});
|
|
6986
6986
|
import path20 from "path";
|
|
6987
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readdirSync as readdirSync4 } from "fs";
|
|
6987
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync2 } from "fs";
|
|
6988
6988
|
import { createClient as createClient2 } from "@libsql/client";
|
|
6989
6989
|
function initShardManager(encryptionKey) {
|
|
6990
6990
|
_encryptionKey = encryptionKey;
|
|
@@ -7006,7 +7006,7 @@ function getShardClient(projectName) {
|
|
|
7006
7006
|
if (!_encryptionKey) {
|
|
7007
7007
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
7008
7008
|
}
|
|
7009
|
-
const safeName = projectName
|
|
7009
|
+
const safeName = safeShardName(projectName);
|
|
7010
7010
|
if (!safeName || safeName === "unknown") {
|
|
7011
7011
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
7012
7012
|
}
|
|
@@ -7028,9 +7028,12 @@ function getShardClient(projectName) {
|
|
|
7028
7028
|
return client;
|
|
7029
7029
|
}
|
|
7030
7030
|
function shardExists(projectName) {
|
|
7031
|
-
const safeName = projectName
|
|
7031
|
+
const safeName = safeShardName(projectName);
|
|
7032
7032
|
return existsSync16(path20.join(SHARDS_DIR, `${safeName}.db`));
|
|
7033
7033
|
}
|
|
7034
|
+
function safeShardName(projectName) {
|
|
7035
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7036
|
+
}
|
|
7034
7037
|
function listShards() {
|
|
7035
7038
|
if (!existsSync16(SHARDS_DIR)) return [];
|
|
7036
7039
|
return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -7124,7 +7127,8 @@ async function ensureShardSchema(client) {
|
|
|
7124
7127
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
7125
7128
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
7126
7129
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
7127
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
7130
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
7131
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
7128
7132
|
]) {
|
|
7129
7133
|
try {
|
|
7130
7134
|
await client.execute(col);
|
|
@@ -7220,9 +7224,32 @@ async function ensureShardSchema(client) {
|
|
|
7220
7224
|
}
|
|
7221
7225
|
}
|
|
7222
7226
|
async function getReadyShardClient(projectName) {
|
|
7223
|
-
const
|
|
7224
|
-
|
|
7225
|
-
|
|
7227
|
+
const safeName = safeShardName(projectName);
|
|
7228
|
+
let client = getShardClient(projectName);
|
|
7229
|
+
try {
|
|
7230
|
+
await ensureShardSchema(client);
|
|
7231
|
+
return client;
|
|
7232
|
+
} catch (err) {
|
|
7233
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7234
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
7235
|
+
client.close();
|
|
7236
|
+
_shards.delete(safeName);
|
|
7237
|
+
_shardLastAccess.delete(safeName);
|
|
7238
|
+
const dbPath = path20.join(SHARDS_DIR, `${safeName}.db`);
|
|
7239
|
+
if (existsSync16(dbPath)) {
|
|
7240
|
+
const stat = statSync2(dbPath);
|
|
7241
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7242
|
+
const archivedPath = path20.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7243
|
+
renameSync4(dbPath, archivedPath);
|
|
7244
|
+
process.stderr.write(
|
|
7245
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
7246
|
+
`
|
|
7247
|
+
);
|
|
7248
|
+
}
|
|
7249
|
+
client = getShardClient(projectName);
|
|
7250
|
+
await ensureShardSchema(client);
|
|
7251
|
+
return client;
|
|
7252
|
+
}
|
|
7226
7253
|
}
|
|
7227
7254
|
function evictLRU() {
|
|
7228
7255
|
let oldest = null;
|