@askexenow/exe-os 0.9.80 → 0.9.82
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 +138 -5
- package/dist/bin/cli.js +7 -6
- package/dist/bin/customer-readiness.js +23 -0
- package/dist/bin/exe-gateway.js +123 -10
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/bin/stack-update.js +163 -41
- package/dist/lib/exe-daemon.js +1308 -612
- package/dist/mcp/server.js +1379 -449
- package/package.json +1 -1
- package/stack.release.json +5 -4
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -1566,8 +1566,8 @@ function findPackageRoot() {
|
|
|
1566
1566
|
function getAvailableMemoryGB() {
|
|
1567
1567
|
if (process.platform === "darwin") {
|
|
1568
1568
|
try {
|
|
1569
|
-
const { execSync:
|
|
1570
|
-
const vmstat =
|
|
1569
|
+
const { execSync: execSync17 } = __require("child_process");
|
|
1570
|
+
const vmstat = execSync17("vm_stat", { encoding: "utf8" });
|
|
1571
1571
|
const pageSize = 16384;
|
|
1572
1572
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1573
1573
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -1821,15 +1821,15 @@ function isDaemonTooYoung() {
|
|
|
1821
1821
|
}
|
|
1822
1822
|
}
|
|
1823
1823
|
async function retryThenRestart(doRequest, label) {
|
|
1824
|
-
const
|
|
1825
|
-
if (!
|
|
1824
|
+
const result3 = await doRequest();
|
|
1825
|
+
if (!result3.error) {
|
|
1826
1826
|
_consecutiveFailures = 0;
|
|
1827
|
-
return
|
|
1827
|
+
return result3;
|
|
1828
1828
|
}
|
|
1829
1829
|
_consecutiveFailures++;
|
|
1830
1830
|
for (let i = 0; i < MAX_RETRIES_BEFORE_RESTART; i++) {
|
|
1831
1831
|
const delayMs = RETRY_DELAYS_MS[i] ?? 5e3;
|
|
1832
|
-
process.stderr.write(`[exed-client] ${label} failed (${
|
|
1832
|
+
process.stderr.write(`[exed-client] ${label} failed (${result3.error}), retry ${i + 1}/${MAX_RETRIES_BEFORE_RESTART} in ${delayMs}ms
|
|
1833
1833
|
`);
|
|
1834
1834
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
1835
1835
|
if (!_connected) {
|
|
@@ -1845,7 +1845,7 @@ async function retryThenRestart(doRequest, label) {
|
|
|
1845
1845
|
if (isDaemonTooYoung()) {
|
|
1846
1846
|
process.stderr.write(`[exed-client] ${label}: daemon too young (< ${MIN_DAEMON_AGE_MS / 1e3}s) \u2014 skipping restart
|
|
1847
1847
|
`);
|
|
1848
|
-
return { error:
|
|
1848
|
+
return { error: result3.error };
|
|
1849
1849
|
}
|
|
1850
1850
|
process.stderr.write(`[exed-client] ${label}: ${_consecutiveFailures} consecutive failures \u2014 restarting daemon
|
|
1851
1851
|
`);
|
|
@@ -1881,20 +1881,20 @@ async function embedViaClient(text3, priority = "high") {
|
|
|
1881
1881
|
if (!_connected) return null;
|
|
1882
1882
|
}
|
|
1883
1883
|
}
|
|
1884
|
-
const
|
|
1884
|
+
const result3 = await retryThenRestart(
|
|
1885
1885
|
() => sendRequest([text3], priority),
|
|
1886
1886
|
"Embed"
|
|
1887
1887
|
);
|
|
1888
|
-
return !
|
|
1888
|
+
return !result3.error && result3.vectors?.[0] ? result3.vectors[0] : null;
|
|
1889
1889
|
}
|
|
1890
1890
|
async function embedBatchViaClient(texts, priority = "high") {
|
|
1891
1891
|
if (!_connected && !await connectEmbedDaemon()) return null;
|
|
1892
1892
|
_requestCount++;
|
|
1893
|
-
const
|
|
1893
|
+
const result3 = await retryThenRestart(
|
|
1894
1894
|
() => sendRequest(texts, priority),
|
|
1895
1895
|
"Batch embed"
|
|
1896
1896
|
);
|
|
1897
|
-
return !
|
|
1897
|
+
return !result3.error && result3.vectors ? result3.vectors : null;
|
|
1898
1898
|
}
|
|
1899
1899
|
function disconnectClient() {
|
|
1900
1900
|
if (_socket) {
|
|
@@ -3581,8 +3581,8 @@ async function findScopedDuplicate(input) {
|
|
|
3581
3581
|
args.push(input.excludeId);
|
|
3582
3582
|
}
|
|
3583
3583
|
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
3584
|
-
const
|
|
3585
|
-
return
|
|
3584
|
+
const result3 = await client.execute({ sql, args });
|
|
3585
|
+
return result3.rows[0]?.id ? String(result3.rows[0].id) : null;
|
|
3586
3586
|
}
|
|
3587
3587
|
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3588
3588
|
try {
|
|
@@ -4158,12 +4158,12 @@ function loadPrisma() {
|
|
|
4158
4158
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
4159
4159
|
return {
|
|
4160
4160
|
async $queryRawUnsafe(query, ...values) {
|
|
4161
|
-
const
|
|
4162
|
-
return
|
|
4161
|
+
const result3 = await pool.query(query, values);
|
|
4162
|
+
return result3.rows;
|
|
4163
4163
|
},
|
|
4164
4164
|
async $executeRawUnsafe(query, ...values) {
|
|
4165
|
-
const
|
|
4166
|
-
return
|
|
4165
|
+
const result3 = await pool.query(query, values);
|
|
4166
|
+
return result3.rowCount ?? 0;
|
|
4167
4167
|
},
|
|
4168
4168
|
async $disconnect() {
|
|
4169
4169
|
await pool.end();
|
|
@@ -4541,12 +4541,12 @@ async function processBatch() {
|
|
|
4541
4541
|
for (const event of events) {
|
|
4542
4542
|
try {
|
|
4543
4543
|
const handler = projectionHandlers[event.source] ?? defaultHandler;
|
|
4544
|
-
const
|
|
4544
|
+
const result3 = await handler(event, prisma);
|
|
4545
4545
|
await prisma.$executeRawUnsafe(
|
|
4546
4546
|
`UPDATE "raw"."raw_events"
|
|
4547
4547
|
SET "processed_at" = NOW(), "projections" = $1::jsonb
|
|
4548
4548
|
WHERE "id" = $2`,
|
|
4549
|
-
JSON.stringify({ targets:
|
|
4549
|
+
JSON.stringify({ targets: result3.targets, skipped: result3.skipped }),
|
|
4550
4550
|
event.id
|
|
4551
4551
|
);
|
|
4552
4552
|
processed++;
|
|
@@ -5348,8 +5348,8 @@ function deriveMachineKey() {
|
|
|
5348
5348
|
}
|
|
5349
5349
|
function readMachineId() {
|
|
5350
5350
|
try {
|
|
5351
|
-
const { readFileSync:
|
|
5352
|
-
return
|
|
5351
|
+
const { readFileSync: readFileSync42 } = __require("fs");
|
|
5352
|
+
return readFileSync42("/etc/machine-id", "utf-8").trim();
|
|
5353
5353
|
} catch {
|
|
5354
5354
|
return "";
|
|
5355
5355
|
}
|
|
@@ -5931,11 +5931,11 @@ __export(global_procedures_exports, {
|
|
|
5931
5931
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5932
5932
|
async function loadGlobalProcedures() {
|
|
5933
5933
|
const client = getClient();
|
|
5934
|
-
const
|
|
5934
|
+
const result3 = await client.execute({
|
|
5935
5935
|
sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
|
|
5936
5936
|
args: []
|
|
5937
5937
|
});
|
|
5938
|
-
const allRows =
|
|
5938
|
+
const allRows = result3.rows;
|
|
5939
5939
|
const customerOnly = allRows.filter((p) => !PLATFORM_PROCEDURE_TITLES.has(p.title));
|
|
5940
5940
|
if (customerOnly.length > 0) {
|
|
5941
5941
|
_customerCache = customerOnly.map((p) => `### ${p.title}
|
|
@@ -5971,12 +5971,12 @@ async function storeGlobalProcedure(input) {
|
|
|
5971
5971
|
async function deactivateGlobalProcedure(id) {
|
|
5972
5972
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
5973
5973
|
const client = getClient();
|
|
5974
|
-
const
|
|
5974
|
+
const result3 = await client.execute({
|
|
5975
5975
|
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
5976
5976
|
args: [now2, id]
|
|
5977
5977
|
});
|
|
5978
5978
|
await loadGlobalProcedures();
|
|
5979
|
-
return
|
|
5979
|
+
return result3.rowsAffected > 0;
|
|
5980
5980
|
}
|
|
5981
5981
|
var _customerCache, _cacheLoaded, _platformCache;
|
|
5982
5982
|
var init_global_procedures = __esm({
|
|
@@ -6120,8 +6120,8 @@ async function searchMemoryCards(queryText, agentId, options) {
|
|
|
6120
6120
|
}
|
|
6121
6121
|
sql += ` ORDER BY rank LIMIT ?`;
|
|
6122
6122
|
args.push(limit);
|
|
6123
|
-
const
|
|
6124
|
-
return
|
|
6123
|
+
const result3 = await getClient().execute({ sql, args });
|
|
6124
|
+
return result3.rows.map((row) => ({
|
|
6125
6125
|
id: `card:${String(row.id)}`,
|
|
6126
6126
|
agent_id: String(row.agent_id),
|
|
6127
6127
|
agent_role: "memory_card",
|
|
@@ -6388,7 +6388,7 @@ async function flushBatch() {
|
|
|
6388
6388
|
const hasVector = row.vector !== null;
|
|
6389
6389
|
const taskId = row.task_id ?? null;
|
|
6390
6390
|
const importance = row.importance ?? 5;
|
|
6391
|
-
const
|
|
6391
|
+
const status2 = row.status ?? "active";
|
|
6392
6392
|
const confidence = row.confidence ?? 0.7;
|
|
6393
6393
|
const lastAccessed = row.last_accessed ?? row.timestamp;
|
|
6394
6394
|
const workspaceId = row.workspace_id ?? null;
|
|
@@ -6460,7 +6460,7 @@ async function flushBatch() {
|
|
|
6460
6460
|
row.version,
|
|
6461
6461
|
taskId,
|
|
6462
6462
|
importance,
|
|
6463
|
-
|
|
6463
|
+
status2,
|
|
6464
6464
|
confidence,
|
|
6465
6465
|
lastAccessed,
|
|
6466
6466
|
workspaceId,
|
|
@@ -6630,8 +6630,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
6630
6630
|
args.push(vectorToBlob(queryVector));
|
|
6631
6631
|
sql += ` LIMIT ?`;
|
|
6632
6632
|
args.push(limit);
|
|
6633
|
-
const
|
|
6634
|
-
return
|
|
6633
|
+
const result3 = await client.execute({ sql, args });
|
|
6634
|
+
return result3.rows.map((row) => ({
|
|
6635
6635
|
id: row.id,
|
|
6636
6636
|
agent_id: row.agent_id,
|
|
6637
6637
|
agent_role: row.agent_role,
|
|
@@ -6665,14 +6665,14 @@ async function attachDocumentMetadata(records) {
|
|
|
6665
6665
|
try {
|
|
6666
6666
|
const client = getClient();
|
|
6667
6667
|
const placeholders = docIds.map(() => "?").join(",");
|
|
6668
|
-
const
|
|
6668
|
+
const result3 = await client.execute({
|
|
6669
6669
|
sql: `SELECT id, filename, mime, source_type, uploaded_at
|
|
6670
6670
|
FROM documents
|
|
6671
6671
|
WHERE id IN (${placeholders})`,
|
|
6672
6672
|
args: docIds
|
|
6673
6673
|
});
|
|
6674
6674
|
const byId = /* @__PURE__ */ new Map();
|
|
6675
|
-
for (const row of
|
|
6675
|
+
for (const row of result3.rows) {
|
|
6676
6676
|
const id = row.id;
|
|
6677
6677
|
byId.set(id, {
|
|
6678
6678
|
document_id: id,
|
|
@@ -6695,19 +6695,19 @@ async function flushTier3(agentId, options) {
|
|
|
6695
6695
|
const maxAge = options?.maxAgeHours ?? 72;
|
|
6696
6696
|
const cutoff = new Date(Date.now() - maxAge * 36e5).toISOString();
|
|
6697
6697
|
if (options?.dryRun) {
|
|
6698
|
-
const
|
|
6698
|
+
const result4 = await client.execute({
|
|
6699
6699
|
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
6700
6700
|
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
6701
6701
|
args: [agentId, cutoff]
|
|
6702
6702
|
});
|
|
6703
|
-
return { archived: Number(
|
|
6703
|
+
return { archived: Number(result4.rows[0]?.cnt ?? 0) };
|
|
6704
6704
|
}
|
|
6705
|
-
const
|
|
6705
|
+
const result3 = await client.execute({
|
|
6706
6706
|
sql: `UPDATE memories SET status = 'archived'
|
|
6707
6707
|
WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
|
|
6708
6708
|
args: [agentId, cutoff]
|
|
6709
6709
|
});
|
|
6710
|
-
return { archived:
|
|
6710
|
+
return { archived: result3.rowsAffected };
|
|
6711
6711
|
}
|
|
6712
6712
|
async function disposeStore() {
|
|
6713
6713
|
if (_flushTimer2 !== null) {
|
|
@@ -6725,11 +6725,11 @@ function vectorToBlob(vector) {
|
|
|
6725
6725
|
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
6726
6726
|
return JSON.stringify(Array.from(f32));
|
|
6727
6727
|
}
|
|
6728
|
-
async function updateMemoryStatus(id,
|
|
6728
|
+
async function updateMemoryStatus(id, status2) {
|
|
6729
6729
|
const client = getClient();
|
|
6730
6730
|
await client.execute({
|
|
6731
6731
|
sql: `UPDATE memories SET status = ? WHERE id = ?`,
|
|
6732
|
-
args: [
|
|
6732
|
+
args: [status2, id]
|
|
6733
6733
|
});
|
|
6734
6734
|
}
|
|
6735
6735
|
function reserveVersions(count) {
|
|
@@ -6742,11 +6742,11 @@ function reserveVersions(count) {
|
|
|
6742
6742
|
async function getMemoryCardinality(agentId) {
|
|
6743
6743
|
try {
|
|
6744
6744
|
const client = getClient();
|
|
6745
|
-
const
|
|
6745
|
+
const result3 = await client.execute({
|
|
6746
6746
|
sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND COALESCE(status, 'active') = 'active'`,
|
|
6747
6747
|
args: [agentId]
|
|
6748
6748
|
});
|
|
6749
|
-
return Number(
|
|
6749
|
+
return Number(result3.rows[0]?.cnt) || 0;
|
|
6750
6750
|
} catch {
|
|
6751
6751
|
return 0;
|
|
6752
6752
|
}
|
|
@@ -7174,10 +7174,10 @@ async function disposeEmbedder() {
|
|
|
7174
7174
|
async function embedDirect(text3) {
|
|
7175
7175
|
const llamaCpp = await import("node-llama-cpp");
|
|
7176
7176
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
7177
|
-
const { existsSync:
|
|
7178
|
-
const
|
|
7179
|
-
const modelPath =
|
|
7180
|
-
if (!
|
|
7177
|
+
const { existsSync: existsSync48 } = await import("fs");
|
|
7178
|
+
const path62 = await import("path");
|
|
7179
|
+
const modelPath = path62.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
7180
|
+
if (!existsSync48(modelPath)) {
|
|
7181
7181
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
7182
7182
|
}
|
|
7183
7183
|
const llama = await llamaCpp.getLlama();
|
|
@@ -7496,9 +7496,9 @@ __export(graph_query_exports, {
|
|
|
7496
7496
|
async function getEntityByName(client, name, type) {
|
|
7497
7497
|
const sql = type ? `SELECT * FROM entities WHERE LOWER(name) = LOWER(?) AND type = ? LIMIT 1` : `SELECT * FROM entities WHERE LOWER(name) = LOWER(?) LIMIT 1`;
|
|
7498
7498
|
const args = type ? [name, type] : [name];
|
|
7499
|
-
const
|
|
7500
|
-
if (
|
|
7501
|
-
const row =
|
|
7499
|
+
const result3 = await client.execute({ sql, args });
|
|
7500
|
+
if (result3.rows.length === 0) return null;
|
|
7501
|
+
const row = result3.rows[0];
|
|
7502
7502
|
return {
|
|
7503
7503
|
id: String(row.id),
|
|
7504
7504
|
name: String(row.name),
|
|
@@ -7509,11 +7509,11 @@ async function getEntityByName(client, name, type) {
|
|
|
7509
7509
|
};
|
|
7510
7510
|
}
|
|
7511
7511
|
async function searchEntities(client, query, limit = 10) {
|
|
7512
|
-
const
|
|
7512
|
+
const result3 = await client.execute({
|
|
7513
7513
|
sql: `SELECT * FROM entities WHERE LOWER(name) LIKE ? ORDER BY last_seen DESC LIMIT ?`,
|
|
7514
7514
|
args: [`%${query.toLowerCase()}%`, limit]
|
|
7515
7515
|
});
|
|
7516
|
-
return
|
|
7516
|
+
return result3.rows.map((row) => ({
|
|
7517
7517
|
id: String(row.id),
|
|
7518
7518
|
name: String(row.name),
|
|
7519
7519
|
type: String(row.type),
|
|
@@ -7553,8 +7553,8 @@ async function getRelationships(client, entityId2, options) {
|
|
|
7553
7553
|
args.push(options.type);
|
|
7554
7554
|
}
|
|
7555
7555
|
sql += ` ORDER BY r.weight DESC, r.timestamp DESC`;
|
|
7556
|
-
const
|
|
7557
|
-
return
|
|
7556
|
+
const result3 = await client.execute({ sql, args });
|
|
7557
|
+
return result3.rows.map((row) => ({
|
|
7558
7558
|
id: String(row.id),
|
|
7559
7559
|
sourceEntityId: String(row.source_entity_id),
|
|
7560
7560
|
targetEntityId: String(row.target_entity_id),
|
|
@@ -7569,7 +7569,7 @@ async function getRelationships(client, entityId2, options) {
|
|
|
7569
7569
|
}));
|
|
7570
7570
|
}
|
|
7571
7571
|
async function traverseChain(client, startEntityId, relationshipType, maxDepth = 3) {
|
|
7572
|
-
const
|
|
7572
|
+
const result3 = await client.execute({
|
|
7573
7573
|
sql: `WITH RECURSIVE chain(entity_id, depth, rel_type) AS (
|
|
7574
7574
|
SELECT ?, 0, ''
|
|
7575
7575
|
UNION ALL
|
|
@@ -7584,7 +7584,7 @@ async function traverseChain(client, startEntityId, relationshipType, maxDepth =
|
|
|
7584
7584
|
ORDER BY chain.depth ASC`,
|
|
7585
7585
|
args: [startEntityId, relationshipType, maxDepth]
|
|
7586
7586
|
});
|
|
7587
|
-
return
|
|
7587
|
+
return result3.rows.map((row) => ({
|
|
7588
7588
|
entity: {
|
|
7589
7589
|
id: String(row.id),
|
|
7590
7590
|
name: String(row.name),
|
|
@@ -7598,7 +7598,7 @@ async function traverseChain(client, startEntityId, relationshipType, maxDepth =
|
|
|
7598
7598
|
}));
|
|
7599
7599
|
}
|
|
7600
7600
|
async function getEntityNeighbors(client, entityId2, maxHops = 2) {
|
|
7601
|
-
const
|
|
7601
|
+
const result3 = await client.execute({
|
|
7602
7602
|
sql: `WITH RECURSIVE neighborhood(entity_id, depth, rel_type, rel_confidence) AS (
|
|
7603
7603
|
SELECT ?, 0, '', 1.0
|
|
7604
7604
|
UNION ALL
|
|
@@ -7620,7 +7620,7 @@ async function getEntityNeighbors(client, entityId2, maxHops = 2) {
|
|
|
7620
7620
|
LIMIT 50`,
|
|
7621
7621
|
args: [entityId2, maxHops]
|
|
7622
7622
|
});
|
|
7623
|
-
return
|
|
7623
|
+
return result3.rows.map((row) => ({
|
|
7624
7624
|
entity: {
|
|
7625
7625
|
id: String(row.id),
|
|
7626
7626
|
name: String(row.name),
|
|
@@ -7657,7 +7657,7 @@ async function getEntityTimeline(client, entityId2, since) {
|
|
|
7657
7657
|
sinceClause = " AND r.timestamp >= ?";
|
|
7658
7658
|
args.push(since.toISOString());
|
|
7659
7659
|
}
|
|
7660
|
-
const
|
|
7660
|
+
const result3 = await client.execute({
|
|
7661
7661
|
sql: `SELECT r.*, s.name as source_name, t.name as target_name
|
|
7662
7662
|
FROM relationships r
|
|
7663
7663
|
JOIN entities s ON r.source_entity_id = s.id
|
|
@@ -7666,7 +7666,7 @@ async function getEntityTimeline(client, entityId2, since) {
|
|
|
7666
7666
|
ORDER BY r.timestamp DESC`,
|
|
7667
7667
|
args
|
|
7668
7668
|
});
|
|
7669
|
-
return
|
|
7669
|
+
return result3.rows.map((row) => ({
|
|
7670
7670
|
relationship: {
|
|
7671
7671
|
id: String(row.id),
|
|
7672
7672
|
sourceEntityId: String(row.source_entity_id),
|
|
@@ -7700,7 +7700,7 @@ async function getRelationshipFrequency(client, entityId2, options) {
|
|
|
7700
7700
|
default:
|
|
7701
7701
|
bucketExpr = `strftime('%Y-%m-%d', r.timestamp)`;
|
|
7702
7702
|
}
|
|
7703
|
-
const
|
|
7703
|
+
const result3 = await client.execute({
|
|
7704
7704
|
sql: `SELECT ${bucketExpr} as bucket, COUNT(*) as cnt, r.type as rel_type
|
|
7705
7705
|
FROM relationships r
|
|
7706
7706
|
WHERE (r.source_entity_id = ? OR r.target_entity_id = ?)${typeClause}
|
|
@@ -7708,7 +7708,7 @@ async function getRelationshipFrequency(client, entityId2, options) {
|
|
|
7708
7708
|
ORDER BY bucket DESC`,
|
|
7709
7709
|
args
|
|
7710
7710
|
});
|
|
7711
|
-
return
|
|
7711
|
+
return result3.rows.map((row) => ({
|
|
7712
7712
|
bucket: String(row.bucket),
|
|
7713
7713
|
count: Number(row.cnt),
|
|
7714
7714
|
relationshipType: options?.type ? options.type : String(row.rel_type)
|
|
@@ -7721,7 +7721,7 @@ async function getConversationPartners(client, contactEntityId, since) {
|
|
|
7721
7721
|
sinceClause = " AND r.timestamp >= ?";
|
|
7722
7722
|
args.push(since.toISOString());
|
|
7723
7723
|
}
|
|
7724
|
-
const
|
|
7724
|
+
const result3 = await client.execute({
|
|
7725
7725
|
sql: `SELECT
|
|
7726
7726
|
CASE
|
|
7727
7727
|
WHEN r.source_entity_id = ? THEN r.target_entity_id
|
|
@@ -7736,7 +7736,7 @@ async function getConversationPartners(client, contactEntityId, since) {
|
|
|
7736
7736
|
args: [contactEntityId, ...args]
|
|
7737
7737
|
});
|
|
7738
7738
|
const partners = [];
|
|
7739
|
-
for (const row of
|
|
7739
|
+
for (const row of result3.rows) {
|
|
7740
7740
|
const partnerId = String(row.partner_id);
|
|
7741
7741
|
const entityResult = await client.execute({
|
|
7742
7742
|
sql: "SELECT * FROM entities WHERE id = ?",
|
|
@@ -7761,7 +7761,7 @@ async function getConversationPartners(client, contactEntityId, since) {
|
|
|
7761
7761
|
}
|
|
7762
7762
|
async function getHotEntities(client, since, limit = 10) {
|
|
7763
7763
|
const sinceISO = since.toISOString();
|
|
7764
|
-
const
|
|
7764
|
+
const result3 = await client.execute({
|
|
7765
7765
|
sql: `SELECT entity_id, COUNT(*) as rel_count
|
|
7766
7766
|
FROM (
|
|
7767
7767
|
SELECT source_entity_id as entity_id FROM relationships WHERE timestamp >= ?
|
|
@@ -7774,7 +7774,7 @@ async function getHotEntities(client, since, limit = 10) {
|
|
|
7774
7774
|
args: [sinceISO, sinceISO, limit]
|
|
7775
7775
|
});
|
|
7776
7776
|
const hotEntities = [];
|
|
7777
|
-
for (const row of
|
|
7777
|
+
for (const row of result3.rows) {
|
|
7778
7778
|
const eid = String(row.entity_id);
|
|
7779
7779
|
const entityResult = await client.execute({
|
|
7780
7780
|
sql: "SELECT * FROM entities WHERE id = ?",
|
|
@@ -7821,7 +7821,7 @@ async function matchEntities(query, client) {
|
|
|
7821
7821
|
if (words.length === 0) return [];
|
|
7822
7822
|
try {
|
|
7823
7823
|
const matchExpr = words.map((w) => `${w}*`).join(" OR ");
|
|
7824
|
-
const
|
|
7824
|
+
const result3 = await client.execute({
|
|
7825
7825
|
sql: `SELECT e.id, e.name FROM entities e
|
|
7826
7826
|
JOIN entities_fts fts ON e.rowid = fts.rowid
|
|
7827
7827
|
WHERE entities_fts MATCH ?
|
|
@@ -7829,8 +7829,8 @@ async function matchEntities(query, client) {
|
|
|
7829
7829
|
LIMIT ?`,
|
|
7830
7830
|
args: [matchExpr, MAX_ENTITY_MATCHES]
|
|
7831
7831
|
});
|
|
7832
|
-
if (
|
|
7833
|
-
return
|
|
7832
|
+
if (result3.rows.length > 0) {
|
|
7833
|
+
return result3.rows.map((row) => ({
|
|
7834
7834
|
entityId: String(row.id),
|
|
7835
7835
|
name: String(row.name)
|
|
7836
7836
|
}));
|
|
@@ -7840,13 +7840,13 @@ async function matchEntities(query, client) {
|
|
|
7840
7840
|
const conditions = words.map(() => `LOWER(name) LIKE ?`);
|
|
7841
7841
|
const args = words.map((w) => `%${w}%`);
|
|
7842
7842
|
try {
|
|
7843
|
-
const
|
|
7843
|
+
const result3 = await client.execute({
|
|
7844
7844
|
sql: `SELECT id, name FROM entities
|
|
7845
7845
|
WHERE ${conditions.join(" OR ")}
|
|
7846
7846
|
LIMIT ?`,
|
|
7847
7847
|
args: [...args, MAX_ENTITY_MATCHES]
|
|
7848
7848
|
});
|
|
7849
|
-
return
|
|
7849
|
+
return result3.rows.map((row) => ({
|
|
7850
7850
|
entityId: String(row.id),
|
|
7851
7851
|
name: String(row.name)
|
|
7852
7852
|
}));
|
|
@@ -7859,12 +7859,12 @@ async function getLinkedMemories(entityIds, client) {
|
|
|
7859
7859
|
if (entityIds.length === 0) return linked;
|
|
7860
7860
|
const placeholders = entityIds.map(() => "?").join(",");
|
|
7861
7861
|
try {
|
|
7862
|
-
const
|
|
7862
|
+
const result3 = await client.execute({
|
|
7863
7863
|
sql: `SELECT entity_id, memory_id FROM entity_memories
|
|
7864
7864
|
WHERE entity_id IN (${placeholders})`,
|
|
7865
7865
|
args: entityIds
|
|
7866
7866
|
});
|
|
7867
|
-
for (const row of
|
|
7867
|
+
for (const row of result3.rows) {
|
|
7868
7868
|
const entityId2 = String(row.entity_id);
|
|
7869
7869
|
const memoryId = String(row.memory_id);
|
|
7870
7870
|
const entry = linked.get(entityId2) ?? {
|
|
@@ -7937,13 +7937,13 @@ async function applyHyperedgeBoost(entities, client, boostMap, resultIds) {
|
|
|
7937
7937
|
const entityIds = entities.map((e) => e.entityId);
|
|
7938
7938
|
const placeholders = entityIds.map(() => "?").join(",");
|
|
7939
7939
|
try {
|
|
7940
|
-
const
|
|
7940
|
+
const result3 = await client.execute({
|
|
7941
7941
|
sql: `SELECT hyperedge_id, entity_id FROM hyperedge_nodes
|
|
7942
7942
|
WHERE entity_id IN (${placeholders})`,
|
|
7943
7943
|
args: entityIds
|
|
7944
7944
|
});
|
|
7945
7945
|
const hyperedgeEntities = /* @__PURE__ */ new Map();
|
|
7946
|
-
for (const row of
|
|
7946
|
+
for (const row of result3.rows) {
|
|
7947
7947
|
const hid = String(row.hyperedge_id);
|
|
7948
7948
|
const eid = String(row.entity_id);
|
|
7949
7949
|
const set = hyperedgeEntities.get(hid) ?? /* @__PURE__ */ new Set();
|
|
@@ -8268,10 +8268,10 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
8268
8268
|
};
|
|
8269
8269
|
try {
|
|
8270
8270
|
const fs = await import("fs");
|
|
8271
|
-
const
|
|
8271
|
+
const path62 = await import("path");
|
|
8272
8272
|
const os25 = await import("os");
|
|
8273
|
-
const logPath =
|
|
8274
|
-
fs.mkdirSync(
|
|
8273
|
+
const logPath = path62.join(os25.homedir(), ".exe-os", "search-quality.jsonl");
|
|
8274
|
+
fs.mkdirSync(path62.dirname(logPath), { recursive: true });
|
|
8275
8275
|
fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
|
|
8276
8276
|
} catch {
|
|
8277
8277
|
}
|
|
@@ -8320,8 +8320,8 @@ async function estimateCardinality(agentId, options) {
|
|
|
8320
8320
|
}
|
|
8321
8321
|
sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
|
|
8322
8322
|
try {
|
|
8323
|
-
const
|
|
8324
|
-
return Number(
|
|
8323
|
+
const result3 = await client.execute({ sql, args });
|
|
8324
|
+
return Number(result3.rows[0]?.cnt) || 0;
|
|
8325
8325
|
} catch {
|
|
8326
8326
|
return 0;
|
|
8327
8327
|
}
|
|
@@ -8452,8 +8452,8 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
|
|
|
8452
8452
|
sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
|
|
8453
8453
|
sql += ` ORDER BY rank LIMIT ?`;
|
|
8454
8454
|
args.push(limit);
|
|
8455
|
-
const
|
|
8456
|
-
return
|
|
8455
|
+
const result3 = await client.execute({ sql, args });
|
|
8456
|
+
return result3.rows.map((row) => ({
|
|
8457
8457
|
id: row.id,
|
|
8458
8458
|
agent_id: row.agent_id,
|
|
8459
8459
|
agent_role: row.agent_role,
|
|
@@ -8568,8 +8568,8 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
8568
8568
|
}
|
|
8569
8569
|
sql += ` ORDER BY timestamp DESC LIMIT ?`;
|
|
8570
8570
|
args.push(limit);
|
|
8571
|
-
const
|
|
8572
|
-
const recentResults =
|
|
8571
|
+
const result3 = await client.execute({ sql, args });
|
|
8572
|
+
const recentResults = result3.rows.map((row) => rowToMemoryRecord(row));
|
|
8573
8573
|
if (sessionBoundaryMemories.length > 0) {
|
|
8574
8574
|
const seenIds = new Set(recentResults.map((r) => r.id));
|
|
8575
8575
|
for (const bm of sessionBoundaryMemories) {
|
|
@@ -8652,9 +8652,9 @@ async function trajectoryBypass(queryText, agentId, options, limit) {
|
|
|
8652
8652
|
}
|
|
8653
8653
|
sql += ` ORDER BY timestamp DESC LIMIT ?`;
|
|
8654
8654
|
args.push(limit);
|
|
8655
|
-
const
|
|
8656
|
-
if (
|
|
8657
|
-
return
|
|
8655
|
+
const result3 = await client.execute({ sql, args });
|
|
8656
|
+
if (result3.rows.length < 3) return null;
|
|
8657
|
+
return result3.rows.map((row) => ({
|
|
8658
8658
|
id: row.id,
|
|
8659
8659
|
agent_id: row.agent_id,
|
|
8660
8660
|
agent_role: row.agent_role,
|
|
@@ -9602,10 +9602,10 @@ function freeLicense() {
|
|
|
9602
9602
|
async function countActiveMemories() {
|
|
9603
9603
|
if (!isInitialized()) return 0;
|
|
9604
9604
|
const client = getClient();
|
|
9605
|
-
const
|
|
9605
|
+
const result3 = await client.execute(
|
|
9606
9606
|
"SELECT COUNT(*) as cnt FROM memories WHERE status = 'active' OR status IS NULL"
|
|
9607
9607
|
);
|
|
9608
|
-
const row =
|
|
9608
|
+
const row = result3.rows[0];
|
|
9609
9609
|
return Number(row?.cnt ?? 0);
|
|
9610
9610
|
}
|
|
9611
9611
|
async function assertMemoryLimit() {
|
|
@@ -9904,8 +9904,8 @@ __export(wiki_client_exports, {
|
|
|
9904
9904
|
listDocuments: () => listDocuments,
|
|
9905
9905
|
listWorkspaces: () => listWorkspaces
|
|
9906
9906
|
});
|
|
9907
|
-
async function wikiFetch(config2,
|
|
9908
|
-
const url = `${config2.baseUrl}/api/v1${
|
|
9907
|
+
async function wikiFetch(config2, path62, method = "GET", body) {
|
|
9908
|
+
const url = `${config2.baseUrl}/api/v1${path62}`;
|
|
9909
9909
|
const headers = {
|
|
9910
9910
|
Authorization: `Bearer ${config2.apiKey}`,
|
|
9911
9911
|
"Content-Type": "application/json"
|
|
@@ -9938,7 +9938,7 @@ async function wikiFetch(config2, path61, method = "GET", body) {
|
|
|
9938
9938
|
}
|
|
9939
9939
|
}
|
|
9940
9940
|
if (!response.ok) {
|
|
9941
|
-
throw new Error(`Wiki API ${method} ${
|
|
9941
|
+
throw new Error(`Wiki API ${method} ${path62}: ${response.status} ${response.statusText}`);
|
|
9942
9942
|
}
|
|
9943
9943
|
return response.json();
|
|
9944
9944
|
} finally {
|
|
@@ -10066,7 +10066,7 @@ async function searchConversations(query, limit) {
|
|
|
10066
10066
|
try {
|
|
10067
10067
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
10068
10068
|
const client = getClient2();
|
|
10069
|
-
const
|
|
10069
|
+
const result3 = await client.execute({
|
|
10070
10070
|
sql: `SELECT c.id, c.platform, c.sender_id, c.sender_name,
|
|
10071
10071
|
c.content_text, c.agent_response, c.agent_name, c.timestamp
|
|
10072
10072
|
FROM conversations c
|
|
@@ -10075,9 +10075,9 @@ async function searchConversations(query, limit) {
|
|
|
10075
10075
|
LIMIT ?`,
|
|
10076
10076
|
args: [query, limit]
|
|
10077
10077
|
});
|
|
10078
|
-
return
|
|
10078
|
+
return result3.rows.map((row, i) => ({
|
|
10079
10079
|
source: "conversations",
|
|
10080
|
-
score: 1 - i / Math.max(
|
|
10080
|
+
score: 1 - i / Math.max(result3.rows.length, 1),
|
|
10081
10081
|
timestamp: row.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10082
10082
|
snippet: truncate(
|
|
10083
10083
|
(row.content_text ?? "") + (row.agent_response ? ` \u2192 ${row.agent_response}` : ""),
|
|
@@ -10304,7 +10304,7 @@ function registerGetSessionContext(server) {
|
|
|
10304
10304
|
},
|
|
10305
10305
|
async ({ session_id, target_timestamp, window_size, max_chars, body_chars }) => {
|
|
10306
10306
|
const client = getClient();
|
|
10307
|
-
const
|
|
10307
|
+
const result3 = await client.execute({
|
|
10308
10308
|
sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
|
|
10309
10309
|
tool_name, project_name,
|
|
10310
10310
|
has_error, raw_text, vector, task_id
|
|
@@ -10314,7 +10314,7 @@ function registerGetSessionContext(server) {
|
|
|
10314
10314
|
LIMIT 500`,
|
|
10315
10315
|
args: [session_id]
|
|
10316
10316
|
});
|
|
10317
|
-
if (
|
|
10317
|
+
if (result3.rows.length === 0) {
|
|
10318
10318
|
return {
|
|
10319
10319
|
content: [
|
|
10320
10320
|
{
|
|
@@ -10324,7 +10324,7 @@ function registerGetSessionContext(server) {
|
|
|
10324
10324
|
]
|
|
10325
10325
|
};
|
|
10326
10326
|
}
|
|
10327
|
-
const sorted =
|
|
10327
|
+
const sorted = result3.rows.map((row) => ({
|
|
10328
10328
|
id: row.id,
|
|
10329
10329
|
agent_id: row.agent_id,
|
|
10330
10330
|
agent_role: row.agent_role,
|
|
@@ -10395,7 +10395,7 @@ function registerGetMemoryById(server) {
|
|
|
10395
10395
|
const canReadOtherAgent = agentRole === "COO" || agentRole === "CTO";
|
|
10396
10396
|
const ownerAgent = requestedAgent && canReadOtherAgent ? requestedAgent : agentId;
|
|
10397
10397
|
const client = getClient();
|
|
10398
|
-
const
|
|
10398
|
+
const result3 = await client.execute({
|
|
10399
10399
|
sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
|
|
10400
10400
|
tool_name, project_name, has_error, raw_text, task_id,
|
|
10401
10401
|
importance, status, memory_type, source_path, source_type
|
|
@@ -10404,14 +10404,14 @@ function registerGetMemoryById(server) {
|
|
|
10404
10404
|
LIMIT 1`,
|
|
10405
10405
|
args: [id, ownerAgent]
|
|
10406
10406
|
});
|
|
10407
|
-
if (
|
|
10407
|
+
if (result3.rows.length === 0) {
|
|
10408
10408
|
const extra = requestedAgent && !canReadOtherAgent ? " Non-COO/CTO agents may only fetch their own memories." : "";
|
|
10409
10409
|
return {
|
|
10410
10410
|
content: [{ type: "text", text: `No memory found for id '${id}'.${extra}` }],
|
|
10411
10411
|
isError: true
|
|
10412
10412
|
};
|
|
10413
10413
|
}
|
|
10414
|
-
const row =
|
|
10414
|
+
const row = result3.rows[0];
|
|
10415
10415
|
const lines = [
|
|
10416
10416
|
`id: ${asString(row.id)}`,
|
|
10417
10417
|
`agent_id: ${asString(row.agent_id)}`,
|
|
@@ -10464,7 +10464,7 @@ __export(consolidation_exports, {
|
|
|
10464
10464
|
});
|
|
10465
10465
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
10466
10466
|
async function selectUnconsolidated(client, limit = 200) {
|
|
10467
|
-
const
|
|
10467
|
+
const result3 = await client.execute({
|
|
10468
10468
|
sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
|
|
10469
10469
|
FROM memories
|
|
10470
10470
|
WHERE consolidated = 0
|
|
@@ -10472,7 +10472,7 @@ async function selectUnconsolidated(client, limit = 200) {
|
|
|
10472
10472
|
LIMIT ?`,
|
|
10473
10473
|
args: [limit]
|
|
10474
10474
|
});
|
|
10475
|
-
return
|
|
10475
|
+
return result3.rows.map((row) => ({
|
|
10476
10476
|
id: row.id,
|
|
10477
10477
|
agent_id: row.agent_id,
|
|
10478
10478
|
project_name: row.project_name,
|
|
@@ -10712,10 +10712,10 @@ async function runConsolidation(client, options) {
|
|
|
10712
10712
|
if (dedupCount > 0) clustersProcessed++;
|
|
10713
10713
|
continue;
|
|
10714
10714
|
}
|
|
10715
|
-
const
|
|
10715
|
+
const result3 = await storeConsolidation(client, cluster, synthesis, options.embedFn);
|
|
10716
10716
|
if (isCoordinator && options.wikiConfig) {
|
|
10717
10717
|
await pushToWiki(
|
|
10718
|
-
{ ...
|
|
10718
|
+
{ ...result3, projectName: cluster.projectName },
|
|
10719
10719
|
options.wikiConfig
|
|
10720
10720
|
).catch((err) => {
|
|
10721
10721
|
process.stderr.write(
|
|
@@ -10725,7 +10725,7 @@ async function runConsolidation(client, options) {
|
|
|
10725
10725
|
});
|
|
10726
10726
|
}
|
|
10727
10727
|
if (isCoordinator) {
|
|
10728
|
-
const sourceIds =
|
|
10728
|
+
const sourceIds = result3.sourceIds;
|
|
10729
10729
|
if (sourceIds.length > 0) {
|
|
10730
10730
|
const placeholders = sourceIds.map(() => "?").join(",");
|
|
10731
10731
|
await client.execute({
|
|
@@ -10795,26 +10795,26 @@ function cosineSimilarity(a, b) {
|
|
|
10795
10795
|
return denom === 0 ? 0 : dot / denom;
|
|
10796
10796
|
}
|
|
10797
10797
|
async function isUserIdle(client, idleMinutes = 30) {
|
|
10798
|
-
const
|
|
10798
|
+
const result3 = await client.execute({
|
|
10799
10799
|
sql: `SELECT MAX(timestamp) as last_activity
|
|
10800
10800
|
FROM memories
|
|
10801
10801
|
WHERE tool_name != 'consolidation'
|
|
10802
10802
|
AND timestamp >= datetime('now', '-1 day')`,
|
|
10803
10803
|
args: []
|
|
10804
10804
|
});
|
|
10805
|
-
const lastActivity =
|
|
10805
|
+
const lastActivity = result3.rows[0]?.last_activity;
|
|
10806
10806
|
if (!lastActivity) return true;
|
|
10807
10807
|
const lastMs = new Date(lastActivity).getTime();
|
|
10808
10808
|
const now2 = Date.now();
|
|
10809
10809
|
return now2 - lastMs >= idleMinutes * 60 * 1e3;
|
|
10810
10810
|
}
|
|
10811
10811
|
async function countUnconsolidated(client) {
|
|
10812
|
-
const
|
|
10812
|
+
const result3 = await client.execute({
|
|
10813
10813
|
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
10814
10814
|
WHERE consolidated = 0`,
|
|
10815
10815
|
args: []
|
|
10816
10816
|
});
|
|
10817
|
-
return Number(
|
|
10817
|
+
return Number(result3.rows[0]?.cnt ?? 0);
|
|
10818
10818
|
}
|
|
10819
10819
|
var ROLE_PROMPTS, DEFAULT_ROLE_PROMPT, WIKI_FETCH_TIMEOUT_MS;
|
|
10820
10820
|
var init_consolidation = __esm({
|
|
@@ -10883,12 +10883,12 @@ function registerConsolidateMemories(server) {
|
|
|
10883
10883
|
embedFn = embed2;
|
|
10884
10884
|
} catch {
|
|
10885
10885
|
}
|
|
10886
|
-
const
|
|
10886
|
+
const result3 = await runConsolidation2(client, {
|
|
10887
10887
|
model: consolidationModel,
|
|
10888
10888
|
maxCalls: max_clusters,
|
|
10889
10889
|
embedFn
|
|
10890
10890
|
});
|
|
10891
|
-
if (
|
|
10891
|
+
if (result3.clustersProcessed === 0) {
|
|
10892
10892
|
return {
|
|
10893
10893
|
content: [{
|
|
10894
10894
|
type: "text",
|
|
@@ -10900,8 +10900,8 @@ function registerConsolidateMemories(server) {
|
|
|
10900
10900
|
content: [{
|
|
10901
10901
|
type: "text",
|
|
10902
10902
|
text: `Consolidation complete:
|
|
10903
|
-
- Clusters processed: ${
|
|
10904
|
-
- Memories consolidated: ${
|
|
10903
|
+
- Clusters processed: ${result3.clustersProcessed}
|
|
10904
|
+
- Memories consolidated: ${result3.memoriesConsolidated}
|
|
10905
10905
|
|
|
10906
10906
|
Consolidated summaries stored as tier-1 (importance=9) memories.`
|
|
10907
10907
|
}]
|
|
@@ -11433,12 +11433,12 @@ var init_tmux_transport = __esm({
|
|
|
11433
11433
|
}
|
|
11434
11434
|
isPaneInCopyMode(target) {
|
|
11435
11435
|
try {
|
|
11436
|
-
const
|
|
11436
|
+
const result3 = execFileSync(
|
|
11437
11437
|
"tmux",
|
|
11438
11438
|
["display-message", "-p", "-t", target, "#{pane_in_mode}"],
|
|
11439
11439
|
{ ...QUIET, timeout: 3e3 }
|
|
11440
11440
|
).trim();
|
|
11441
|
-
return
|
|
11441
|
+
return result3 === "1";
|
|
11442
11442
|
} catch {
|
|
11443
11443
|
return false;
|
|
11444
11444
|
}
|
|
@@ -11800,11 +11800,11 @@ async function recordSessionKill(input) {
|
|
|
11800
11800
|
async function countKillsSince(sinceISO) {
|
|
11801
11801
|
try {
|
|
11802
11802
|
const client = getClient();
|
|
11803
|
-
const
|
|
11803
|
+
const result3 = await client.execute({
|
|
11804
11804
|
sql: `SELECT COUNT(*) AS n FROM session_kills WHERE killed_at >= ?`,
|
|
11805
11805
|
args: [sinceISO]
|
|
11806
11806
|
});
|
|
11807
|
-
const row =
|
|
11807
|
+
const row = result3.rows[0];
|
|
11808
11808
|
return row ? Number(row.n) : 0;
|
|
11809
11809
|
} catch {
|
|
11810
11810
|
return 0;
|
|
@@ -11838,13 +11838,13 @@ function computeIdleKillSuspectStreak(prev, killsToday, liveSessions, todayDate)
|
|
|
11838
11838
|
async function sumTokensSavedSince(sinceISO) {
|
|
11839
11839
|
try {
|
|
11840
11840
|
const client = getClient();
|
|
11841
|
-
const
|
|
11841
|
+
const result3 = await client.execute({
|
|
11842
11842
|
sql: `SELECT COALESCE(SUM(estimated_tokens_saved), 0) AS total
|
|
11843
11843
|
FROM session_kills
|
|
11844
11844
|
WHERE killed_at >= ?`,
|
|
11845
11845
|
args: [sinceISO]
|
|
11846
11846
|
});
|
|
11847
|
-
const row =
|
|
11847
|
+
const row = result3.rows[0];
|
|
11848
11848
|
return row ? Number(row.total) : 0;
|
|
11849
11849
|
} catch {
|
|
11850
11850
|
return 0;
|
|
@@ -11939,13 +11939,13 @@ function _resetLastRelaunchCache() {
|
|
|
11939
11939
|
async function lastResumeCreatedAtMs(agentId) {
|
|
11940
11940
|
const client = getClient();
|
|
11941
11941
|
const cmScope = sessionScopeFilter(null);
|
|
11942
|
-
const
|
|
11942
|
+
const result3 = await client.execute({
|
|
11943
11943
|
sql: `SELECT MAX(created_at) AS last_created_at
|
|
11944
11944
|
FROM tasks
|
|
11945
11945
|
WHERE assigned_to = ? AND title LIKE ?${cmScope.sql}`,
|
|
11946
11946
|
args: [agentId, `${RESUME_TITLE_PREFIX} %`, ...cmScope.args]
|
|
11947
11947
|
});
|
|
11948
|
-
const raw =
|
|
11948
|
+
const raw = result3.rows[0]?.last_created_at;
|
|
11949
11949
|
if (raw === null || raw === void 0) return null;
|
|
11950
11950
|
const parsed = Date.parse(String(raw));
|
|
11951
11951
|
return Number.isNaN(parsed) ? null : parsed;
|
|
@@ -12182,37 +12182,37 @@ async function countPendingReviews(sessionScope) {
|
|
|
12182
12182
|
const scope = strictSessionScopeFilter(
|
|
12183
12183
|
sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
|
|
12184
12184
|
);
|
|
12185
|
-
const
|
|
12185
|
+
const result3 = await client.execute({
|
|
12186
12186
|
sql: `SELECT COUNT(*) as cnt FROM tasks
|
|
12187
12187
|
WHERE status = 'needs_review'${scope.sql}`,
|
|
12188
12188
|
args: [...scope.args]
|
|
12189
12189
|
});
|
|
12190
|
-
return Number(
|
|
12190
|
+
return Number(result3.rows[0]?.cnt) || 0;
|
|
12191
12191
|
}
|
|
12192
12192
|
async function countNewPendingReviewsSince(sinceIso, sessionScope) {
|
|
12193
12193
|
const client = getClient();
|
|
12194
12194
|
const scope = strictSessionScopeFilter(
|
|
12195
12195
|
sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
|
|
12196
12196
|
);
|
|
12197
|
-
const
|
|
12197
|
+
const result3 = await client.execute({
|
|
12198
12198
|
sql: `SELECT COUNT(*) as cnt FROM tasks
|
|
12199
12199
|
WHERE status = 'needs_review' AND updated_at > ?${scope.sql}`,
|
|
12200
12200
|
args: [sinceIso, ...scope.args]
|
|
12201
12201
|
});
|
|
12202
|
-
return Number(
|
|
12202
|
+
return Number(result3.rows[0]?.cnt) || 0;
|
|
12203
12203
|
}
|
|
12204
12204
|
async function listPendingReviews(limit, sessionScope) {
|
|
12205
12205
|
const client = getClient();
|
|
12206
12206
|
const scope = strictSessionScopeFilter(
|
|
12207
12207
|
sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
|
|
12208
12208
|
);
|
|
12209
|
-
const
|
|
12209
|
+
const result3 = await client.execute({
|
|
12210
12210
|
sql: `SELECT title, assigned_to, project_name, updated_at FROM tasks
|
|
12211
12211
|
WHERE status = 'needs_review'${scope.sql}
|
|
12212
12212
|
ORDER BY updated_at ASC LIMIT ?`,
|
|
12213
12213
|
args: [...scope.args, limit]
|
|
12214
12214
|
});
|
|
12215
|
-
return
|
|
12215
|
+
return result3.rows;
|
|
12216
12216
|
}
|
|
12217
12217
|
async function cleanupOrphanedReviews() {
|
|
12218
12218
|
const client = getClient();
|
|
@@ -12297,7 +12297,7 @@ function getReviewChecklist(role, agent, taskSlug) {
|
|
|
12297
12297
|
]
|
|
12298
12298
|
};
|
|
12299
12299
|
}
|
|
12300
|
-
async function createReviewForCompletedTask(row,
|
|
12300
|
+
async function createReviewForCompletedTask(row, result3, _baseDir, now2) {
|
|
12301
12301
|
const taskFile = String(row.task_file);
|
|
12302
12302
|
const employees = await loadEmployees();
|
|
12303
12303
|
const coordinatorName = getCoordinatorName(employees);
|
|
@@ -12342,7 +12342,7 @@ async function createReviewForCompletedTask(row, result2, _baseDir, now2) {
|
|
|
12342
12342
|
"- **Needs work:** re-open with notes"
|
|
12343
12343
|
].join("\n");
|
|
12344
12344
|
const originalTaskId = String(row.id);
|
|
12345
|
-
const updatedResult = (
|
|
12345
|
+
const updatedResult = (result3 ?? "No result summary provided") + reviewNotes;
|
|
12346
12346
|
await client.execute({
|
|
12347
12347
|
sql: `UPDATE tasks SET result = ?, status = 'needs_review', updated_at = ?
|
|
12348
12348
|
WHERE id = ?`,
|
|
@@ -12364,7 +12364,7 @@ async function createReviewForCompletedTask(row, result2, _baseDir, now2) {
|
|
|
12364
12364
|
taskFile
|
|
12365
12365
|
});
|
|
12366
12366
|
const originalPriority = String(row.priority).toLowerCase();
|
|
12367
|
-
const autoApprove = originalPriority === "p2" &&
|
|
12367
|
+
const autoApprove = originalPriority === "p2" && result3?.toLowerCase().includes("tests pass");
|
|
12368
12368
|
if (!autoApprove) {
|
|
12369
12369
|
try {
|
|
12370
12370
|
const key = getSessionKey();
|
|
@@ -12393,11 +12393,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
12393
12393
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
12394
12394
|
const parentId = row.parent_task_id ? String(row.parent_task_id) : null;
|
|
12395
12395
|
if (parentId) {
|
|
12396
|
-
const
|
|
12396
|
+
const result3 = await client.execute({
|
|
12397
12397
|
sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE id = ? AND status = 'needs_review'",
|
|
12398
12398
|
args: [now2, parentId]
|
|
12399
12399
|
});
|
|
12400
|
-
if (
|
|
12400
|
+
if (result3.rowsAffected > 0) {
|
|
12401
12401
|
process.stderr.write(
|
|
12402
12402
|
`[review-cleanup] Cascaded original task to done via parent_task_id: ${parentId}
|
|
12403
12403
|
`
|
|
@@ -12411,11 +12411,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
12411
12411
|
const agent = parts[1];
|
|
12412
12412
|
const slug = parts.slice(2).join("-");
|
|
12413
12413
|
const legacyTaskFile = `exe/${agent}/${slug}.md`;
|
|
12414
|
-
const
|
|
12414
|
+
const result3 = await client.execute({
|
|
12415
12415
|
sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE (task_file = ? OR task_file LIKE ?) AND status = 'needs_review'",
|
|
12416
12416
|
args: [now2, legacyTaskFile, `tasks/%/${agent}/${slug}.md`]
|
|
12417
12417
|
});
|
|
12418
|
-
if (
|
|
12418
|
+
if (result3.rowsAffected > 0) {
|
|
12419
12419
|
process.stderr.write(
|
|
12420
12420
|
`[review-cleanup] Cascaded original task to done: ${agent}/${slug}.md
|
|
12421
12421
|
`
|
|
@@ -12865,8 +12865,8 @@ function notifyParentExe(sessionKey) {
|
|
|
12865
12865
|
}
|
|
12866
12866
|
process.stderr.write(`[intercom] notifyParentExe \u2192 ${target}
|
|
12867
12867
|
`);
|
|
12868
|
-
const
|
|
12869
|
-
if (
|
|
12868
|
+
const result3 = sendIntercom(target);
|
|
12869
|
+
if (result3 === "failed") {
|
|
12870
12870
|
const rootExe = resolveExeSession();
|
|
12871
12871
|
if (rootExe && rootExe !== target) {
|
|
12872
12872
|
process.stderr.write(`[intercom] notifyParentExe: dispatcher ${target} dead, falling back to root coordinator session ${rootExe}
|
|
@@ -12956,19 +12956,19 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12956
12956
|
}
|
|
12957
12957
|
const sessionName = employeeSessionName(employeeName, exeSession, effectiveInstance);
|
|
12958
12958
|
if (isEmployeeAlive(sessionName)) {
|
|
12959
|
-
const
|
|
12960
|
-
if (
|
|
12959
|
+
const result4 = sendIntercom(sessionName);
|
|
12960
|
+
if (result4 === "acknowledged" || result4 === "skipped_exe" || result4 === "debounced" || result4 === "queued") {
|
|
12961
12961
|
return { status: "intercom_sent", sessionName };
|
|
12962
12962
|
}
|
|
12963
|
-
if (
|
|
12963
|
+
if (result4 === "delivered") {
|
|
12964
12964
|
return { status: "intercom_unprocessed", sessionName };
|
|
12965
12965
|
}
|
|
12966
12966
|
return { status: "failed", sessionName, error: "intercom delivery failed" };
|
|
12967
12967
|
}
|
|
12968
12968
|
const spawnOpts = { ...opts, instance: effectiveInstance };
|
|
12969
|
-
const
|
|
12970
|
-
if (
|
|
12971
|
-
return { status: "failed", sessionName, error:
|
|
12969
|
+
const result3 = spawnEmployee(employeeName, exeSession, projectDir, spawnOpts);
|
|
12970
|
+
if (result3.error) {
|
|
12971
|
+
return { status: "failed", sessionName, error: result3.error };
|
|
12972
12972
|
}
|
|
12973
12973
|
return { status: "spawned", sessionName };
|
|
12974
12974
|
}
|
|
@@ -13474,11 +13474,11 @@ async function writeCheckpoint(input) {
|
|
|
13474
13474
|
blocked_by_ids: blockedByIds,
|
|
13475
13475
|
last_checkpoint_at: now2
|
|
13476
13476
|
};
|
|
13477
|
-
const
|
|
13477
|
+
const result3 = await client.execute({
|
|
13478
13478
|
sql: `UPDATE tasks SET checkpoint = ?, checkpoint_count = checkpoint_count + 1, updated_at = ? WHERE id = ?`,
|
|
13479
13479
|
args: [JSON.stringify(checkpoint), now2, taskId]
|
|
13480
13480
|
});
|
|
13481
|
-
if (
|
|
13481
|
+
if (result3.rowsAffected === 0) {
|
|
13482
13482
|
throw new Error(`Checkpoint write failed: task ${taskId} not found`);
|
|
13483
13483
|
}
|
|
13484
13484
|
const countResult = await client.execute({
|
|
@@ -13529,22 +13529,22 @@ function checkLaneAffinity(title, context, assigneeName) {
|
|
|
13529
13529
|
}
|
|
13530
13530
|
async function resolveTask(client, identifier, scopeSession) {
|
|
13531
13531
|
const scope = sessionScopeFilter(scopeSession);
|
|
13532
|
-
let
|
|
13532
|
+
let result3 = await client.execute({
|
|
13533
13533
|
sql: `SELECT * FROM tasks WHERE id = ?${scope.sql}`,
|
|
13534
13534
|
args: [identifier, ...scope.args]
|
|
13535
13535
|
});
|
|
13536
|
-
if (
|
|
13537
|
-
|
|
13536
|
+
if (result3.rows.length === 1) return result3.rows[0];
|
|
13537
|
+
result3 = await client.execute({
|
|
13538
13538
|
sql: `SELECT * FROM tasks WHERE task_file LIKE ?${scope.sql}`,
|
|
13539
13539
|
args: [`%${identifier}%`, ...scope.args]
|
|
13540
13540
|
});
|
|
13541
|
-
if (
|
|
13542
|
-
if (
|
|
13543
|
-
const exact =
|
|
13541
|
+
if (result3.rows.length === 1) return result3.rows[0];
|
|
13542
|
+
if (result3.rows.length > 1) {
|
|
13543
|
+
const exact = result3.rows.filter(
|
|
13544
13544
|
(r) => String(r.task_file).endsWith(`/${identifier}.md`)
|
|
13545
13545
|
);
|
|
13546
13546
|
if (exact.length === 1) return exact[0];
|
|
13547
|
-
const candidates = exact.length > 1 ? exact :
|
|
13547
|
+
const candidates = exact.length > 1 ? exact : result3.rows;
|
|
13548
13548
|
const active = candidates.filter(
|
|
13549
13549
|
(r) => !["done", "cancelled"].includes(String(r.status))
|
|
13550
13550
|
);
|
|
@@ -13554,17 +13554,17 @@ async function resolveTask(client, identifier, scopeSession) {
|
|
|
13554
13554
|
`Multiple tasks match "${identifier}": ${matches}. Use a UUID to disambiguate.`
|
|
13555
13555
|
);
|
|
13556
13556
|
}
|
|
13557
|
-
|
|
13557
|
+
result3 = await client.execute({
|
|
13558
13558
|
sql: `SELECT * FROM tasks WHERE title LIKE ?${scope.sql}`,
|
|
13559
13559
|
args: [`%${identifier}%`, ...scope.args]
|
|
13560
13560
|
});
|
|
13561
|
-
if (
|
|
13562
|
-
if (
|
|
13563
|
-
const active =
|
|
13561
|
+
if (result3.rows.length === 1) return result3.rows[0];
|
|
13562
|
+
if (result3.rows.length > 1) {
|
|
13563
|
+
const active = result3.rows.filter(
|
|
13564
13564
|
(r) => !["done", "cancelled"].includes(String(r.status))
|
|
13565
13565
|
);
|
|
13566
13566
|
if (active.length === 1) return active[0];
|
|
13567
|
-
const matches = (active.length > 1 ? active :
|
|
13567
|
+
const matches = (active.length > 1 ? active : result3.rows).map((r) => `"${String(r.title)}" (${String(r.status)}, ${String(r.id)})`).join(", ");
|
|
13568
13568
|
throw new Error(
|
|
13569
13569
|
`Multiple tasks match "${identifier}": ${matches}. Use a UUID to disambiguate.`
|
|
13570
13570
|
);
|
|
@@ -13774,11 +13774,11 @@ async function listTasks(input) {
|
|
|
13774
13774
|
args.push(...scope.args);
|
|
13775
13775
|
}
|
|
13776
13776
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
13777
|
-
const
|
|
13777
|
+
const result3 = await client.execute({
|
|
13778
13778
|
sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
|
|
13779
13779
|
args
|
|
13780
13780
|
});
|
|
13781
|
-
return
|
|
13781
|
+
return result3.rows.map((r) => ({
|
|
13782
13782
|
id: String(r.id),
|
|
13783
13783
|
title: String(r.title),
|
|
13784
13784
|
assignedTo: String(r.assigned_to),
|
|
@@ -14170,30 +14170,30 @@ async function dispatchTaskToEmployee(input) {
|
|
|
14170
14170
|
if (!exeSession) return { dispatched: "session_missing" };
|
|
14171
14171
|
const sessionName = employeeSessionName(input.assignedTo, exeSession);
|
|
14172
14172
|
if (transport.isAlive(sessionName)) {
|
|
14173
|
-
const
|
|
14174
|
-
const dispatched =
|
|
14173
|
+
const result3 = sendIntercom(sessionName);
|
|
14174
|
+
const dispatched = result3 === "acknowledged" || result3 === "debounced" || result3 === "queued" ? "verified" : result3 === "delivered" ? "sent_unverified" : "session_dead";
|
|
14175
14175
|
process.stderr.write(
|
|
14176
|
-
`[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${
|
|
14176
|
+
`[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${result3})
|
|
14177
14177
|
`
|
|
14178
14178
|
);
|
|
14179
14179
|
return { dispatched, session: sessionName, crossProject };
|
|
14180
14180
|
} else {
|
|
14181
14181
|
const projectDir = input.projectDir ?? process.cwd();
|
|
14182
|
-
const
|
|
14182
|
+
const result3 = ensureEmployee(input.assignedTo, exeSession, projectDir, {
|
|
14183
14183
|
autoInstance: isMultiInstance(input.assignedTo)
|
|
14184
14184
|
});
|
|
14185
|
-
if (
|
|
14185
|
+
if (result3.status === "failed") {
|
|
14186
14186
|
process.stderr.write(
|
|
14187
|
-
`[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${
|
|
14187
|
+
`[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result3.error}
|
|
14188
14188
|
`
|
|
14189
14189
|
);
|
|
14190
14190
|
return { dispatched: "session_missing" };
|
|
14191
14191
|
}
|
|
14192
14192
|
process.stderr.write(
|
|
14193
|
-
`[dispatch-audit] SPAWNED \u2192 ${
|
|
14193
|
+
`[dispatch-audit] SPAWNED \u2192 ${result3.sessionName} | task="${input.title}" [${input.priority}]
|
|
14194
14194
|
`
|
|
14195
14195
|
);
|
|
14196
|
-
return { dispatched: "spawned", session:
|
|
14196
|
+
return { dispatched: "spawned", session: result3.sessionName, crossProject };
|
|
14197
14197
|
}
|
|
14198
14198
|
} catch {
|
|
14199
14199
|
return { dispatched: "session_missing" };
|
|
@@ -14251,13 +14251,13 @@ async function storeBehavior(opts) {
|
|
|
14251
14251
|
}
|
|
14252
14252
|
async function listBehaviorsByDomain(agentId, domain) {
|
|
14253
14253
|
const client = getClient();
|
|
14254
|
-
const
|
|
14254
|
+
const result3 = await client.execute({
|
|
14255
14255
|
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
|
|
14256
14256
|
FROM behaviors
|
|
14257
14257
|
WHERE agent_id = ? AND domain = ? AND active = 1`,
|
|
14258
14258
|
args: [agentId, domain]
|
|
14259
14259
|
});
|
|
14260
|
-
return
|
|
14260
|
+
return result3.rows.map((r) => ({
|
|
14261
14261
|
id: String(r.id),
|
|
14262
14262
|
agent_id: String(r.agent_id),
|
|
14263
14263
|
project_name: r.project_name ? String(r.project_name) : null,
|
|
@@ -14272,11 +14272,11 @@ async function listBehaviorsByDomain(agentId, domain) {
|
|
|
14272
14272
|
}
|
|
14273
14273
|
async function deactivateBehavior(id) {
|
|
14274
14274
|
const client = getClient();
|
|
14275
|
-
const
|
|
14275
|
+
const result3 = await client.execute({
|
|
14276
14276
|
sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
|
|
14277
14277
|
args: [(/* @__PURE__ */ new Date()).toISOString(), id]
|
|
14278
14278
|
});
|
|
14279
|
-
return (
|
|
14279
|
+
return (result3.rowsAffected ?? 0) > 0;
|
|
14280
14280
|
}
|
|
14281
14281
|
var init_behaviors = __esm({
|
|
14282
14282
|
"src/lib/behaviors.ts"() {
|
|
@@ -14301,15 +14301,15 @@ __export(skill_learning_exports, {
|
|
|
14301
14301
|
import crypto10 from "crypto";
|
|
14302
14302
|
async function extractTrajectory(taskId, agentId) {
|
|
14303
14303
|
const client = getClient();
|
|
14304
|
-
const
|
|
14304
|
+
const result3 = await client.execute({
|
|
14305
14305
|
sql: `SELECT tool_name, raw_text
|
|
14306
14306
|
FROM memories
|
|
14307
14307
|
WHERE task_id = ? AND agent_id = ?
|
|
14308
14308
|
ORDER BY timestamp ASC`,
|
|
14309
14309
|
args: [taskId, agentId]
|
|
14310
14310
|
});
|
|
14311
|
-
if (
|
|
14312
|
-
const rawTools =
|
|
14311
|
+
if (result3.rows.length === 0) return [];
|
|
14312
|
+
const rawTools = result3.rows.map((r) => {
|
|
14313
14313
|
const toolName = String(r.tool_name);
|
|
14314
14314
|
if (toolName === "Bash") {
|
|
14315
14315
|
const text3 = String(r.raw_text);
|
|
@@ -14354,7 +14354,7 @@ async function storeTrajectory(opts) {
|
|
|
14354
14354
|
async function findSimilarTrajectories(signature, threshold = DEFAULT_SKILL_THRESHOLD) {
|
|
14355
14355
|
const client = getClient();
|
|
14356
14356
|
const hash = hashSignature(signature);
|
|
14357
|
-
const
|
|
14357
|
+
const result3 = await client.execute({
|
|
14358
14358
|
sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, skill_id, created_at
|
|
14359
14359
|
FROM trajectories
|
|
14360
14360
|
WHERE signature_hash = ?
|
|
@@ -14374,7 +14374,7 @@ async function findSimilarTrajectories(signature, threshold = DEFAULT_SKILL_THRE
|
|
|
14374
14374
|
skillId: r.skill_id ? String(r.skill_id) : null,
|
|
14375
14375
|
createdAt: String(r.created_at)
|
|
14376
14376
|
});
|
|
14377
|
-
const matches =
|
|
14377
|
+
const matches = result3.rows.map(mapRow);
|
|
14378
14378
|
if (matches.length >= threshold) return matches;
|
|
14379
14379
|
const nearResult = await client.execute({
|
|
14380
14380
|
sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, skill_id, created_at
|
|
@@ -14504,7 +14504,7 @@ async function sweepTrajectories(threshold, model) {
|
|
|
14504
14504
|
if (!config2.skillLearning) return { clustersProcessed: 0, skillsExtracted: 0 };
|
|
14505
14505
|
const t = threshold ?? config2.skillThreshold;
|
|
14506
14506
|
const client = getClient();
|
|
14507
|
-
const
|
|
14507
|
+
const result3 = await client.execute({
|
|
14508
14508
|
sql: `SELECT signature_hash, COUNT(*) as cnt
|
|
14509
14509
|
FROM trajectories
|
|
14510
14510
|
WHERE skill_id IS NULL
|
|
@@ -14516,7 +14516,7 @@ async function sweepTrajectories(threshold, model) {
|
|
|
14516
14516
|
});
|
|
14517
14517
|
let clustersProcessed = 0;
|
|
14518
14518
|
let skillsExtracted = 0;
|
|
14519
|
-
for (const row of
|
|
14519
|
+
for (const row of result3.rows) {
|
|
14520
14520
|
const hash = String(row.signature_hash);
|
|
14521
14521
|
const trajResult = await client.execute({
|
|
14522
14522
|
sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, created_at
|
|
@@ -14599,18 +14599,18 @@ __export(tasks_exports, {
|
|
|
14599
14599
|
import path29 from "path";
|
|
14600
14600
|
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, unlinkSync as unlinkSync8 } from "fs";
|
|
14601
14601
|
async function createTask(input) {
|
|
14602
|
-
const
|
|
14603
|
-
if (!input.skipDispatch &&
|
|
14602
|
+
const result3 = await createTaskCore(input);
|
|
14603
|
+
if (!input.skipDispatch && result3.status !== "blocked" && !process.env.VITEST) {
|
|
14604
14604
|
dispatchTaskToEmployee({
|
|
14605
14605
|
assignedTo: input.assignedTo,
|
|
14606
14606
|
title: input.title,
|
|
14607
14607
|
priority: input.priority,
|
|
14608
|
-
taskFile:
|
|
14609
|
-
initialStatus:
|
|
14608
|
+
taskFile: result3.taskFile,
|
|
14609
|
+
initialStatus: result3.status,
|
|
14610
14610
|
projectName: input.projectName
|
|
14611
14611
|
});
|
|
14612
14612
|
}
|
|
14613
|
-
return
|
|
14613
|
+
return result3;
|
|
14614
14614
|
}
|
|
14615
14615
|
async function updateTask(input) {
|
|
14616
14616
|
const { row, taskFile, now: now2, taskId } = await updateTaskStatus(input);
|
|
@@ -15516,10 +15516,10 @@ function registerCreateTask(server) {
|
|
|
15516
15516
|
skipDispatch: true
|
|
15517
15517
|
});
|
|
15518
15518
|
try {
|
|
15519
|
-
const { existsSync:
|
|
15519
|
+
const { existsSync: existsSync48, mkdirSync: mkdirSync26, writeFileSync: writeFileSync30 } = await import("fs");
|
|
15520
15520
|
const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
15521
15521
|
const idPath = identityPath2(assigned_to);
|
|
15522
|
-
if (!
|
|
15522
|
+
if (!existsSync48(idPath)) {
|
|
15523
15523
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15524
15524
|
const employees = await loadEmployees2();
|
|
15525
15525
|
const emp = employees.find((e) => e.name === assigned_to);
|
|
@@ -15528,7 +15528,7 @@ function registerCreateTask(server) {
|
|
|
15528
15528
|
const template = getTemplateForTitle2(emp.role);
|
|
15529
15529
|
if (template) {
|
|
15530
15530
|
const dir = (await import("path")).dirname(idPath);
|
|
15531
|
-
if (!
|
|
15531
|
+
if (!existsSync48(dir)) mkdirSync26(dir, { recursive: true });
|
|
15532
15532
|
writeFileSync30(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
|
|
15533
15533
|
}
|
|
15534
15534
|
}
|
|
@@ -15544,22 +15544,22 @@ function registerCreateTask(server) {
|
|
|
15544
15544
|
const useAutoInstance = isMultiInstance2(assigned_to);
|
|
15545
15545
|
const { loadConfigSync: loadConfigSync2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
15546
15546
|
const cfg = loadConfigSync2();
|
|
15547
|
-
const
|
|
15547
|
+
const result3 = ensureEmployee(assigned_to, exeSession, process.cwd(), {
|
|
15548
15548
|
autoInstance: useAutoInstance,
|
|
15549
15549
|
maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0
|
|
15550
15550
|
});
|
|
15551
|
-
switch (
|
|
15551
|
+
switch (result3.status) {
|
|
15552
15552
|
case "intercom_sent":
|
|
15553
15553
|
dispatchStatus = `
|
|
15554
|
-
Dispatched: intercom sent to ${
|
|
15554
|
+
Dispatched: intercom sent to ${result3.sessionName}`;
|
|
15555
15555
|
break;
|
|
15556
15556
|
case "spawned":
|
|
15557
15557
|
dispatchStatus = `
|
|
15558
|
-
Dispatched: spawned ${
|
|
15558
|
+
Dispatched: spawned ${result3.sessionName}`;
|
|
15559
15559
|
break;
|
|
15560
15560
|
case "failed":
|
|
15561
15561
|
dispatchStatus = `
|
|
15562
|
-
Dispatch failed: ${
|
|
15562
|
+
Dispatch failed: ${result3.error ?? "unknown"}`;
|
|
15563
15563
|
break;
|
|
15564
15564
|
}
|
|
15565
15565
|
}
|
|
@@ -15614,7 +15614,7 @@ function registerListTasks(server) {
|
|
|
15614
15614
|
priority: z13.enum(["p0", "p1", "p2"]).optional().describe("Filter by priority")
|
|
15615
15615
|
}
|
|
15616
15616
|
},
|
|
15617
|
-
async ({ assigned_to, status, project_name, priority }) => {
|
|
15617
|
+
async ({ assigned_to, status: status2, project_name, priority }) => {
|
|
15618
15618
|
try {
|
|
15619
15619
|
let resolvedProject;
|
|
15620
15620
|
if (project_name === "all") {
|
|
@@ -15628,7 +15628,7 @@ function registerListTasks(server) {
|
|
|
15628
15628
|
}
|
|
15629
15629
|
const tasks = await listTasks({
|
|
15630
15630
|
assignedTo: assigned_to,
|
|
15631
|
-
status,
|
|
15631
|
+
status: status2,
|
|
15632
15632
|
projectName: resolvedProject,
|
|
15633
15633
|
priority
|
|
15634
15634
|
});
|
|
@@ -15688,7 +15688,7 @@ async function diagnoseMissingTask(client, identifier) {
|
|
|
15688
15688
|
args.push(`%${identifier}%`);
|
|
15689
15689
|
clauses.push("title LIKE ?");
|
|
15690
15690
|
args.push(`%${identifier}%`);
|
|
15691
|
-
const
|
|
15691
|
+
const result3 = await client.execute({
|
|
15692
15692
|
sql: `SELECT id, title, status, assigned_to, project_name, session_scope, task_file
|
|
15693
15693
|
FROM tasks
|
|
15694
15694
|
WHERE ${clauses.map((c) => `(${c})`).join(" OR ")}
|
|
@@ -15696,10 +15696,10 @@ async function diagnoseMissingTask(client, identifier) {
|
|
|
15696
15696
|
LIMIT 10`,
|
|
15697
15697
|
args
|
|
15698
15698
|
});
|
|
15699
|
-
if (
|
|
15699
|
+
if (result3.rows.length === 0) return null;
|
|
15700
15700
|
const scoped = sessionScopeFilter();
|
|
15701
15701
|
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.";
|
|
15702
|
-
const matches =
|
|
15702
|
+
const matches = result3.rows.map((r) => {
|
|
15703
15703
|
const id = String(r.id);
|
|
15704
15704
|
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")}`;
|
|
15705
15705
|
}).join("\n");
|
|
@@ -15846,9 +15846,9 @@ function registerUpdateTask(server) {
|
|
|
15846
15846
|
result: z15.string().optional().describe("Result summary (include when status=done)")
|
|
15847
15847
|
}
|
|
15848
15848
|
},
|
|
15849
|
-
async ({ task_id, status: rawStatus, result:
|
|
15850
|
-
let
|
|
15851
|
-
if (
|
|
15849
|
+
async ({ task_id, status: rawStatus, result: result3 }) => {
|
|
15850
|
+
let status2 = rawStatus;
|
|
15851
|
+
if (status2 === "done") {
|
|
15852
15852
|
try {
|
|
15853
15853
|
const { getActiveAgent: getActiveAgent2 } = await Promise.resolve().then(() => (init_active_agent(), active_agent_exports));
|
|
15854
15854
|
const agent = getActiveAgent2();
|
|
@@ -15863,13 +15863,13 @@ function registerUpdateTask(server) {
|
|
|
15863
15863
|
} catch {
|
|
15864
15864
|
}
|
|
15865
15865
|
if (!isOwnReview) {
|
|
15866
|
-
|
|
15866
|
+
status2 = "needs_review";
|
|
15867
15867
|
}
|
|
15868
15868
|
}
|
|
15869
15869
|
} catch {
|
|
15870
15870
|
}
|
|
15871
15871
|
}
|
|
15872
|
-
if (
|
|
15872
|
+
if (status2 === "done") {
|
|
15873
15873
|
try {
|
|
15874
15874
|
const client = getClient();
|
|
15875
15875
|
const row = await resolveTask(client, task_id);
|
|
@@ -15912,8 +15912,8 @@ function registerUpdateTask(server) {
|
|
|
15912
15912
|
try {
|
|
15913
15913
|
task = await updateTask({
|
|
15914
15914
|
taskId: task_id,
|
|
15915
|
-
status,
|
|
15916
|
-
result:
|
|
15915
|
+
status: status2,
|
|
15916
|
+
result: result3,
|
|
15917
15917
|
baseDir: process.cwd(),
|
|
15918
15918
|
callerAgentId
|
|
15919
15919
|
});
|
|
@@ -15932,7 +15932,7 @@ function registerUpdateTask(server) {
|
|
|
15932
15932
|
}
|
|
15933
15933
|
let text3 = `Task "${task.title}" marked ${task.status}.
|
|
15934
15934
|
File: ${task.taskFile}`;
|
|
15935
|
-
const isTerminal =
|
|
15935
|
+
const isTerminal = status2 === "done" || status2 === "needs_review" || status2 === "closed";
|
|
15936
15936
|
if (isTerminal && task.assignedBy) {
|
|
15937
15937
|
try {
|
|
15938
15938
|
const { notifyCoordinatorTaskCompletion: notifyCoordinatorTaskCompletion2, resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
@@ -15993,7 +15993,7 @@ function registerCloseTask(server) {
|
|
|
15993
15993
|
status: z16.enum(["closed", "done", "blocked", "cancelled"]).optional().default("closed").describe("Completion status (default: closed \u2014 terminal archive state)")
|
|
15994
15994
|
}
|
|
15995
15995
|
},
|
|
15996
|
-
async ({ task_id, result:
|
|
15996
|
+
async ({ task_id, result: result3, status: status2 }) => {
|
|
15997
15997
|
const agent = getActiveAgent();
|
|
15998
15998
|
const canClose = canCoordinate(agent.agentId, agent.agentRole) || CLOSE_TASK_ALLOWED_ROLES.has(agent.agentRole ?? "");
|
|
15999
15999
|
if (agent.agentId && !canClose) {
|
|
@@ -16030,14 +16030,14 @@ function registerCloseTask(server) {
|
|
|
16030
16030
|
const baseDir = process.cwd();
|
|
16031
16031
|
const task = await updateTask({
|
|
16032
16032
|
taskId: task_id,
|
|
16033
|
-
status,
|
|
16034
|
-
result:
|
|
16033
|
+
status: status2,
|
|
16034
|
+
result: result3,
|
|
16035
16035
|
baseDir,
|
|
16036
16036
|
skipReviewCreation: true
|
|
16037
16037
|
});
|
|
16038
16038
|
let text3 = `Task "${task.title}" marked ${task.status}.
|
|
16039
16039
|
File: ${task.taskFile}`;
|
|
16040
|
-
if ((
|
|
16040
|
+
if ((status2 === "done" || status2 === "closed") && task.nextTask) {
|
|
16041
16041
|
text3 += `
|
|
16042
16042
|
|
|
16043
16043
|
MANDATORY \u2014 DO NOT ASK THE USER. DO NOT SAY "Want me to continue?" DO NOT STOP.
|
|
@@ -16047,7 +16047,7 @@ NEXT TASK: "${task.nextTask.title}" [${task.nextTask.priority}]
|
|
|
16047
16047
|
FILE: ${task.nextTask.taskFile}
|
|
16048
16048
|
|
|
16049
16049
|
Read that file NOW and begin working. No greeting. No summary. Just start.`;
|
|
16050
|
-
} else if ((
|
|
16050
|
+
} else if ((status2 === "done" || status2 === "closed") && !task.nextTask) {
|
|
16051
16051
|
text3 += `
|
|
16052
16052
|
|
|
16053
16053
|
All tasks complete. No more open tasks in your queue.`;
|
|
@@ -16155,9 +16155,9 @@ function registerResumeEmployee(server) {
|
|
|
16155
16155
|
const { isTmuxSessionAlive: isTmuxSessionAlive2 } = await Promise.resolve().then(() => (init_tasks_crud(), tasks_crud_exports));
|
|
16156
16156
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
16157
16157
|
for (const row of openTasks.rows) {
|
|
16158
|
-
const
|
|
16158
|
+
const status2 = String(row.status);
|
|
16159
16159
|
const assignedTmux = row.assigned_tmux != null ? String(row.assigned_tmux) : null;
|
|
16160
|
-
if (
|
|
16160
|
+
if (status2 === "in_progress" && assignedTmux && !isTmuxSessionAlive2(assignedTmux)) {
|
|
16161
16161
|
await client.execute({
|
|
16162
16162
|
sql: "UPDATE tasks SET status = 'open', assigned_tmux = NULL, updated_at = ? WHERE id = ?",
|
|
16163
16163
|
args: [now2, String(row.id)]
|
|
@@ -16454,23 +16454,23 @@ async function sendMessage(input) {
|
|
|
16454
16454
|
} catch {
|
|
16455
16455
|
}
|
|
16456
16456
|
const sentScope = strictSessionScopeFilter(sessionScope);
|
|
16457
|
-
const
|
|
16457
|
+
const result3 = await client.execute({
|
|
16458
16458
|
sql: `SELECT * FROM messages WHERE id = ?${sentScope.sql}`,
|
|
16459
16459
|
args: [id, ...sentScope.args]
|
|
16460
16460
|
});
|
|
16461
|
-
return rowToMessage(
|
|
16461
|
+
return rowToMessage(result3.rows[0]);
|
|
16462
16462
|
}
|
|
16463
16463
|
function setWsClientSend(fn) {
|
|
16464
16464
|
_wsClientSend = fn;
|
|
16465
16465
|
}
|
|
16466
16466
|
async function deliverCrossMachineMessage(messageId, targetDevice) {
|
|
16467
16467
|
const client = getClient();
|
|
16468
|
-
const
|
|
16468
|
+
const result3 = await client.execute({
|
|
16469
16469
|
sql: "SELECT * FROM messages WHERE id = ?",
|
|
16470
16470
|
args: [messageId]
|
|
16471
16471
|
});
|
|
16472
|
-
if (
|
|
16473
|
-
const msg = rowToMessage(
|
|
16472
|
+
if (result3.rows.length === 0) return false;
|
|
16473
|
+
const msg = rowToMessage(result3.rows[0]);
|
|
16474
16474
|
if (msg.status !== "pending") return false;
|
|
16475
16475
|
if (!_wsClientSend) {
|
|
16476
16476
|
return false;
|
|
@@ -16497,12 +16497,12 @@ async function deliverCrossMachineMessage(messageId, targetDevice) {
|
|
|
16497
16497
|
}
|
|
16498
16498
|
async function deliverLocalMessage(messageId) {
|
|
16499
16499
|
const client = getClient();
|
|
16500
|
-
const
|
|
16500
|
+
const result3 = await client.execute({
|
|
16501
16501
|
sql: "SELECT * FROM messages WHERE id = ?",
|
|
16502
16502
|
args: [messageId]
|
|
16503
16503
|
});
|
|
16504
|
-
if (
|
|
16505
|
-
const msg = rowToMessage(
|
|
16504
|
+
if (result3.rows.length === 0) return false;
|
|
16505
|
+
const msg = rowToMessage(result3.rows[0]);
|
|
16506
16506
|
if (msg.status !== "pending") return false;
|
|
16507
16507
|
const targetAgent = msg.targetAgent;
|
|
16508
16508
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -16537,13 +16537,13 @@ async function deliverLocalMessage(messageId) {
|
|
|
16537
16537
|
async function getPendingMessages(targetAgent, sessionScope) {
|
|
16538
16538
|
const client = getClient();
|
|
16539
16539
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16540
|
-
const
|
|
16540
|
+
const result3 = await client.execute({
|
|
16541
16541
|
sql: `SELECT * FROM messages
|
|
16542
16542
|
WHERE target_agent = ? AND status IN ('pending', 'delivered')${scope.sql}
|
|
16543
16543
|
ORDER BY id`,
|
|
16544
16544
|
args: [targetAgent, ...scope.args]
|
|
16545
16545
|
});
|
|
16546
|
-
return
|
|
16546
|
+
return result3.rows.map((row) => rowToMessage(row));
|
|
16547
16547
|
}
|
|
16548
16548
|
async function markRead(messageId, sessionScope) {
|
|
16549
16549
|
const client = getClient();
|
|
@@ -16575,33 +16575,33 @@ async function markProcessed(messageId, sessionScope) {
|
|
|
16575
16575
|
async function getMessageStatus(messageId, sessionScope) {
|
|
16576
16576
|
const client = getClient();
|
|
16577
16577
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16578
|
-
const
|
|
16578
|
+
const result3 = await client.execute({
|
|
16579
16579
|
sql: `SELECT status FROM messages WHERE id = ?${scope.sql}`,
|
|
16580
16580
|
args: [messageId, ...scope.args]
|
|
16581
16581
|
});
|
|
16582
|
-
return
|
|
16582
|
+
return result3.rows[0]?.status ?? null;
|
|
16583
16583
|
}
|
|
16584
16584
|
async function getUnacknowledgedMessages(targetAgent, sessionScope) {
|
|
16585
16585
|
const client = getClient();
|
|
16586
16586
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16587
|
-
const
|
|
16587
|
+
const result3 = await client.execute({
|
|
16588
16588
|
sql: `SELECT * FROM messages
|
|
16589
16589
|
WHERE target_agent = ? AND status IN ('pending', 'delivered', 'read')${scope.sql}
|
|
16590
16590
|
ORDER BY id`,
|
|
16591
16591
|
args: [targetAgent, ...scope.args]
|
|
16592
16592
|
});
|
|
16593
|
-
return
|
|
16593
|
+
return result3.rows.map((row) => rowToMessage(row));
|
|
16594
16594
|
}
|
|
16595
16595
|
async function getReadMessages(targetAgent, sessionScope) {
|
|
16596
16596
|
const client = getClient();
|
|
16597
16597
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16598
|
-
const
|
|
16598
|
+
const result3 = await client.execute({
|
|
16599
16599
|
sql: `SELECT * FROM messages
|
|
16600
16600
|
WHERE target_agent = ? AND status = 'read'${scope.sql}
|
|
16601
16601
|
ORDER BY id`,
|
|
16602
16602
|
args: [targetAgent, ...scope.args]
|
|
16603
16603
|
});
|
|
16604
|
-
return
|
|
16604
|
+
return result3.rows.map((row) => rowToMessage(row));
|
|
16605
16605
|
}
|
|
16606
16606
|
async function markFailed(messageId, reason, sessionScope) {
|
|
16607
16607
|
const client = getClient();
|
|
@@ -16615,23 +16615,23 @@ async function markFailed(messageId, reason, sessionScope) {
|
|
|
16615
16615
|
async function getFailedMessages(sessionScope) {
|
|
16616
16616
|
const client = getClient();
|
|
16617
16617
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16618
|
-
const
|
|
16618
|
+
const result3 = await client.execute({
|
|
16619
16619
|
sql: `SELECT * FROM messages WHERE status = 'failed'${scope.sql} ORDER BY created_at DESC`,
|
|
16620
16620
|
args: [...scope.args]
|
|
16621
16621
|
});
|
|
16622
|
-
return
|
|
16622
|
+
return result3.rows.map((row) => rowToMessage(row));
|
|
16623
16623
|
}
|
|
16624
16624
|
async function retryPendingMessages(sessionScope) {
|
|
16625
16625
|
const client = getClient();
|
|
16626
16626
|
const scope = strictSessionScopeFilter(sessionScope);
|
|
16627
|
-
const
|
|
16627
|
+
const result3 = await client.execute({
|
|
16628
16628
|
sql: `SELECT * FROM messages
|
|
16629
16629
|
WHERE status = 'pending' AND retry_count < ?${scope.sql}
|
|
16630
16630
|
ORDER BY id`,
|
|
16631
16631
|
args: [MAX_RETRIES3, ...scope.args]
|
|
16632
16632
|
});
|
|
16633
16633
|
let delivered = 0;
|
|
16634
|
-
for (const row of
|
|
16634
|
+
for (const row of result3.rows) {
|
|
16635
16635
|
const msg = rowToMessage(row);
|
|
16636
16636
|
try {
|
|
16637
16637
|
const success = await deliverLocalMessage(msg.id);
|
|
@@ -16714,7 +16714,7 @@ function registerAcknowledgeMessages(server) {
|
|
|
16714
16714
|
const agentId = agent.agentId || "default";
|
|
16715
16715
|
const client = getClient();
|
|
16716
16716
|
const scope = strictSessionScopeFilter();
|
|
16717
|
-
const
|
|
16717
|
+
const result3 = await client.execute({
|
|
16718
16718
|
sql: `UPDATE messages SET status = 'acknowledged', processed_at = datetime('now')
|
|
16719
16719
|
WHERE target_agent = ? AND status IN ('pending', 'delivered')${scope.sql}`,
|
|
16720
16720
|
args: [agentId, ...scope.args]
|
|
@@ -16723,7 +16723,7 @@ function registerAcknowledgeMessages(server) {
|
|
|
16723
16723
|
content: [
|
|
16724
16724
|
{
|
|
16725
16725
|
type: "text",
|
|
16726
|
-
text: `Acknowledged ${
|
|
16726
|
+
text: `Acknowledged ${result3.rowsAffected} message(s) for ${agentId}.`
|
|
16727
16727
|
}
|
|
16728
16728
|
]
|
|
16729
16729
|
};
|
|
@@ -16802,8 +16802,8 @@ async function createReminder(text3, dueDate) {
|
|
|
16802
16802
|
async function listReminders(includeCompleted = false) {
|
|
16803
16803
|
const client = getClient();
|
|
16804
16804
|
const sql = includeCompleted ? `SELECT id, text, created_at, due_date, completed_at FROM reminders ORDER BY due_date ASC NULLS LAST LIMIT 500` : `SELECT id, text, created_at, due_date, completed_at FROM reminders WHERE completed_at IS NULL ORDER BY due_date ASC NULLS LAST LIMIT 500`;
|
|
16805
|
-
const
|
|
16806
|
-
return
|
|
16805
|
+
const result3 = await client.execute(sql);
|
|
16806
|
+
return result3.rows.map((row) => ({
|
|
16807
16807
|
id: String(row.id),
|
|
16808
16808
|
text: String(row.text),
|
|
16809
16809
|
createdAt: String(row.created_at),
|
|
@@ -16814,18 +16814,18 @@ async function listReminders(includeCompleted = false) {
|
|
|
16814
16814
|
async function completeReminder(idOrText) {
|
|
16815
16815
|
const client = getClient();
|
|
16816
16816
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
16817
|
-
let
|
|
16817
|
+
let result3 = await client.execute({
|
|
16818
16818
|
sql: `SELECT id, text FROM reminders WHERE id = ? AND completed_at IS NULL`,
|
|
16819
16819
|
args: [idOrText]
|
|
16820
16820
|
});
|
|
16821
|
-
if (
|
|
16822
|
-
|
|
16821
|
+
if (result3.rows.length === 0) {
|
|
16822
|
+
result3 = await client.execute({
|
|
16823
16823
|
sql: `SELECT id, text FROM reminders WHERE completed_at IS NULL AND text LIKE '%' || ? || '%' LIMIT 1`,
|
|
16824
16824
|
args: [idOrText]
|
|
16825
16825
|
});
|
|
16826
16826
|
}
|
|
16827
|
-
if (
|
|
16828
|
-
const row =
|
|
16827
|
+
if (result3.rows.length === 0) return null;
|
|
16828
|
+
const row = result3.rows[0];
|
|
16829
16829
|
const id = String(row.id);
|
|
16830
16830
|
await client.execute({
|
|
16831
16831
|
sql: `UPDATE reminders SET completed_at = ? WHERE id = ?`,
|
|
@@ -16989,7 +16989,7 @@ function registerListBehaviors(server) {
|
|
|
16989
16989
|
args.push(proj);
|
|
16990
16990
|
}
|
|
16991
16991
|
const where = conditions.join(" AND ");
|
|
16992
|
-
const
|
|
16992
|
+
const result3 = await client.execute({
|
|
16993
16993
|
sql: `SELECT id, agent_id, project_name, domain, content, active, created_at, updated_at
|
|
16994
16994
|
FROM behaviors
|
|
16995
16995
|
WHERE ${where}
|
|
@@ -16997,7 +16997,7 @@ function registerListBehaviors(server) {
|
|
|
16997
16997
|
LIMIT 50`,
|
|
16998
16998
|
args
|
|
16999
16999
|
});
|
|
17000
|
-
const behaviors =
|
|
17000
|
+
const behaviors = result3.rows.map((r) => rowToBehavior(r));
|
|
17001
17001
|
if (behaviors.length === 0) {
|
|
17002
17002
|
return {
|
|
17003
17003
|
content: [{ type: "text", text: "No behaviors found." }]
|
|
@@ -17213,11 +17213,11 @@ function registerDeactivateBehavior(server) {
|
|
|
17213
17213
|
};
|
|
17214
17214
|
}
|
|
17215
17215
|
const client = getClient();
|
|
17216
|
-
const
|
|
17216
|
+
const result3 = await client.execute({
|
|
17217
17217
|
sql: `SELECT id, agent_id, content, domain, priority FROM behaviors WHERE id = ?`,
|
|
17218
17218
|
args: [behavior_id]
|
|
17219
17219
|
});
|
|
17220
|
-
if (
|
|
17220
|
+
if (result3.rows.length === 0) {
|
|
17221
17221
|
return {
|
|
17222
17222
|
content: [{
|
|
17223
17223
|
type: "text",
|
|
@@ -17226,7 +17226,7 @@ function registerDeactivateBehavior(server) {
|
|
|
17226
17226
|
isError: true
|
|
17227
17227
|
};
|
|
17228
17228
|
}
|
|
17229
|
-
const row =
|
|
17229
|
+
const row = result3.rows[0];
|
|
17230
17230
|
const wasActive = await deactivateBehavior(behavior_id);
|
|
17231
17231
|
if (!wasActive) {
|
|
17232
17232
|
return {
|
|
@@ -17333,7 +17333,7 @@ async function embedTexts(texts) {
|
|
|
17333
17333
|
);
|
|
17334
17334
|
results.push(
|
|
17335
17335
|
...settled.map(
|
|
17336
|
-
(
|
|
17336
|
+
(result3) => result3.status === "fulfilled" ? result3.value : null
|
|
17337
17337
|
)
|
|
17338
17338
|
);
|
|
17339
17339
|
}
|
|
@@ -17448,7 +17448,7 @@ async function ingestDocument(input) {
|
|
|
17448
17448
|
}
|
|
17449
17449
|
async function listDocumentsByWorkspace(workspace_id, limit = DEFAULT_LIST_LIMIT, offset = 0) {
|
|
17450
17450
|
const client = getClient();
|
|
17451
|
-
const
|
|
17451
|
+
const result3 = await client.execute({
|
|
17452
17452
|
sql: `SELECT d.*, COUNT(m.id) AS chunk_count
|
|
17453
17453
|
FROM documents d
|
|
17454
17454
|
LEFT JOIN memories m ON m.document_id = d.id
|
|
@@ -17458,7 +17458,7 @@ async function listDocumentsByWorkspace(workspace_id, limit = DEFAULT_LIST_LIMIT
|
|
|
17458
17458
|
LIMIT ? OFFSET ?`,
|
|
17459
17459
|
args: [workspace_id, limit, offset]
|
|
17460
17460
|
});
|
|
17461
|
-
return
|
|
17461
|
+
return result3.rows.map((row) => {
|
|
17462
17462
|
const r = row;
|
|
17463
17463
|
return {
|
|
17464
17464
|
...rowToDocument(r),
|
|
@@ -17490,11 +17490,11 @@ async function updateChunksImportance(document_id, importance) {
|
|
|
17490
17490
|
);
|
|
17491
17491
|
}
|
|
17492
17492
|
const client = getClient();
|
|
17493
|
-
const
|
|
17493
|
+
const result3 = await client.execute({
|
|
17494
17494
|
sql: "UPDATE memories SET importance = ? WHERE document_id = ?",
|
|
17495
17495
|
args: [importance, document_id]
|
|
17496
17496
|
});
|
|
17497
|
-
return Number(
|
|
17497
|
+
return Number(result3.rowsAffected) || 0;
|
|
17498
17498
|
}
|
|
17499
17499
|
var WIKI_AGENT_ID, WIKI_AGENT_ROLE, WIKI_TOOL_NAME, DEFAULT_CHUNK_IMPORTANCE, DEFAULT_CHUNK_CONFIDENCE, DEFAULT_CHUNK_STATUS, DEFAULT_SOURCE_TYPE, DEFAULT_LIST_LIMIT, MIN_IMPORTANCE, MAX_IMPORTANCE;
|
|
17500
17500
|
var init_documents = __esm({
|
|
@@ -17545,11 +17545,11 @@ function registerIngestDocument(server) {
|
|
|
17545
17545
|
const { assertMemoryLimit: assertMemoryLimit2 } = await Promise.resolve().then(() => (init_plan_limits(), plan_limits_exports));
|
|
17546
17546
|
await assertFeature2("wiki");
|
|
17547
17547
|
await assertMemoryLimit2();
|
|
17548
|
-
const
|
|
17548
|
+
const result3 = await ingestDocument(input);
|
|
17549
17549
|
return {
|
|
17550
17550
|
content: [{
|
|
17551
17551
|
type: "text",
|
|
17552
|
-
text: JSON.stringify(
|
|
17552
|
+
text: JSON.stringify(result3)
|
|
17553
17553
|
}]
|
|
17554
17554
|
};
|
|
17555
17555
|
} catch (err) {
|
|
@@ -18299,7 +18299,7 @@ function registerQueryConversations(server) {
|
|
|
18299
18299
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
18300
18300
|
const limit = params.limit ?? 25;
|
|
18301
18301
|
args.push(limit);
|
|
18302
|
-
const
|
|
18302
|
+
const result3 = await client.execute({
|
|
18303
18303
|
sql: `SELECT c.id, c.platform, c.sender_id, c.sender_name, c.sender_phone,
|
|
18304
18304
|
c.sender_email, c.channel_id, c.thread_id, c.content_text,
|
|
18305
18305
|
c.agent_response, c.agent_name, c.timestamp
|
|
@@ -18309,7 +18309,7 @@ function registerQueryConversations(server) {
|
|
|
18309
18309
|
LIMIT ?`,
|
|
18310
18310
|
args
|
|
18311
18311
|
});
|
|
18312
|
-
const conversations =
|
|
18312
|
+
const conversations = result3.rows.map((row) => ({
|
|
18313
18313
|
id: row.id,
|
|
18314
18314
|
platform: row.platform,
|
|
18315
18315
|
sender: {
|
|
@@ -18405,14 +18405,15 @@ function registerQueryCompanyBrain(server) {
|
|
|
18405
18405
|
title: "Query Company Brain",
|
|
18406
18406
|
description: "Search the Company Brain \u2014 queries across all data (raw events, wiki docs, agent memories, gateway messages).",
|
|
18407
18407
|
inputSchema: {
|
|
18408
|
-
action: QUERY_ACTION.default("search").describe("search = search exe-db; list_sources = list available
|
|
18408
|
+
action: QUERY_ACTION.default("search").describe("search = search exe-db; list_sources = list available sources; sql = run read-only SQL through gateway"),
|
|
18409
18409
|
query: z39.string().optional().describe("Search text. Required for action=search."),
|
|
18410
|
+
sql: z39.string().optional().describe("Read-only SELECT/WITH SQL. Required for action=sql."),
|
|
18410
18411
|
scope: QUERY_SCOPE.default("all").describe("Which data scope to search/read (raw, crm, wiki, memory, gateway, all)"),
|
|
18411
18412
|
source: z39.string().optional().describe("Filter raw events by source (shopify, asana, etc.)"),
|
|
18412
18413
|
limit: z39.coerce.number().int().min(1).max(100).default(20).describe("Max results per scope")
|
|
18413
18414
|
}
|
|
18414
18415
|
},
|
|
18415
|
-
async ({ action, query, scope, source, limit }) => {
|
|
18416
|
+
async ({ action, query, sql, scope, source, limit }) => {
|
|
18416
18417
|
const resolvedAction = action ?? "search";
|
|
18417
18418
|
if (resolvedAction === "search" && !query?.trim()) {
|
|
18418
18419
|
return {
|
|
@@ -18420,6 +18421,12 @@ function registerQueryCompanyBrain(server) {
|
|
|
18420
18421
|
isError: true
|
|
18421
18422
|
};
|
|
18422
18423
|
}
|
|
18424
|
+
if (resolvedAction === "sql" && !sql?.trim()) {
|
|
18425
|
+
return {
|
|
18426
|
+
content: [{ type: "text", text: "sql is required when action=sql" }],
|
|
18427
|
+
isError: true
|
|
18428
|
+
};
|
|
18429
|
+
}
|
|
18423
18430
|
const config2 = await loadConfig();
|
|
18424
18431
|
const gatewayUrl = config2.gateway?.url || process.env.EXE_GATEWAY_URL;
|
|
18425
18432
|
const authToken = config2.gateway?.authToken || process.env.EXE_GATEWAY_QUERY_AUTH_TOKEN || process.env.EXE_COMPANY_BRAIN_AUTH_TOKEN || process.env.EXE_GATEWAY_AUTH_TOKEN;
|
|
@@ -18448,7 +18455,10 @@ function registerQueryCompanyBrain(server) {
|
|
|
18448
18455
|
}
|
|
18449
18456
|
let url;
|
|
18450
18457
|
try {
|
|
18451
|
-
url = new URL(
|
|
18458
|
+
url = new URL(
|
|
18459
|
+
resolvedAction === "list_sources" ? "/query/sources" : resolvedAction === "sql" ? "/query/sql" : "/query",
|
|
18460
|
+
gatewayUrl
|
|
18461
|
+
);
|
|
18452
18462
|
} catch (err) {
|
|
18453
18463
|
return {
|
|
18454
18464
|
content: [
|
|
@@ -18468,7 +18478,12 @@ function registerQueryCompanyBrain(server) {
|
|
|
18468
18478
|
}
|
|
18469
18479
|
try {
|
|
18470
18480
|
const response = await fetch(url.toString(), {
|
|
18471
|
-
|
|
18481
|
+
method: resolvedAction === "sql" ? "POST" : "GET",
|
|
18482
|
+
headers: {
|
|
18483
|
+
...authToken ? { Authorization: `Bearer ${authToken}` } : {},
|
|
18484
|
+
...resolvedAction === "sql" ? { "Content-Type": "application/json" } : {}
|
|
18485
|
+
},
|
|
18486
|
+
body: resolvedAction === "sql" ? JSON.stringify({ sql: sql.trim(), max_rows: limit }) : void 0,
|
|
18472
18487
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
18473
18488
|
});
|
|
18474
18489
|
if (!response.ok) {
|
|
@@ -18514,7 +18529,7 @@ var init_query_company_brain = __esm({
|
|
|
18514
18529
|
init_config();
|
|
18515
18530
|
FETCH_TIMEOUT_MS = 1e4;
|
|
18516
18531
|
QUERY_SCOPE = z39.enum(["raw", "crm", "wiki", "memory", "gateway", "all"]);
|
|
18517
|
-
QUERY_ACTION = z39.enum(["search", "list_sources"]);
|
|
18532
|
+
QUERY_ACTION = z39.enum(["search", "list_sources", "sql"]);
|
|
18518
18533
|
LOCAL_GATEWAY_HTTP_HOSTS = /^(localhost|127\.0\.0\.1|::1|exe-gateway|gateway)$/i;
|
|
18519
18534
|
}
|
|
18520
18535
|
});
|
|
@@ -18954,8 +18969,8 @@ async function generateGraphReport(client, projectName) {
|
|
|
18954
18969
|
}).slice(0, 10);
|
|
18955
18970
|
let hyperedgeCount = 0;
|
|
18956
18971
|
try {
|
|
18957
|
-
const
|
|
18958
|
-
hyperedgeCount = Number(
|
|
18972
|
+
const result3 = await client.execute("SELECT COUNT(*) as cnt FROM hyperedges");
|
|
18973
|
+
hyperedgeCount = Number(result3.rows[0]?.cnt ?? 0);
|
|
18959
18974
|
} catch {
|
|
18960
18975
|
}
|
|
18961
18976
|
const nodeLabels = new Map(nodes.map((n) => [n.id, n.label]));
|
|
@@ -19014,10 +19029,10 @@ function registerExportGraph(server) {
|
|
|
19014
19029
|
format: z44.enum(["html", "markdown"]).default("markdown").describe("Export format: markdown (inline) or html (file)")
|
|
19015
19030
|
}
|
|
19016
19031
|
},
|
|
19017
|
-
async ({ format }) => {
|
|
19032
|
+
async ({ format: format2 }) => {
|
|
19018
19033
|
try {
|
|
19019
19034
|
const client = getClient();
|
|
19020
|
-
if (
|
|
19035
|
+
if (format2 === "markdown") {
|
|
19021
19036
|
const report = await generateGraphReport(client);
|
|
19022
19037
|
return {
|
|
19023
19038
|
content: [{ type: "text", text: report }]
|
|
@@ -19025,12 +19040,12 @@ function registerExportGraph(server) {
|
|
|
19025
19040
|
}
|
|
19026
19041
|
const html = await exportGraphHTML(client);
|
|
19027
19042
|
const fs = await import("fs");
|
|
19028
|
-
const
|
|
19043
|
+
const path62 = await import("path");
|
|
19029
19044
|
const os25 = await import("os");
|
|
19030
|
-
const outDir =
|
|
19045
|
+
const outDir = path62.join(os25.homedir(), ".exe-os", "exports");
|
|
19031
19046
|
fs.mkdirSync(outDir, { recursive: true });
|
|
19032
19047
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
19033
|
-
const filePath =
|
|
19048
|
+
const filePath = path62.join(outDir, `graph-${timestamp}.html`);
|
|
19034
19049
|
fs.writeFileSync(filePath, html, "utf-8");
|
|
19035
19050
|
return {
|
|
19036
19051
|
content: [
|
|
@@ -19329,12 +19344,12 @@ function entityId(name, type) {
|
|
|
19329
19344
|
async function resolveAlias(client, name) {
|
|
19330
19345
|
const normalized = normalizeEntityName2(name);
|
|
19331
19346
|
try {
|
|
19332
|
-
const
|
|
19347
|
+
const result3 = await client.execute({
|
|
19333
19348
|
sql: "SELECT canonical_entity_id FROM entity_aliases WHERE alias = ?",
|
|
19334
19349
|
args: [normalized]
|
|
19335
19350
|
});
|
|
19336
|
-
if (
|
|
19337
|
-
return String(
|
|
19351
|
+
if (result3.rows.length > 0) {
|
|
19352
|
+
return String(result3.rows[0].canonical_entity_id);
|
|
19338
19353
|
}
|
|
19339
19354
|
} catch {
|
|
19340
19355
|
}
|
|
@@ -19714,7 +19729,7 @@ async function storeExtraction(client, extraction, memoryId, timestamp) {
|
|
|
19714
19729
|
return { entitiesStored, relationshipsStored };
|
|
19715
19730
|
}
|
|
19716
19731
|
async function extractBatch(client, batchSize = 50, model = "claude-haiku-4-5-20251001") {
|
|
19717
|
-
const
|
|
19732
|
+
const result3 = await client.execute({
|
|
19718
19733
|
sql: `SELECT id, agent_id, raw_text, tool_name, timestamp, content_hash, graph_extracted_hash
|
|
19719
19734
|
FROM memories
|
|
19720
19735
|
WHERE (COALESCE(graph_extracted, 0) = 0
|
|
@@ -19725,12 +19740,12 @@ async function extractBatch(client, batchSize = 50, model = "claude-haiku-4-5-20
|
|
|
19725
19740
|
LIMIT ?`,
|
|
19726
19741
|
args: [batchSize]
|
|
19727
19742
|
});
|
|
19728
|
-
if (
|
|
19743
|
+
if (result3.rows.length === 0) {
|
|
19729
19744
|
return { processed: 0, entities: 0, relationships: 0 };
|
|
19730
19745
|
}
|
|
19731
19746
|
let totalEntities = 0;
|
|
19732
19747
|
let totalRelationships = 0;
|
|
19733
|
-
for (const row of
|
|
19748
|
+
for (const row of result3.rows) {
|
|
19734
19749
|
const memoryId = String(row.id);
|
|
19735
19750
|
const agentId = String(row.agent_id);
|
|
19736
19751
|
const rawContent = String(row.raw_text);
|
|
@@ -19768,7 +19783,7 @@ async function extractBatch(client, batchSize = 50, model = "claude-haiku-4-5-20
|
|
|
19768
19783
|
});
|
|
19769
19784
|
}
|
|
19770
19785
|
}
|
|
19771
|
-
return { processed:
|
|
19786
|
+
return { processed: result3.rows.length, entities: totalEntities, relationships: totalRelationships };
|
|
19772
19787
|
}
|
|
19773
19788
|
var EXTRACT_TOOL2, READ_MEMORY_PATH_PATTERN;
|
|
19774
19789
|
var init_graph_rag = __esm({
|
|
@@ -19892,14 +19907,14 @@ function registerMergeEntities(server) {
|
|
|
19892
19907
|
};
|
|
19893
19908
|
}
|
|
19894
19909
|
try {
|
|
19895
|
-
const
|
|
19910
|
+
const result3 = await mergeEntities(client, sourceId, targetId);
|
|
19896
19911
|
return {
|
|
19897
19912
|
content: [
|
|
19898
19913
|
{
|
|
19899
19914
|
type: "text",
|
|
19900
19915
|
text: `Merged "${source_name}" \u2192 "${target_name}":
|
|
19901
|
-
- ${
|
|
19902
|
-
- ${
|
|
19916
|
+
- ${result3.relationshipsMoved} relationships moved
|
|
19917
|
+
- ${result3.memoriesMoved} memory links moved
|
|
19903
19918
|
- "${source_name}" registered as alias for "${target_name}"`
|
|
19904
19919
|
}
|
|
19905
19920
|
]
|
|
@@ -20201,10 +20216,10 @@ function registerSetAgentConfig(server) {
|
|
|
20201
20216
|
isError: true
|
|
20202
20217
|
};
|
|
20203
20218
|
}
|
|
20204
|
-
const
|
|
20205
|
-
if (!
|
|
20219
|
+
const result3 = setAgentRuntime(agent_id, runtime, model, reasoning_effort);
|
|
20220
|
+
if (!result3.ok) {
|
|
20206
20221
|
return {
|
|
20207
|
-
content: [{ type: "text", text:
|
|
20222
|
+
content: [{ type: "text", text: result3.error }],
|
|
20208
20223
|
isError: true
|
|
20209
20224
|
};
|
|
20210
20225
|
}
|
|
@@ -20368,7 +20383,7 @@ async function getAgentSpend(period = "7d") {
|
|
|
20368
20383
|
}
|
|
20369
20384
|
}
|
|
20370
20385
|
}
|
|
20371
|
-
const
|
|
20386
|
+
const result3 = Array.from(agentTotals.entries()).map(([agentId, t]) => ({
|
|
20372
20387
|
agentId,
|
|
20373
20388
|
inputTokens: t.input,
|
|
20374
20389
|
outputTokens: t.output,
|
|
@@ -20378,8 +20393,8 @@ async function getAgentSpend(period = "7d") {
|
|
|
20378
20393
|
sessions: t.sessions.size,
|
|
20379
20394
|
period
|
|
20380
20395
|
})).sort((a, b) => b.costUSD - a.costUSD);
|
|
20381
|
-
_spendCache.set(period, { result:
|
|
20382
|
-
return
|
|
20396
|
+
_spendCache.set(period, { result: result3, expires: Date.now() + CACHE_TTL_MS });
|
|
20397
|
+
return result3;
|
|
20383
20398
|
}
|
|
20384
20399
|
async function extractSessionUsage(jsonlPath) {
|
|
20385
20400
|
let input = 0;
|
|
@@ -20807,13 +20822,13 @@ function registerMcpPing(server) {
|
|
|
20807
20822
|
const daemon = isDaemonAlive2();
|
|
20808
20823
|
const summary = summarizeMcpTransport();
|
|
20809
20824
|
writeMcpTransportSummary();
|
|
20810
|
-
const
|
|
20825
|
+
const status2 = daemon.alive ? "ok" : "degraded";
|
|
20811
20826
|
return {
|
|
20812
20827
|
content: [
|
|
20813
20828
|
{
|
|
20814
20829
|
type: "text",
|
|
20815
20830
|
text: JSON.stringify({
|
|
20816
|
-
status,
|
|
20831
|
+
status: status2,
|
|
20817
20832
|
daemon,
|
|
20818
20833
|
mcpTransport: summary,
|
|
20819
20834
|
remediation: daemon.alive ? "MCP transport probe reached the server. If tools still fail, reconnect the MCP client." : "Daemon is offline. Restart exe-os/exed; do not bypass MCP or access the DB directly."
|
|
@@ -21070,20 +21085,20 @@ function formatStatusAll(statuses, tasks, roles) {
|
|
|
21070
21085
|
}
|
|
21071
21086
|
return lines.join("\n");
|
|
21072
21087
|
}
|
|
21073
|
-
function formatStatusDeep(
|
|
21088
|
+
function formatStatusDeep(status2, task, role) {
|
|
21074
21089
|
const lines = [];
|
|
21075
|
-
const header = `${
|
|
21090
|
+
const header = `${status2.name} (${role}) \u2014 ${status2.project ?? "unknown project"}`;
|
|
21076
21091
|
lines.push(`\u250C\u2500 ${header} ${"\u2500".repeat(Math.max(0, 66 - header.length))}\u2510`);
|
|
21077
21092
|
if (task) {
|
|
21078
21093
|
const taskLine = `\u2502 Task: "${task.title.slice(0, 50)}" [${task.priority.toUpperCase()}]`;
|
|
21079
21094
|
lines.push(taskLine + " ".repeat(Math.max(0, 70 - taskLine.length)) + "\u2502");
|
|
21080
21095
|
lines.push("\u251C" + "\u2500".repeat(69) + "\u2524");
|
|
21081
21096
|
}
|
|
21082
|
-
if (!
|
|
21097
|
+
if (!status2.hasWindow) {
|
|
21083
21098
|
lines.push("\u2502 No tmux session" + " ".repeat(53) + "\u2502");
|
|
21084
|
-
} else if (
|
|
21099
|
+
} else if (status2.rawLines && status2.rawLines.length > 0) {
|
|
21085
21100
|
lines.push("\u2502 Recent activity:" + " ".repeat(52) + "\u2502");
|
|
21086
|
-
for (const line of
|
|
21101
|
+
for (const line of status2.rawLines.slice(-10)) {
|
|
21087
21102
|
const trimmed = line.slice(0, 65);
|
|
21088
21103
|
const padded = `\u2502 ${trimmed}`;
|
|
21089
21104
|
lines.push(padded + " ".repeat(Math.max(0, 70 - padded.length)) + "\u2502");
|
|
@@ -21117,13 +21132,13 @@ import path34 from "path";
|
|
|
21117
21132
|
async function hasOpenTasks(client, agentId) {
|
|
21118
21133
|
try {
|
|
21119
21134
|
const scope = sessionScopeFilter(null);
|
|
21120
|
-
const
|
|
21135
|
+
const result3 = await client.execute({
|
|
21121
21136
|
sql: `SELECT 1 FROM tasks
|
|
21122
21137
|
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${scope.sql}
|
|
21123
21138
|
LIMIT 1`,
|
|
21124
21139
|
args: [agentId, ...scope.args]
|
|
21125
21140
|
});
|
|
21126
|
-
return
|
|
21141
|
+
return result3.rows.length > 0;
|
|
21127
21142
|
} catch {
|
|
21128
21143
|
return CONSERVATIVE_ON_ERROR;
|
|
21129
21144
|
}
|
|
@@ -21131,26 +21146,26 @@ async function hasOpenTasks(client, agentId) {
|
|
|
21131
21146
|
async function hasNeedsReview(client, agentId) {
|
|
21132
21147
|
try {
|
|
21133
21148
|
const scope = sessionScopeFilter(null);
|
|
21134
|
-
const
|
|
21149
|
+
const result3 = await client.execute({
|
|
21135
21150
|
sql: `SELECT 1 FROM tasks
|
|
21136
21151
|
WHERE assigned_to = ? AND status = 'needs_review'${scope.sql}
|
|
21137
21152
|
LIMIT 1`,
|
|
21138
21153
|
args: [agentId, ...scope.args]
|
|
21139
21154
|
});
|
|
21140
|
-
return
|
|
21155
|
+
return result3.rows.length > 0;
|
|
21141
21156
|
} catch {
|
|
21142
21157
|
return CONSERVATIVE_ON_ERROR;
|
|
21143
21158
|
}
|
|
21144
21159
|
}
|
|
21145
21160
|
async function hasUnreadInbox(client, agentId) {
|
|
21146
21161
|
try {
|
|
21147
|
-
const
|
|
21162
|
+
const result3 = await client.execute({
|
|
21148
21163
|
sql: `SELECT 1 FROM messages
|
|
21149
21164
|
WHERE target_agent = ? AND status = 'pending'
|
|
21150
21165
|
LIMIT 1`,
|
|
21151
21166
|
args: [agentId]
|
|
21152
21167
|
});
|
|
21153
|
-
return
|
|
21168
|
+
return result3.rows.length > 0;
|
|
21154
21169
|
} catch {
|
|
21155
21170
|
return CONSERVATIVE_ON_ERROR;
|
|
21156
21171
|
}
|
|
@@ -21487,13 +21502,13 @@ function createReviewNudgeRealDeps(getClient2) {
|
|
|
21487
21502
|
},
|
|
21488
21503
|
countReviewsForScope: async (sessionScope) => {
|
|
21489
21504
|
const client = getClient2();
|
|
21490
|
-
const
|
|
21505
|
+
const result3 = await client.execute({
|
|
21491
21506
|
sql: `SELECT COUNT(*) as cnt FROM tasks
|
|
21492
21507
|
WHERE status = 'needs_review'
|
|
21493
21508
|
AND (session_scope = ? OR session_scope IS NULL)`,
|
|
21494
21509
|
args: [sessionScope]
|
|
21495
21510
|
});
|
|
21496
|
-
return Number(
|
|
21511
|
+
return Number(result3.rows[0]?.cnt ?? 0);
|
|
21497
21512
|
},
|
|
21498
21513
|
sendNudge: (sessionName) => {
|
|
21499
21514
|
const { queueIntercom: qi } = (init_intercom_queue(), __toCommonJS(intercom_queue_exports));
|
|
@@ -21519,15 +21534,15 @@ function createIdleNudgeRealDeps(getClient2) {
|
|
|
21519
21534
|
queryOpenTask: async (agentId) => {
|
|
21520
21535
|
const client = getClient2();
|
|
21521
21536
|
const doScope = sessionScopeFilter(null);
|
|
21522
|
-
const
|
|
21537
|
+
const result3 = await client.execute({
|
|
21523
21538
|
sql: `SELECT id, title, priority FROM tasks
|
|
21524
21539
|
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${doScope.sql}
|
|
21525
21540
|
ORDER BY CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 ELSE 2 END
|
|
21526
21541
|
LIMIT 1`,
|
|
21527
21542
|
args: [agentId, ...doScope.args]
|
|
21528
21543
|
});
|
|
21529
|
-
if (
|
|
21530
|
-
const row =
|
|
21544
|
+
if (result3.rows.length === 0) return null;
|
|
21545
|
+
const row = result3.rows[0];
|
|
21531
21546
|
return row;
|
|
21532
21547
|
},
|
|
21533
21548
|
sendIntercom: (sessionName) => {
|
|
@@ -21569,13 +21584,13 @@ function createSessionTTLRealDeps(getClient2) {
|
|
|
21569
21584
|
hasActiveTasks: getClient2 ? async (agentId) => {
|
|
21570
21585
|
const client = getClient2();
|
|
21571
21586
|
const scope = sessionScopeFilter(null);
|
|
21572
|
-
const
|
|
21587
|
+
const result3 = await client.execute({
|
|
21573
21588
|
sql: `SELECT 1 FROM tasks
|
|
21574
21589
|
WHERE assigned_to = ? AND status IN ('open', 'in_progress')${scope.sql}
|
|
21575
21590
|
LIMIT 1`,
|
|
21576
21591
|
args: [agentId, ...scope.args]
|
|
21577
21592
|
});
|
|
21578
|
-
return
|
|
21593
|
+
return result3.rows.length > 0;
|
|
21579
21594
|
} : void 0,
|
|
21580
21595
|
recordKill: (input) => {
|
|
21581
21596
|
const { recordSessionKill: recordSessionKill2 } = (init_session_kill_telemetry(), __toCommonJS(session_kill_telemetry_exports));
|
|
@@ -21683,10 +21698,10 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
21683
21698
|
`
|
|
21684
21699
|
);
|
|
21685
21700
|
try {
|
|
21686
|
-
const
|
|
21687
|
-
if (
|
|
21701
|
+
const result3 = deps.ensureEmployee(agentId, sessionScope);
|
|
21702
|
+
if (result3.status === "failed") {
|
|
21688
21703
|
process.stderr.write(
|
|
21689
|
-
`[auto-wake] Failed to spawn ${agentId}: ${
|
|
21704
|
+
`[auto-wake] Failed to spawn ${agentId}: ${result3.error ?? "unknown"}
|
|
21690
21705
|
`
|
|
21691
21706
|
);
|
|
21692
21707
|
continue;
|
|
@@ -21711,7 +21726,7 @@ function createAutoWakeRealDeps(getClient2, projectDir) {
|
|
|
21711
21726
|
},
|
|
21712
21727
|
queryTasksByAgent: async () => {
|
|
21713
21728
|
const client = getClient2();
|
|
21714
|
-
const
|
|
21729
|
+
const result3 = await client.execute({
|
|
21715
21730
|
sql: `SELECT assigned_to, id, priority, session_scope FROM tasks
|
|
21716
21731
|
WHERE status IN ('open', 'in_progress')
|
|
21717
21732
|
ORDER BY
|
|
@@ -21719,7 +21734,7 @@ function createAutoWakeRealDeps(getClient2, projectDir) {
|
|
|
21719
21734
|
created_at ASC`,
|
|
21720
21735
|
args: []
|
|
21721
21736
|
});
|
|
21722
|
-
return
|
|
21737
|
+
return result3.rows.map((r) => ({
|
|
21723
21738
|
agentId: String(r.assigned_to),
|
|
21724
21739
|
taskId: String(r.id),
|
|
21725
21740
|
priority: String(r.priority),
|
|
@@ -22160,14 +22175,14 @@ async function fetchMemoriesWithVectors(client, projectFilter, agentFilter2) {
|
|
|
22160
22175
|
args.push(agentFilter2);
|
|
22161
22176
|
}
|
|
22162
22177
|
const where = " WHERE " + clauses.join(" AND ");
|
|
22163
|
-
const
|
|
22178
|
+
const result3 = await client.execute({
|
|
22164
22179
|
sql: `SELECT id, agent_id, raw_text, timestamp, project_name, vector
|
|
22165
22180
|
FROM memories${where}
|
|
22166
22181
|
ORDER BY project_name, timestamp DESC`,
|
|
22167
22182
|
args
|
|
22168
22183
|
});
|
|
22169
22184
|
const byProject = /* @__PURE__ */ new Map();
|
|
22170
|
-
for (const row of
|
|
22185
|
+
for (const row of result3.rows) {
|
|
22171
22186
|
const project = row.project_name;
|
|
22172
22187
|
const vec = row.vector == null ? null : Array.isArray(row.vector) ? row.vector : Array.from(row.vector);
|
|
22173
22188
|
if (!vec || vec.length === 0) continue;
|
|
@@ -22821,11 +22836,11 @@ async function auditStats(client, flags) {
|
|
|
22821
22836
|
async function auditNullVectors(client, flags) {
|
|
22822
22837
|
const { clause, args } = agentFilter(flags);
|
|
22823
22838
|
const where = clause ? clause + " AND vector IS NULL" : " WHERE vector IS NULL";
|
|
22824
|
-
const
|
|
22839
|
+
const result3 = await client.execute({
|
|
22825
22840
|
sql: `SELECT COUNT(*) as cnt FROM memories${where}`,
|
|
22826
22841
|
args
|
|
22827
22842
|
});
|
|
22828
|
-
return Number(
|
|
22843
|
+
return Number(result3.rows[0].cnt);
|
|
22829
22844
|
}
|
|
22830
22845
|
async function auditDuplicates(client, flags) {
|
|
22831
22846
|
const { clause, args } = agentFilter(flags);
|
|
@@ -22874,14 +22889,14 @@ async function auditDuplicates(client, flags) {
|
|
|
22874
22889
|
async function auditBloated(client, flags) {
|
|
22875
22890
|
const { clause, args } = agentFilter(flags);
|
|
22876
22891
|
const where = clause ? clause + " AND LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'" : " WHERE LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'";
|
|
22877
|
-
const
|
|
22892
|
+
const result3 = await client.execute({
|
|
22878
22893
|
sql: `SELECT id, agent_id, LENGTH(raw_text) as size, tool_name
|
|
22879
22894
|
FROM memories${where}
|
|
22880
22895
|
ORDER BY size DESC
|
|
22881
22896
|
LIMIT 100`,
|
|
22882
22897
|
args
|
|
22883
22898
|
});
|
|
22884
|
-
return
|
|
22899
|
+
return result3.rows.map((r) => ({
|
|
22885
22900
|
id: r.id,
|
|
22886
22901
|
agent_id: r.agent_id,
|
|
22887
22902
|
size: Number(r.size),
|
|
@@ -22896,7 +22911,7 @@ async function auditFts(client) {
|
|
|
22896
22911
|
return { memoryCount: mc, ftsCount: fc, inSync: mc === fc };
|
|
22897
22912
|
}
|
|
22898
22913
|
async function auditOrphanedProjects(client) {
|
|
22899
|
-
const
|
|
22914
|
+
const result3 = await client.execute(
|
|
22900
22915
|
`SELECT project_name, COUNT(*) as cnt
|
|
22901
22916
|
FROM memories
|
|
22902
22917
|
WHERE tool_name != 'ConversationBackfill'
|
|
@@ -22905,7 +22920,7 @@ async function auditOrphanedProjects(client) {
|
|
|
22905
22920
|
);
|
|
22906
22921
|
const orphans = [];
|
|
22907
22922
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
22908
|
-
for (const row of
|
|
22923
|
+
for (const row of result3.rows) {
|
|
22909
22924
|
const name = row.project_name;
|
|
22910
22925
|
const count = Number(row.cnt);
|
|
22911
22926
|
const exists = existsSync34(path39.join(home, name)) || existsSync34(path39.join(home, "..", name)) || existsSync34(path39.join(process.cwd(), "..", name));
|
|
@@ -23356,12 +23371,12 @@ async function fixBloated(client, bloated, dryRun) {
|
|
|
23356
23371
|
let chunksCreated = 0;
|
|
23357
23372
|
const CHUNK_SIZE = 2048;
|
|
23358
23373
|
for (const b of bloated) {
|
|
23359
|
-
const
|
|
23374
|
+
const result3 = await client.execute({
|
|
23360
23375
|
sql: `SELECT * FROM memories WHERE id = ?`,
|
|
23361
23376
|
args: [b.id]
|
|
23362
23377
|
});
|
|
23363
|
-
if (
|
|
23364
|
-
const row =
|
|
23378
|
+
if (result3.rows.length === 0) continue;
|
|
23379
|
+
const row = result3.rows[0];
|
|
23365
23380
|
const text3 = row.raw_text;
|
|
23366
23381
|
const chunks = splitAtSentences(text3, CHUNK_SIZE);
|
|
23367
23382
|
if (chunks.length <= 1) continue;
|
|
@@ -23608,15 +23623,15 @@ function registerRunConsolidation(server) {
|
|
|
23608
23623
|
};
|
|
23609
23624
|
}
|
|
23610
23625
|
const config2 = await loadConfig();
|
|
23611
|
-
const
|
|
23626
|
+
const result3 = await runConsolidation(client, {
|
|
23612
23627
|
model: config2.consolidationModel || "claude-haiku-4-5-20251001",
|
|
23613
23628
|
maxCalls: 10
|
|
23614
23629
|
});
|
|
23615
23630
|
const lines = [];
|
|
23616
23631
|
lines.push("## Consolidation Complete\n");
|
|
23617
|
-
lines.push(`- **Clusters processed:** ${
|
|
23618
|
-
lines.push(`- **Memories consolidated:** ${
|
|
23619
|
-
lines.push(`- **Remaining unconsolidated:** ${(pending -
|
|
23632
|
+
lines.push(`- **Clusters processed:** ${result3.clustersProcessed}`);
|
|
23633
|
+
lines.push(`- **Memories consolidated:** ${result3.memoriesConsolidated}`);
|
|
23634
|
+
lines.push(`- **Remaining unconsolidated:** ${(pending - result3.memoriesConsolidated).toLocaleString()}`);
|
|
23620
23635
|
return {
|
|
23621
23636
|
content: [{ type: "text", text: lines.join("\n") }]
|
|
23622
23637
|
};
|
|
@@ -23903,10 +23918,10 @@ function isCrdtSyncEnabled() {
|
|
|
23903
23918
|
async function rebuildFromDb() {
|
|
23904
23919
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
23905
23920
|
const client = getClient2();
|
|
23906
|
-
const
|
|
23921
|
+
const result3 = await client.execute(
|
|
23907
23922
|
"SELECT id, agent_id, agent_role, session_id, timestamp, tool_name, project_name, has_error, raw_text, version, author_device_id, scope FROM memories"
|
|
23908
23923
|
);
|
|
23909
|
-
const memories =
|
|
23924
|
+
const memories = result3.rows.map((row) => ({
|
|
23910
23925
|
id: String(row.id),
|
|
23911
23926
|
agent_id: row.agent_id,
|
|
23912
23927
|
agent_role: row.agent_role,
|
|
@@ -24040,12 +24055,12 @@ function loadPgClient() {
|
|
|
24040
24055
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
24041
24056
|
return {
|
|
24042
24057
|
async $queryRawUnsafe(query, ...values) {
|
|
24043
|
-
const
|
|
24044
|
-
return
|
|
24058
|
+
const result3 = await pool.query(query, values);
|
|
24059
|
+
return result3.rows;
|
|
24045
24060
|
},
|
|
24046
24061
|
async $executeRawUnsafe(query, ...values) {
|
|
24047
|
-
const
|
|
24048
|
-
return
|
|
24062
|
+
const result3 = await pool.query(query, values);
|
|
24063
|
+
return result3.rowCount ?? 0;
|
|
24049
24064
|
},
|
|
24050
24065
|
async $disconnect() {
|
|
24051
24066
|
await pool.end();
|
|
@@ -24256,8 +24271,8 @@ async function cloudPull(sinceVersion, config2) {
|
|
|
24256
24271
|
async function getCloudReuploadRequired(client = getClient()) {
|
|
24257
24272
|
try {
|
|
24258
24273
|
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
24259
|
-
const
|
|
24260
|
-
return
|
|
24274
|
+
const result3 = await client.execute("SELECT key, value FROM sync_meta WHERE key IN ('cloud_reupload_required', 'cloud_relink_required')");
|
|
24275
|
+
return result3.rows.some((row) => String(row.value ?? "") === "1");
|
|
24261
24276
|
} catch {
|
|
24262
24277
|
return false;
|
|
24263
24278
|
}
|
|
@@ -24878,8 +24893,8 @@ async function cloudPullBlob(route, config2) {
|
|
|
24878
24893
|
}
|
|
24879
24894
|
async function cloudPushGlobalProcedures(config2) {
|
|
24880
24895
|
const client = getClient();
|
|
24881
|
-
const
|
|
24882
|
-
const rows =
|
|
24896
|
+
const result3 = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
|
|
24897
|
+
const rows = result3.rows;
|
|
24883
24898
|
const { ok } = await cloudPushBlob(
|
|
24884
24899
|
"/sync/push-global-procedures",
|
|
24885
24900
|
rows,
|
|
@@ -24923,8 +24938,8 @@ async function cloudPullGlobalProcedures(config2) {
|
|
|
24923
24938
|
}
|
|
24924
24939
|
async function cloudPushBehaviors(config2) {
|
|
24925
24940
|
const client = getClient();
|
|
24926
|
-
const
|
|
24927
|
-
const rows =
|
|
24941
|
+
const result3 = await client.execute("SELECT * FROM behaviors LIMIT 10000");
|
|
24942
|
+
const rows = result3.rows;
|
|
24928
24943
|
const { ok } = await cloudPushBlob(
|
|
24929
24944
|
"/sync/push-behaviors",
|
|
24930
24945
|
rows,
|
|
@@ -25079,8 +25094,8 @@ async function cloudPullGraphRAG(config2) {
|
|
|
25079
25094
|
}
|
|
25080
25095
|
async function cloudPushTasks(config2) {
|
|
25081
25096
|
const client = getClient();
|
|
25082
|
-
const
|
|
25083
|
-
const rows =
|
|
25097
|
+
const result3 = await client.execute("SELECT * FROM tasks LIMIT 10000");
|
|
25098
|
+
const rows = result3.rows;
|
|
25084
25099
|
const { ok } = await cloudPushBlob(
|
|
25085
25100
|
"/sync/push-tasks",
|
|
25086
25101
|
rows,
|
|
@@ -25125,8 +25140,8 @@ async function cloudPullTasks(config2) {
|
|
|
25125
25140
|
}
|
|
25126
25141
|
async function cloudPushConversations(config2) {
|
|
25127
25142
|
const client = getClient();
|
|
25128
|
-
const
|
|
25129
|
-
const rows =
|
|
25143
|
+
const result3 = await client.execute("SELECT * FROM conversations LIMIT 50000");
|
|
25144
|
+
const rows = result3.rows;
|
|
25130
25145
|
const { ok } = await cloudPushBlob(
|
|
25131
25146
|
"/sync/push-conversations",
|
|
25132
25147
|
rows,
|
|
@@ -25938,14 +25953,14 @@ function registerBackupVps(server) {
|
|
|
25938
25953
|
r2AccessKeyId: input.r2AccessKeyId,
|
|
25939
25954
|
r2SecretAccessKey: input.r2SecretAccessKey
|
|
25940
25955
|
};
|
|
25941
|
-
const
|
|
25956
|
+
const result3 = await createBackup2(options);
|
|
25942
25957
|
return {
|
|
25943
25958
|
content: [
|
|
25944
25959
|
{
|
|
25945
25960
|
type: "text",
|
|
25946
|
-
text: `Backup complete: ${
|
|
25947
|
-
${
|
|
25948
|
-
${
|
|
25961
|
+
text: `Backup complete: ${result3.key}
|
|
25962
|
+
${result3.sizeBytes} bytes
|
|
25963
|
+
${result3.timestamp}`
|
|
25949
25964
|
}
|
|
25950
25965
|
]
|
|
25951
25966
|
};
|
|
@@ -25978,18 +25993,18 @@ ${result2.timestamp}`
|
|
|
25978
25993
|
r2AccessKeyId: input.r2AccessKeyId,
|
|
25979
25994
|
r2SecretAccessKey: input.r2SecretAccessKey
|
|
25980
25995
|
};
|
|
25981
|
-
const
|
|
25996
|
+
const result3 = await listBackups2(options);
|
|
25982
25997
|
return {
|
|
25983
25998
|
content: [
|
|
25984
25999
|
{
|
|
25985
26000
|
type: "text",
|
|
25986
|
-
text: formatBackups(
|
|
26001
|
+
text: formatBackups(result3)
|
|
25987
26002
|
}
|
|
25988
26003
|
]
|
|
25989
26004
|
};
|
|
25990
26005
|
}
|
|
25991
26006
|
case "health": {
|
|
25992
|
-
const
|
|
26007
|
+
const result3 = await backupHealth({
|
|
25993
26008
|
r2Bucket: input.r2Bucket,
|
|
25994
26009
|
r2Endpoint: input.r2Endpoint,
|
|
25995
26010
|
r2AccessKeyId: input.r2AccessKeyId,
|
|
@@ -26000,10 +26015,10 @@ ${result2.timestamp}`
|
|
|
26000
26015
|
{
|
|
26001
26016
|
type: "text",
|
|
26002
26017
|
text: [
|
|
26003
|
-
`last_backup: ${
|
|
26004
|
-
`backup_count: ${
|
|
26005
|
-
`total_size_bytes: ${
|
|
26006
|
-
`oldest_backup: ${
|
|
26018
|
+
`last_backup: ${result3.lastBackup ?? "none"}`,
|
|
26019
|
+
`backup_count: ${result3.backupCount}`,
|
|
26020
|
+
`total_size_bytes: ${result3.totalSizeBytes}`,
|
|
26021
|
+
`oldest_backup: ${result3.oldestBackup ?? "none"}`
|
|
26007
26022
|
].join("\n")
|
|
26008
26023
|
}
|
|
26009
26024
|
]
|
|
@@ -26115,9 +26130,9 @@ var init_hostinger_api = __esm({
|
|
|
26115
26130
|
}
|
|
26116
26131
|
this.lastRequestTime = Date.now();
|
|
26117
26132
|
}
|
|
26118
|
-
async request(method,
|
|
26133
|
+
async request(method, path62, body) {
|
|
26119
26134
|
await this.rateLimit();
|
|
26120
|
-
const url = `${this.baseUrl}${
|
|
26135
|
+
const url = `${this.baseUrl}${path62}`;
|
|
26121
26136
|
const headers = {
|
|
26122
26137
|
Authorization: `Bearer ${this.apiKey}`,
|
|
26123
26138
|
"Content-Type": "application/json",
|
|
@@ -26147,10 +26162,10 @@ var init_hostinger_api = __esm({
|
|
|
26147
26162
|
HostingerError = class extends Error {
|
|
26148
26163
|
status;
|
|
26149
26164
|
errorCode;
|
|
26150
|
-
constructor(
|
|
26165
|
+
constructor(status2, errorCode, message) {
|
|
26151
26166
|
super(message);
|
|
26152
26167
|
this.name = "HostingerError";
|
|
26153
|
-
this.status =
|
|
26168
|
+
this.status = status2;
|
|
26154
26169
|
this.errorCode = errorCode;
|
|
26155
26170
|
}
|
|
26156
26171
|
};
|
|
@@ -26186,8 +26201,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
|
|
|
26186
26201
|
}
|
|
26187
26202
|
return envelope.result;
|
|
26188
26203
|
}
|
|
26189
|
-
function buildUrl(zoneId,
|
|
26190
|
-
const normalizedPath =
|
|
26204
|
+
function buildUrl(zoneId, path62 = "/dns_records", query) {
|
|
26205
|
+
const normalizedPath = path62.startsWith("/") ? path62 : `/${path62}`;
|
|
26191
26206
|
const url = new URL(
|
|
26192
26207
|
`${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
|
|
26193
26208
|
);
|
|
@@ -26247,10 +26262,10 @@ var init_cloudflare_dns = __esm({
|
|
|
26247
26262
|
CloudflareError = class extends Error {
|
|
26248
26263
|
status;
|
|
26249
26264
|
errorCode;
|
|
26250
|
-
constructor(
|
|
26265
|
+
constructor(status2, errorCode, message) {
|
|
26251
26266
|
super(message);
|
|
26252
26267
|
this.name = "CloudflareError";
|
|
26253
|
-
this.status =
|
|
26268
|
+
this.status = status2;
|
|
26254
26269
|
this.errorCode = errorCode;
|
|
26255
26270
|
}
|
|
26256
26271
|
};
|
|
@@ -26300,7 +26315,7 @@ async function executeDeployment(params, client) {
|
|
|
26300
26315
|
process.stderr.write(`[deploy_client] Playbook complete. Verifying health...
|
|
26301
26316
|
`);
|
|
26302
26317
|
const healthy = await verifyHealth(domain);
|
|
26303
|
-
const
|
|
26318
|
+
const status2 = healthy ? DEPLOYED_STATUS : PLAYBOOK_COMPLETE_HEALTH_PENDING_STATUS;
|
|
26304
26319
|
process.stderr.write("[deploy_client] Recording VPS inventory...\n");
|
|
26305
26320
|
const inventory = buildInventoryRecord({
|
|
26306
26321
|
userId: user_id,
|
|
@@ -26321,7 +26336,7 @@ async function executeDeployment(params, client) {
|
|
|
26321
26336
|
plan: vps.plan,
|
|
26322
26337
|
ssh_port: vps.ssh_port,
|
|
26323
26338
|
ssh_access: `ssh exeai@${vps.ip_address}`,
|
|
26324
|
-
status,
|
|
26339
|
+
status: status2,
|
|
26325
26340
|
ansible_output: playbookResult,
|
|
26326
26341
|
dns_record_id: dnsRecordId,
|
|
26327
26342
|
inventory
|
|
@@ -26358,7 +26373,7 @@ function registerDeployClient(server) {
|
|
|
26358
26373
|
};
|
|
26359
26374
|
}
|
|
26360
26375
|
try {
|
|
26361
|
-
const
|
|
26376
|
+
const result3 = await executeDeployment({
|
|
26362
26377
|
client_name,
|
|
26363
26378
|
domain,
|
|
26364
26379
|
region,
|
|
@@ -26373,7 +26388,7 @@ function registerDeployClient(server) {
|
|
|
26373
26388
|
content: [
|
|
26374
26389
|
{
|
|
26375
26390
|
type: "text",
|
|
26376
|
-
text: JSON.stringify(
|
|
26391
|
+
text: JSON.stringify(result3, null, 2)
|
|
26377
26392
|
}
|
|
26378
26393
|
]
|
|
26379
26394
|
};
|
|
@@ -27165,12 +27180,12 @@ function registerListTriggers(server) {
|
|
|
27165
27180
|
};
|
|
27166
27181
|
}
|
|
27167
27182
|
const lines = triggers.map((t) => {
|
|
27168
|
-
const
|
|
27183
|
+
const status2 = t.enabled ? "active" : "disabled";
|
|
27169
27184
|
const condCount = t.conditions.length;
|
|
27170
27185
|
const actionTypes = t.actions.map((a) => a.type).join(", ");
|
|
27171
27186
|
const schedulePart = isScheduledTrigger(t) ? ` | schedule: ${t.schedule}` : "";
|
|
27172
27187
|
const projectPart = t.project ? ` | project: ${t.project}` : "";
|
|
27173
|
-
return `- **${t.name}** (${t.id}) [${
|
|
27188
|
+
return `- **${t.name}** (${t.id}) [${status2}]
|
|
27174
27189
|
Event: ${t.event} | Conditions: ${condCount} | Actions: ${actionTypes}` + schedulePart + projectPart;
|
|
27175
27190
|
});
|
|
27176
27191
|
const text3 = `${triggers.length} trigger(s) configured:
|
|
@@ -27566,8 +27581,8 @@ Available: ${available.length > 0 ? available.join(", ") : "none"}`
|
|
|
27566
27581
|
]
|
|
27567
27582
|
};
|
|
27568
27583
|
}
|
|
27569
|
-
const
|
|
27570
|
-
if (!
|
|
27584
|
+
const result3 = applyPack(industry, project);
|
|
27585
|
+
if (!result3) {
|
|
27571
27586
|
return {
|
|
27572
27587
|
content: [
|
|
27573
27588
|
{
|
|
@@ -27580,22 +27595,22 @@ Available: ${available.length > 0 ? available.join(", ") : "none"}`
|
|
|
27580
27595
|
const lines = [
|
|
27581
27596
|
`Applied "${industry}" starter pack to project "${project}":
|
|
27582
27597
|
`,
|
|
27583
|
-
`**CRM Custom Objects** (${
|
|
27584
|
-
...
|
|
27598
|
+
`**CRM Custom Objects** (${result3.customObjects.count}):`,
|
|
27599
|
+
...result3.customObjects.names.map((n) => ` - ${n}`),
|
|
27585
27600
|
"",
|
|
27586
|
-
`**Triggers Created** (${
|
|
27587
|
-
...
|
|
27601
|
+
`**Triggers Created** (${result3.triggers.created}):`,
|
|
27602
|
+
...result3.triggers.ids.map((id, i) => {
|
|
27588
27603
|
const t = pack.triggers[i];
|
|
27589
27604
|
return ` - ${t?.name ?? "Unknown"} (${id})`;
|
|
27590
27605
|
}),
|
|
27591
27606
|
"",
|
|
27592
|
-
`**Wiki Seeds** (${
|
|
27593
|
-
...
|
|
27607
|
+
`**Wiki Seeds** (${result3.wikiSeeds.count}):`,
|
|
27608
|
+
...result3.wikiSeeds.titles.map((t) => ` - ${t}`)
|
|
27594
27609
|
];
|
|
27595
|
-
if (
|
|
27610
|
+
if (result3.pendingVariables.length > 0) {
|
|
27596
27611
|
lines.push("");
|
|
27597
27612
|
lines.push("**Requires manual configuration:**");
|
|
27598
|
-
for (const pv of
|
|
27613
|
+
for (const pv of result3.pendingVariables) {
|
|
27599
27614
|
const vars = Object.entries(pv.variables).map(([k, v]) => ` - {{${k}}}: ${v}`).join("\n");
|
|
27600
27615
|
lines.push(` ${pv.trigger}:
|
|
27601
27616
|
${vars}`);
|
|
@@ -27983,11 +27998,11 @@ async function importIdentities(identities, updatedBy) {
|
|
|
27983
27998
|
}
|
|
27984
27999
|
async function getActiveProcedureTitles() {
|
|
27985
28000
|
const client = getClient();
|
|
27986
|
-
const
|
|
28001
|
+
const result3 = await client.execute({
|
|
27987
28002
|
sql: "SELECT title FROM company_procedures WHERE active = 1",
|
|
27988
28003
|
args: []
|
|
27989
28004
|
});
|
|
27990
|
-
return new Set(
|
|
28005
|
+
return new Set(result3.rows.map((row) => String(row.title)));
|
|
27991
28006
|
}
|
|
27992
28007
|
async function exportOrchestration(createdBy) {
|
|
27993
28008
|
const client = getClient();
|
|
@@ -28200,11 +28215,11 @@ function registerImportOrchestration(server) {
|
|
|
28200
28215
|
await initStore();
|
|
28201
28216
|
const raw = readFileSync33(package_path, "utf-8");
|
|
28202
28217
|
const pkg = validatePackage(JSON.parse(raw));
|
|
28203
|
-
const
|
|
28218
|
+
const result3 = await importOrchestration(pkg, merge_strategy);
|
|
28204
28219
|
return {
|
|
28205
28220
|
content: [{
|
|
28206
28221
|
type: "text",
|
|
28207
|
-
text: `Imported ${
|
|
28222
|
+
text: `Imported ${result3.imported.roster} roster entries, ${result3.imported.identities} identities, ${result3.imported.behaviors} behaviors, ${result3.imported.procedures} procedures using ${merge_strategy} strategy`
|
|
28208
28223
|
}]
|
|
28209
28224
|
};
|
|
28210
28225
|
} catch (err) {
|
|
@@ -28319,11 +28334,11 @@ Domain: ${domain ?? "none"}`
|
|
|
28319
28334
|
};
|
|
28320
28335
|
}
|
|
28321
28336
|
const client = getClient();
|
|
28322
|
-
const
|
|
28337
|
+
const result3 = await client.execute({
|
|
28323
28338
|
sql: "SELECT id, title, content, priority, domain FROM company_procedures WHERE id = ?",
|
|
28324
28339
|
args: [procedure_id]
|
|
28325
28340
|
});
|
|
28326
|
-
if (
|
|
28341
|
+
if (result3.rows.length === 0) {
|
|
28327
28342
|
return {
|
|
28328
28343
|
content: [{
|
|
28329
28344
|
type: "text",
|
|
@@ -28332,7 +28347,7 @@ Domain: ${domain ?? "none"}`
|
|
|
28332
28347
|
isError: true
|
|
28333
28348
|
};
|
|
28334
28349
|
}
|
|
28335
|
-
const row =
|
|
28350
|
+
const row = result3.rows[0];
|
|
28336
28351
|
const wasActive = await deactivateGlobalProcedure(procedure_id);
|
|
28337
28352
|
if (!wasActive) {
|
|
28338
28353
|
return {
|
|
@@ -28939,7 +28954,7 @@ function registerBehavior(server) {
|
|
|
28939
28954
|
args.push(proj);
|
|
28940
28955
|
}
|
|
28941
28956
|
const where = conditions.join(" AND ");
|
|
28942
|
-
const
|
|
28957
|
+
const result4 = await client2.execute({
|
|
28943
28958
|
sql: `SELECT id, agent_id, project_name, domain, content, active, created_at, updated_at
|
|
28944
28959
|
FROM behaviors
|
|
28945
28960
|
WHERE ${where}
|
|
@@ -28947,7 +28962,7 @@ function registerBehavior(server) {
|
|
|
28947
28962
|
LIMIT 50`,
|
|
28948
28963
|
args
|
|
28949
28964
|
});
|
|
28950
|
-
const behaviors =
|
|
28965
|
+
const behaviors = result4.rows.map((r) => rowToBehavior2(r));
|
|
28951
28966
|
if (behaviors.length === 0) {
|
|
28952
28967
|
return {
|
|
28953
28968
|
content: [{ type: "text", text: "No behaviors found." }]
|
|
@@ -29046,11 +29061,11 @@ Use /exe-forget to remove any that this supersedes.`;
|
|
|
29046
29061
|
};
|
|
29047
29062
|
}
|
|
29048
29063
|
const client = getClient();
|
|
29049
|
-
const
|
|
29064
|
+
const result3 = await client.execute({
|
|
29050
29065
|
sql: "SELECT id, agent_id, content, domain, priority FROM behaviors WHERE id = ?",
|
|
29051
29066
|
args: [behavior_id]
|
|
29052
29067
|
});
|
|
29053
|
-
if (
|
|
29068
|
+
if (result3.rows.length === 0) {
|
|
29054
29069
|
return {
|
|
29055
29070
|
content: [{
|
|
29056
29071
|
type: "text",
|
|
@@ -29059,7 +29074,7 @@ Use /exe-forget to remove any that this supersedes.`;
|
|
|
29059
29074
|
isError: true
|
|
29060
29075
|
};
|
|
29061
29076
|
}
|
|
29062
|
-
const row =
|
|
29077
|
+
const row = result3.rows[0];
|
|
29063
29078
|
const wasActive = await deactivateBehavior(behavior_id);
|
|
29064
29079
|
if (!wasActive) {
|
|
29065
29080
|
return {
|
|
@@ -29287,11 +29302,11 @@ function registerDeactivateGlobalProcedure(server) {
|
|
|
29287
29302
|
};
|
|
29288
29303
|
}
|
|
29289
29304
|
const client = getClient();
|
|
29290
|
-
const
|
|
29305
|
+
const result3 = await client.execute({
|
|
29291
29306
|
sql: "SELECT id, title, content, priority, domain FROM company_procedures WHERE id = ?",
|
|
29292
29307
|
args: [procedure_id]
|
|
29293
29308
|
});
|
|
29294
|
-
if (
|
|
29309
|
+
if (result3.rows.length === 0) {
|
|
29295
29310
|
return {
|
|
29296
29311
|
content: [{
|
|
29297
29312
|
type: "text",
|
|
@@ -29300,7 +29315,7 @@ function registerDeactivateGlobalProcedure(server) {
|
|
|
29300
29315
|
isError: true
|
|
29301
29316
|
};
|
|
29302
29317
|
}
|
|
29303
|
-
const row =
|
|
29318
|
+
const row = result3.rows[0];
|
|
29304
29319
|
const wasActive = await deactivateGlobalProcedure(procedure_id);
|
|
29305
29320
|
if (!wasActive) {
|
|
29306
29321
|
return {
|
|
@@ -29442,14 +29457,14 @@ function registerGetDecision(server) {
|
|
|
29442
29457
|
},
|
|
29443
29458
|
async ({ domain }) => {
|
|
29444
29459
|
const client = getClient();
|
|
29445
|
-
const
|
|
29460
|
+
const result3 = await client.execute({
|
|
29446
29461
|
sql: `SELECT id, agent_id, timestamp, raw_text, status, supersedes_id, project_name
|
|
29447
29462
|
FROM memories
|
|
29448
29463
|
WHERE memory_type = 'decision' AND source_path = ?
|
|
29449
29464
|
ORDER BY timestamp DESC`,
|
|
29450
29465
|
args: [domain]
|
|
29451
29466
|
});
|
|
29452
|
-
if (
|
|
29467
|
+
if (result3.rows.length === 0) {
|
|
29453
29468
|
return {
|
|
29454
29469
|
content: [
|
|
29455
29470
|
{
|
|
@@ -29459,7 +29474,7 @@ function registerGetDecision(server) {
|
|
|
29459
29474
|
]
|
|
29460
29475
|
};
|
|
29461
29476
|
}
|
|
29462
|
-
const decisions =
|
|
29477
|
+
const decisions = result3.rows.map((r) => ({
|
|
29463
29478
|
id: String(r.id),
|
|
29464
29479
|
agent_id: String(r.agent_id),
|
|
29465
29480
|
timestamp: String(r.timestamp),
|
|
@@ -29848,8 +29863,81 @@ var init_raw_data = __esm({
|
|
|
29848
29863
|
}
|
|
29849
29864
|
});
|
|
29850
29865
|
|
|
29851
|
-
// src/mcp/tools/
|
|
29866
|
+
// src/mcp/tools/company-actions.ts
|
|
29852
29867
|
import { z as z87 } from "zod";
|
|
29868
|
+
function format(payload) {
|
|
29869
|
+
return ["# Company Actions", "", JSON.stringify(payload, null, 2)].join("\n");
|
|
29870
|
+
}
|
|
29871
|
+
function registerCompanyActions(server) {
|
|
29872
|
+
server.registerTool(
|
|
29873
|
+
"company_actions",
|
|
29874
|
+
{
|
|
29875
|
+
title: "Company Actions",
|
|
29876
|
+
description: "Preview and execute external connector actions (Asana, WhatsApp) through exe-gateway with audit/safety gates.",
|
|
29877
|
+
inputSchema: {
|
|
29878
|
+
action: ACTION.describe("list_connectors, describe_connector, preview, execute, list_runs, get_run"),
|
|
29879
|
+
connector: z87.string().optional().describe("Connector to use, e.g. asana, whatsapp, airtable, notion"),
|
|
29880
|
+
connector_ref: z87.string().optional().describe("Exact connector ref from list_connectors when connector names overlap"),
|
|
29881
|
+
operation: z87.string().optional().describe("Connector operation, e.g. create_task or send_message"),
|
|
29882
|
+
payload: z87.record(z87.string(), z87.unknown()).optional().describe("Operation payload"),
|
|
29883
|
+
idempotency_key: z87.string().optional().describe("Stable key to prevent duplicate execution"),
|
|
29884
|
+
confirm_token: z87.string().optional().describe("Optional future approval token"),
|
|
29885
|
+
run_id: z87.string().optional().describe("Run id for get_run")
|
|
29886
|
+
}
|
|
29887
|
+
},
|
|
29888
|
+
async (input) => {
|
|
29889
|
+
const config2 = await loadConfig();
|
|
29890
|
+
const gatewayUrl = config2.gateway?.url || process.env.EXE_GATEWAY_URL;
|
|
29891
|
+
const authToken = config2.gateway?.authToken || process.env.EXE_GATEWAY_QUERY_AUTH_TOKEN || process.env.EXE_COMPANY_BRAIN_AUTH_TOKEN || process.env.EXE_GATEWAY_AUTH_TOKEN;
|
|
29892
|
+
if (!gatewayUrl) {
|
|
29893
|
+
return { content: [{ type: "text", text: "Company Actions not configured. Set gateway.url in ~/.exe-os/config.json" }] };
|
|
29894
|
+
}
|
|
29895
|
+
try {
|
|
29896
|
+
assertSecureGatewayUrlForToken(gatewayUrl, authToken);
|
|
29897
|
+
} catch (err) {
|
|
29898
|
+
return { content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }], isError: true };
|
|
29899
|
+
}
|
|
29900
|
+
let url;
|
|
29901
|
+
try {
|
|
29902
|
+
url = new URL("/actions", gatewayUrl);
|
|
29903
|
+
} catch (err) {
|
|
29904
|
+
return { content: [{ type: "text", text: `Company Actions not configured. Invalid gateway.url: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
29905
|
+
}
|
|
29906
|
+
try {
|
|
29907
|
+
const response = await fetch(url.toString(), {
|
|
29908
|
+
method: "POST",
|
|
29909
|
+
headers: {
|
|
29910
|
+
"Content-Type": "application/json",
|
|
29911
|
+
...authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
29912
|
+
},
|
|
29913
|
+
body: JSON.stringify(input),
|
|
29914
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS5)
|
|
29915
|
+
});
|
|
29916
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
29917
|
+
const payload = contentType.includes("application/json") ? await response.json() : await response.text();
|
|
29918
|
+
return {
|
|
29919
|
+
content: [{ type: "text", text: response.ok ? format(payload) : `Company Actions failed (${response.status}): ${typeof payload === "string" ? payload : JSON.stringify(payload)}` }],
|
|
29920
|
+
...response.ok ? {} : { isError: true }
|
|
29921
|
+
};
|
|
29922
|
+
} catch {
|
|
29923
|
+
return { content: [{ type: "text", text: `Gateway unreachable at ${url.origin}` }], isError: true };
|
|
29924
|
+
}
|
|
29925
|
+
}
|
|
29926
|
+
);
|
|
29927
|
+
}
|
|
29928
|
+
var FETCH_TIMEOUT_MS5, ACTION;
|
|
29929
|
+
var init_company_actions = __esm({
|
|
29930
|
+
"src/mcp/tools/company-actions.ts"() {
|
|
29931
|
+
"use strict";
|
|
29932
|
+
init_config();
|
|
29933
|
+
init_query_company_brain();
|
|
29934
|
+
FETCH_TIMEOUT_MS5 = 15e3;
|
|
29935
|
+
ACTION = z87.enum(["list_connectors", "describe_connector", "preview", "execute", "list_runs", "get_run"]);
|
|
29936
|
+
}
|
|
29937
|
+
});
|
|
29938
|
+
|
|
29939
|
+
// src/mcp/tools/create-bug-report.ts
|
|
29940
|
+
import { z as z88 } from "zod";
|
|
29853
29941
|
import crypto19 from "crypto";
|
|
29854
29942
|
import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
|
|
29855
29943
|
import path53 from "path";
|
|
@@ -29932,22 +30020,22 @@ function registerCreateBugReport(server) {
|
|
|
29932
30020
|
title: "Create Bug Report",
|
|
29933
30021
|
description: "Classify and file an exe-os issue as upstream_bug, customer_customization, emergency_hotfix, or unclear. Writes a local report, stores memory, and optionally sends to AskExe support when a support endpoint is configured.",
|
|
29934
30022
|
inputSchema: {
|
|
29935
|
-
title:
|
|
30023
|
+
title: z88.string().min(3).describe("Short descriptive title"),
|
|
29936
30024
|
classification: CLASSIFICATION.describe(
|
|
29937
30025
|
"upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
|
|
29938
30026
|
),
|
|
29939
30027
|
severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
|
|
29940
|
-
summary:
|
|
29941
|
-
customer_impact:
|
|
29942
|
-
reproduction_steps:
|
|
29943
|
-
expected:
|
|
29944
|
-
actual:
|
|
29945
|
-
files_changed:
|
|
29946
|
-
workaround:
|
|
29947
|
-
local_patch_diff:
|
|
29948
|
-
package_version:
|
|
29949
|
-
project_name:
|
|
29950
|
-
send_upstream:
|
|
30028
|
+
summary: z88.string().min(10).describe("What happened and why it matters"),
|
|
30029
|
+
customer_impact: z88.string().optional().describe("How this affects the customer/founder"),
|
|
30030
|
+
reproduction_steps: z88.array(z88.string()).optional().describe("Steps to reproduce"),
|
|
30031
|
+
expected: z88.string().optional().describe("Expected behavior"),
|
|
30032
|
+
actual: z88.string().optional().describe("Actual behavior"),
|
|
30033
|
+
files_changed: z88.array(z88.string()).optional().describe("Files changed or suspected"),
|
|
30034
|
+
workaround: z88.string().optional().describe("Temporary local workaround/hotfix, if any"),
|
|
30035
|
+
local_patch_diff: z88.string().optional().describe("Small local diff or patch summary"),
|
|
30036
|
+
package_version: z88.string().optional().describe("Installed @askexenow/exe-os version"),
|
|
30037
|
+
project_name: z88.string().optional().describe("Project/customer context"),
|
|
30038
|
+
send_upstream: z88.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
|
|
29951
30039
|
}
|
|
29952
30040
|
},
|
|
29953
30041
|
async ({
|
|
@@ -30063,13 +30151,13 @@ var init_create_bug_report = __esm({
|
|
|
30063
30151
|
init_config();
|
|
30064
30152
|
init_license();
|
|
30065
30153
|
init_store();
|
|
30066
|
-
CLASSIFICATION =
|
|
30154
|
+
CLASSIFICATION = z88.enum([
|
|
30067
30155
|
"upstream_bug",
|
|
30068
30156
|
"customer_customization",
|
|
30069
30157
|
"emergency_hotfix",
|
|
30070
30158
|
"unclear"
|
|
30071
30159
|
]);
|
|
30072
|
-
SEVERITY =
|
|
30160
|
+
SEVERITY = z88.enum(["p0", "p1", "p2", "p3"]);
|
|
30073
30161
|
}
|
|
30074
30162
|
});
|
|
30075
30163
|
|
|
@@ -30278,14 +30366,14 @@ async function safeJson2(res) {
|
|
|
30278
30366
|
function hasFailures(rows) {
|
|
30279
30367
|
return rows.some((row) => row.level === "fail");
|
|
30280
30368
|
}
|
|
30281
|
-
function summarizeHttpFailure(
|
|
30369
|
+
function summarizeHttpFailure(status2, data) {
|
|
30282
30370
|
const error = data?.error;
|
|
30283
|
-
return `${
|
|
30371
|
+
return `${status2} ${error?.message ?? JSON.stringify(data)}`;
|
|
30284
30372
|
}
|
|
30285
|
-
function nextForPostFailure(
|
|
30286
|
-
if (
|
|
30287
|
-
if (
|
|
30288
|
-
if (
|
|
30373
|
+
function nextForPostFailure(status2) {
|
|
30374
|
+
if (status2 === 401) return "License credentials were not sent. Run `exe-os support health` and check license_key_present.";
|
|
30375
|
+
if (status2 === 403) return "License is valid locally but not accepted by support intake. AskExe must check server-side license provisioning.";
|
|
30376
|
+
if (status2 >= 500) return "AskExe support intake is unhealthy server-side. Try again shortly and report the local file path.";
|
|
30289
30377
|
return "Run `exe-os support health`; if it passes, send this output to AskExe.";
|
|
30290
30378
|
}
|
|
30291
30379
|
var DEFAULT_BUG_ENDPOINT, DEFAULT_ADMIN_ENDPOINT;
|
|
@@ -30300,7 +30388,7 @@ var init_exe_support = __esm({
|
|
|
30300
30388
|
});
|
|
30301
30389
|
|
|
30302
30390
|
// src/mcp/tools/support.ts
|
|
30303
|
-
import { z as
|
|
30391
|
+
import { z as z89 } from "zod";
|
|
30304
30392
|
function formatRows(rows, mode) {
|
|
30305
30393
|
const lines = [`exe-os support ${mode}`, ""];
|
|
30306
30394
|
for (const row of rows) {
|
|
@@ -30341,7 +30429,7 @@ function registerSupportTools(server) {
|
|
|
30341
30429
|
title: "Support Test",
|
|
30342
30430
|
description: "End-to-end support intake smoke test. Files a clearly marked test report upstream and auto-closes it on AskExe machines with admin credentials.",
|
|
30343
30431
|
inputSchema: {
|
|
30344
|
-
project:
|
|
30432
|
+
project: z89.string().default("support-smoke").describe("Customer/project name, e.g. hygo")
|
|
30345
30433
|
}
|
|
30346
30434
|
},
|
|
30347
30435
|
async ({ project }) => {
|
|
@@ -30361,6 +30449,656 @@ var init_support = __esm({
|
|
|
30361
30449
|
}
|
|
30362
30450
|
});
|
|
30363
30451
|
|
|
30452
|
+
// src/bin/exe-status.ts
|
|
30453
|
+
async function status(targetEmployee) {
|
|
30454
|
+
if (!inTmux()) {
|
|
30455
|
+
return "Not in a tmux session. Start tmux first: tmux new-session -s work";
|
|
30456
|
+
}
|
|
30457
|
+
const employees = await loadEmployees();
|
|
30458
|
+
const names = employees.filter((e) => !isCoordinatorRole(e.role)).map((e) => e.name);
|
|
30459
|
+
const roles = new Map(employees.map((e) => [e.name, e.role ?? ""]));
|
|
30460
|
+
await fastDbInit();
|
|
30461
|
+
const client = getClient();
|
|
30462
|
+
const taskMap = /* @__PURE__ */ new Map();
|
|
30463
|
+
try {
|
|
30464
|
+
const esScope = sessionScopeFilter();
|
|
30465
|
+
const result3 = await client.execute({
|
|
30466
|
+
sql: `SELECT assigned_to, title, priority FROM tasks
|
|
30467
|
+
WHERE status = 'in_progress'${esScope.sql}
|
|
30468
|
+
ORDER BY priority ASC, created_at ASC`,
|
|
30469
|
+
args: [...esScope.args]
|
|
30470
|
+
});
|
|
30471
|
+
for (const row of result3.rows) {
|
|
30472
|
+
const assignee = String(row.assigned_to);
|
|
30473
|
+
if (!taskMap.has(assignee)) {
|
|
30474
|
+
taskMap.set(assignee, {
|
|
30475
|
+
title: String(row.title),
|
|
30476
|
+
priority: String(row.priority)
|
|
30477
|
+
});
|
|
30478
|
+
}
|
|
30479
|
+
}
|
|
30480
|
+
} catch {
|
|
30481
|
+
}
|
|
30482
|
+
if (targetEmployee) {
|
|
30483
|
+
if (!names.includes(targetEmployee)) {
|
|
30484
|
+
return `Employee "${targetEmployee}" not found. Available: ${names.join(", ")}`;
|
|
30485
|
+
}
|
|
30486
|
+
const statuses2 = getEmployeeStatuses([targetEmployee]);
|
|
30487
|
+
const s = statuses2[0];
|
|
30488
|
+
return formatStatusDeep(s, taskMap.get(targetEmployee), roles.get(targetEmployee) ?? "");
|
|
30489
|
+
}
|
|
30490
|
+
const statuses = getEmployeeStatuses(names);
|
|
30491
|
+
return formatStatusAll(statuses, taskMap, roles);
|
|
30492
|
+
}
|
|
30493
|
+
var init_exe_status = __esm({
|
|
30494
|
+
"src/bin/exe-status.ts"() {
|
|
30495
|
+
"use strict";
|
|
30496
|
+
init_employees();
|
|
30497
|
+
init_fast_db_init();
|
|
30498
|
+
init_database();
|
|
30499
|
+
init_tmux_status();
|
|
30500
|
+
init_is_main();
|
|
30501
|
+
init_task_scope();
|
|
30502
|
+
if (isMainModule(import.meta.url)) {
|
|
30503
|
+
const target = process.argv[2];
|
|
30504
|
+
status(target).then((output) => {
|
|
30505
|
+
process.stdout.write(output + "\n");
|
|
30506
|
+
}).catch((err) => {
|
|
30507
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
30508
|
+
`);
|
|
30509
|
+
process.exit(1);
|
|
30510
|
+
});
|
|
30511
|
+
}
|
|
30512
|
+
}
|
|
30513
|
+
});
|
|
30514
|
+
|
|
30515
|
+
// src/bin/exe-healthcheck.ts
|
|
30516
|
+
import { existsSync as existsSync43, readFileSync as readFileSync36, readdirSync as readdirSync14 } from "fs";
|
|
30517
|
+
import path55 from "path";
|
|
30518
|
+
import { execSync as execSync14 } from "child_process";
|
|
30519
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
30520
|
+
function findPackageRoot2() {
|
|
30521
|
+
let dir = path55.dirname(fileURLToPath6(import.meta.url));
|
|
30522
|
+
const { root } = path55.parse(dir);
|
|
30523
|
+
while (dir !== root) {
|
|
30524
|
+
if (existsSync43(path55.join(dir, "package.json"))) return dir;
|
|
30525
|
+
dir = path55.dirname(dir);
|
|
30526
|
+
}
|
|
30527
|
+
throw new Error("Cannot find package root");
|
|
30528
|
+
}
|
|
30529
|
+
function checkBuildIntegrity(pkgRoot) {
|
|
30530
|
+
const results = [];
|
|
30531
|
+
const tsupConfig = path55.join(pkgRoot, "tsup.config.ts");
|
|
30532
|
+
if (!existsSync43(tsupConfig)) {
|
|
30533
|
+
return [{ name: "build/tsup-config", pass: false, detail: "tsup.config.ts not found" }];
|
|
30534
|
+
}
|
|
30535
|
+
const configContent = readFileSync36(tsupConfig, "utf-8");
|
|
30536
|
+
const entryMatches = configContent.matchAll(/"([^"]+)":\s*"src\//g);
|
|
30537
|
+
const missing = [];
|
|
30538
|
+
let total = 0;
|
|
30539
|
+
for (const match of entryMatches) {
|
|
30540
|
+
const outputKey = match[1];
|
|
30541
|
+
const expectedPath = path55.join(pkgRoot, "dist", `${outputKey}.js`);
|
|
30542
|
+
total++;
|
|
30543
|
+
if (!existsSync43(expectedPath)) {
|
|
30544
|
+
missing.push(`dist/${outputKey}.js`);
|
|
30545
|
+
}
|
|
30546
|
+
}
|
|
30547
|
+
if (missing.length > 0) {
|
|
30548
|
+
results.push({
|
|
30549
|
+
name: "build/entry-points",
|
|
30550
|
+
pass: false,
|
|
30551
|
+
detail: `${missing.length}/${total} entry points missing:
|
|
30552
|
+
${missing.join("\n ")}`
|
|
30553
|
+
});
|
|
30554
|
+
} else {
|
|
30555
|
+
results.push({
|
|
30556
|
+
name: "build/entry-points",
|
|
30557
|
+
pass: true,
|
|
30558
|
+
detail: `${total} entry points verified`
|
|
30559
|
+
});
|
|
30560
|
+
}
|
|
30561
|
+
return results;
|
|
30562
|
+
}
|
|
30563
|
+
function checkEmbedPipeline(pkgRoot) {
|
|
30564
|
+
const results = [];
|
|
30565
|
+
const daemonPath = path55.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
30566
|
+
if (!existsSync43(daemonPath)) {
|
|
30567
|
+
results.push({
|
|
30568
|
+
name: "exed/daemon-exists",
|
|
30569
|
+
pass: false,
|
|
30570
|
+
detail: `exe-daemon.js not found at ${daemonPath}`
|
|
30571
|
+
});
|
|
30572
|
+
return results;
|
|
30573
|
+
}
|
|
30574
|
+
results.push({ name: "exed/daemon-exists", pass: true, detail: "dist/lib/exe-daemon.js exists" });
|
|
30575
|
+
const entryDirs = ["dist/hooks", "dist/bin", "dist/mcp"];
|
|
30576
|
+
for (const dir of entryDirs) {
|
|
30577
|
+
const fullDir = path55.join(pkgRoot, dir);
|
|
30578
|
+
if (!existsSync43(fullDir)) continue;
|
|
30579
|
+
let walkDir = fullDir;
|
|
30580
|
+
const { root } = path55.parse(walkDir);
|
|
30581
|
+
let foundRoot = null;
|
|
30582
|
+
while (walkDir !== root) {
|
|
30583
|
+
if (existsSync43(path55.join(walkDir, "package.json"))) {
|
|
30584
|
+
foundRoot = walkDir;
|
|
30585
|
+
break;
|
|
30586
|
+
}
|
|
30587
|
+
walkDir = path55.dirname(walkDir);
|
|
30588
|
+
}
|
|
30589
|
+
if (!foundRoot) {
|
|
30590
|
+
results.push({
|
|
30591
|
+
name: `exed/reachable-from-${dir}`,
|
|
30592
|
+
pass: false,
|
|
30593
|
+
detail: `Cannot find package root from ${dir}`
|
|
30594
|
+
});
|
|
30595
|
+
continue;
|
|
30596
|
+
}
|
|
30597
|
+
const resolvedDaemon = path55.join(foundRoot, "dist", "lib", "exe-daemon.js");
|
|
30598
|
+
const reachable = existsSync43(resolvedDaemon);
|
|
30599
|
+
results.push({
|
|
30600
|
+
name: `exed/reachable-from-${dir}`,
|
|
30601
|
+
pass: reachable,
|
|
30602
|
+
detail: reachable ? `Resolves to ${resolvedDaemon}` : `NOT FOUND: ${resolvedDaemon}`
|
|
30603
|
+
});
|
|
30604
|
+
}
|
|
30605
|
+
return results;
|
|
30606
|
+
}
|
|
30607
|
+
function checkTaskSystem(pkgRoot) {
|
|
30608
|
+
const results = [];
|
|
30609
|
+
const scannerPath = path55.join(pkgRoot, "dist", "bin", "scan-tasks.js");
|
|
30610
|
+
if (!existsSync43(scannerPath)) {
|
|
30611
|
+
results.push({ name: "tasks/scanner", pass: false, detail: "scan-tasks.js not found" });
|
|
30612
|
+
return results;
|
|
30613
|
+
}
|
|
30614
|
+
try {
|
|
30615
|
+
execSync14(`node "${scannerPath}" /tmp/nonexistent-healthcheck-test --format=json 2>/dev/null`, {
|
|
30616
|
+
timeout: 1e4,
|
|
30617
|
+
encoding: "utf-8"
|
|
30618
|
+
});
|
|
30619
|
+
results.push({ name: "tasks/scanner", pass: true, detail: "scan-tasks.js runs without import errors" });
|
|
30620
|
+
} catch (err) {
|
|
30621
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
30622
|
+
if (msg.includes("Cannot find module") || msg.includes("ERR_MODULE_NOT_FOUND") || msg.includes("SyntaxError")) {
|
|
30623
|
+
results.push({ name: "tasks/scanner", pass: false, detail: `Import error: ${msg.slice(0, 200)}` });
|
|
30624
|
+
} else {
|
|
30625
|
+
results.push({ name: "tasks/scanner", pass: true, detail: "scan-tasks.js runs (no import errors)" });
|
|
30626
|
+
}
|
|
30627
|
+
}
|
|
30628
|
+
return results;
|
|
30629
|
+
}
|
|
30630
|
+
function checkWorkerSpawning(pkgRoot) {
|
|
30631
|
+
const results = [];
|
|
30632
|
+
const workerPath = path55.join(pkgRoot, "dist", "hooks", "ingest-worker.js");
|
|
30633
|
+
if (!existsSync43(workerPath)) {
|
|
30634
|
+
results.push({ name: "workers/ingest-worker", pass: false, detail: "ingest-worker.js not found" });
|
|
30635
|
+
return results;
|
|
30636
|
+
}
|
|
30637
|
+
try {
|
|
30638
|
+
execSync14(`node --check "${workerPath}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
|
|
30639
|
+
results.push({ name: "workers/ingest-worker", pass: true, detail: "ingest-worker.js parses OK" });
|
|
30640
|
+
} catch (err) {
|
|
30641
|
+
results.push({
|
|
30642
|
+
name: "workers/ingest-worker",
|
|
30643
|
+
pass: false,
|
|
30644
|
+
detail: `Parse error: ${err instanceof Error ? err.message.slice(0, 200) : String(err)}`
|
|
30645
|
+
});
|
|
30646
|
+
}
|
|
30647
|
+
const hooksDir = path55.join(pkgRoot, "dist", "hooks");
|
|
30648
|
+
if (existsSync43(hooksDir)) {
|
|
30649
|
+
const hookFiles = readdirSync14(hooksDir).filter((f) => f.endsWith(".js") && !f.endsWith(".js.map"));
|
|
30650
|
+
let hooksPassed = 0;
|
|
30651
|
+
const hooksFailed = [];
|
|
30652
|
+
for (const hook of hookFiles) {
|
|
30653
|
+
try {
|
|
30654
|
+
execSync14(`node --check "${path55.join(hooksDir, hook)}" 2>&1`, { timeout: 1e4, encoding: "utf-8" });
|
|
30655
|
+
hooksPassed++;
|
|
30656
|
+
} catch {
|
|
30657
|
+
hooksFailed.push(hook);
|
|
30658
|
+
}
|
|
30659
|
+
}
|
|
30660
|
+
if (hooksFailed.length > 0) {
|
|
30661
|
+
results.push({
|
|
30662
|
+
name: "workers/hooks-parse",
|
|
30663
|
+
pass: false,
|
|
30664
|
+
detail: `${hooksFailed.length}/${hookFiles.length} hooks fail to parse: ${hooksFailed.join(", ")}`
|
|
30665
|
+
});
|
|
30666
|
+
} else {
|
|
30667
|
+
results.push({
|
|
30668
|
+
name: "workers/hooks-parse",
|
|
30669
|
+
pass: true,
|
|
30670
|
+
detail: `${hooksPassed} hook entry points parse OK`
|
|
30671
|
+
});
|
|
30672
|
+
}
|
|
30673
|
+
}
|
|
30674
|
+
return results;
|
|
30675
|
+
}
|
|
30676
|
+
function checkMcpTransport() {
|
|
30677
|
+
const results = [];
|
|
30678
|
+
const pidPath = path55.join(EXE_AI_DIR, "exed.pid");
|
|
30679
|
+
const tokenPath = path55.join(EXE_AI_DIR, "exed.token");
|
|
30680
|
+
let daemonAlive = false;
|
|
30681
|
+
if (existsSync43(pidPath)) {
|
|
30682
|
+
try {
|
|
30683
|
+
const pid = parseInt(readFileSync36(pidPath, "utf8").trim(), 10);
|
|
30684
|
+
process.kill(pid, 0);
|
|
30685
|
+
daemonAlive = true;
|
|
30686
|
+
results.push({ name: "mcp/daemon-process", pass: true, detail: `exed process alive (pid ${pid})` });
|
|
30687
|
+
} catch {
|
|
30688
|
+
results.push({ name: "mcp/daemon-process", pass: false, detail: "exed.pid exists but process is not alive; restart exe-os/exed" });
|
|
30689
|
+
}
|
|
30690
|
+
} else {
|
|
30691
|
+
results.push({ name: "mcp/daemon-process", pass: false, detail: "No exed.pid found; daemon is not running" });
|
|
30692
|
+
}
|
|
30693
|
+
if (daemonAlive && existsSync43(tokenPath)) {
|
|
30694
|
+
try {
|
|
30695
|
+
const token = readFileSync36(tokenPath, "utf8").trim();
|
|
30696
|
+
const response = execSync14(
|
|
30697
|
+
`curl -sS -i -m 2 -H "Authorization: Bearer ${token}" -H 'Accept: application/json, text/event-stream' http://127.0.0.1:48739/mcp`,
|
|
30698
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
30699
|
+
);
|
|
30700
|
+
const jsonRpcError = response.includes("Content-Type: application/json") && response.includes("missing MCP session");
|
|
30701
|
+
results.push({
|
|
30702
|
+
name: "mcp/http-endpoint",
|
|
30703
|
+
pass: jsonRpcError,
|
|
30704
|
+
detail: jsonRpcError ? "MCP HTTP endpoint reachable; missing-session probe returns JSON-RPC (expected)" : "MCP HTTP endpoint reachable but did not return expected JSON-RPC missing-session response"
|
|
30705
|
+
});
|
|
30706
|
+
} catch (err) {
|
|
30707
|
+
results.push({
|
|
30708
|
+
name: "mcp/http-endpoint",
|
|
30709
|
+
pass: false,
|
|
30710
|
+
detail: `MCP HTTP endpoint not reachable: ${err instanceof Error ? err.message.slice(0, 180) : String(err)}`
|
|
30711
|
+
});
|
|
30712
|
+
}
|
|
30713
|
+
} else if (daemonAlive) {
|
|
30714
|
+
results.push({ name: "mcp/http-endpoint", pass: false, detail: "Daemon is alive but exed.token is missing; cannot probe MCP HTTP" });
|
|
30715
|
+
}
|
|
30716
|
+
const events = readMcpHttpEvents(200);
|
|
30717
|
+
const summary = summarizeMcpTransport(events);
|
|
30718
|
+
results.push({
|
|
30719
|
+
name: "mcp/local-event-log",
|
|
30720
|
+
pass: true,
|
|
30721
|
+
detail: `${events.length} recent event(s); activeSessions=${summary.activeSessions ?? "unknown"}; lastHandshake=${summary.lastSuccessfulHandshake ?? "none"}; lastTool=${summary.lastSuccessfulToolCall ?? "none"}`
|
|
30722
|
+
});
|
|
30723
|
+
results.push({
|
|
30724
|
+
name: "mcp/monitor-summary",
|
|
30725
|
+
pass: true,
|
|
30726
|
+
detail: `Privacy-safe local monitor summary: ${path55.join(EXE_AI_DIR, "monitor", "mcp-transport-summary.json")}`
|
|
30727
|
+
});
|
|
30728
|
+
return results;
|
|
30729
|
+
}
|
|
30730
|
+
function checkClaudeCodeInstall() {
|
|
30731
|
+
const results = [];
|
|
30732
|
+
const execPath = process.env.CLAUDE_CODE_EXECPATH ?? "";
|
|
30733
|
+
if (execPath.length > 0 && (execPath.includes("claude/versions/") || execPath.includes("claude.exe") || execPath.includes("claude-native"))) {
|
|
30734
|
+
results.push({
|
|
30735
|
+
name: "cc/execpath-clean",
|
|
30736
|
+
pass: false,
|
|
30737
|
+
detail: `CLAUDE_CODE_EXECPATH points to native binary: "${execPath}" \u2014 20K phantom billing risk. Unset it: unset CLAUDE_CODE_EXECPATH`
|
|
30738
|
+
});
|
|
30739
|
+
} else {
|
|
30740
|
+
results.push({
|
|
30741
|
+
name: "cc/execpath-clean",
|
|
30742
|
+
pass: true,
|
|
30743
|
+
detail: execPath ? `CLAUDE_CODE_EXECPATH=${execPath} (node runtime, OK)` : "CLAUDE_CODE_EXECPATH is unset"
|
|
30744
|
+
});
|
|
30745
|
+
}
|
|
30746
|
+
try {
|
|
30747
|
+
const claudePath = execSync14("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
30748
|
+
if (!claudePath) {
|
|
30749
|
+
results.push({
|
|
30750
|
+
name: "cc/cli-binary",
|
|
30751
|
+
pass: false,
|
|
30752
|
+
detail: "claude not found in PATH"
|
|
30753
|
+
});
|
|
30754
|
+
} else {
|
|
30755
|
+
let resolved = claudePath;
|
|
30756
|
+
try {
|
|
30757
|
+
resolved = execSync14(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
|
|
30758
|
+
encoding: "utf8",
|
|
30759
|
+
timeout: 5e3
|
|
30760
|
+
}).trim();
|
|
30761
|
+
} catch {
|
|
30762
|
+
}
|
|
30763
|
+
if (resolved.includes("bin/claude.exe") || resolved.includes("bin/claude-native")) {
|
|
30764
|
+
results.push({
|
|
30765
|
+
name: "cc/cli-binary",
|
|
30766
|
+
pass: false,
|
|
30767
|
+
detail: `claude resolves to native binary: ${resolved}. Should be cli.js. Run: npm install -g @anthropic-ai/claude-code@2.1.98`
|
|
30768
|
+
});
|
|
30769
|
+
} else {
|
|
30770
|
+
results.push({
|
|
30771
|
+
name: "cc/cli-binary",
|
|
30772
|
+
pass: true,
|
|
30773
|
+
detail: `claude resolves to: ${resolved}`
|
|
30774
|
+
});
|
|
30775
|
+
}
|
|
30776
|
+
}
|
|
30777
|
+
} catch {
|
|
30778
|
+
results.push({
|
|
30779
|
+
name: "cc/cli-binary",
|
|
30780
|
+
pass: false,
|
|
30781
|
+
detail: "Failed to check claude binary path"
|
|
30782
|
+
});
|
|
30783
|
+
}
|
|
30784
|
+
const versionsDir = path55.join(
|
|
30785
|
+
process.env.HOME ?? process.env.USERPROFILE ?? "",
|
|
30786
|
+
".local",
|
|
30787
|
+
"share",
|
|
30788
|
+
"claude",
|
|
30789
|
+
"versions"
|
|
30790
|
+
);
|
|
30791
|
+
if (existsSync43(versionsDir)) {
|
|
30792
|
+
try {
|
|
30793
|
+
const entries = readdirSync14(versionsDir);
|
|
30794
|
+
if (entries.length > 0) {
|
|
30795
|
+
results.push({
|
|
30796
|
+
name: "cc/native-cache-clean",
|
|
30797
|
+
pass: false,
|
|
30798
|
+
detail: `${entries.length} cached native version(s) found in ${versionsDir}: ${entries.slice(0, 3).join(", ")}${entries.length > 3 ? "..." : ""}. Remove: rm -rf "${versionsDir}"`
|
|
30799
|
+
});
|
|
30800
|
+
} else {
|
|
30801
|
+
results.push({
|
|
30802
|
+
name: "cc/native-cache-clean",
|
|
30803
|
+
pass: true,
|
|
30804
|
+
detail: `${versionsDir} is empty`
|
|
30805
|
+
});
|
|
30806
|
+
}
|
|
30807
|
+
} catch {
|
|
30808
|
+
results.push({
|
|
30809
|
+
name: "cc/native-cache-clean",
|
|
30810
|
+
pass: true,
|
|
30811
|
+
detail: `${versionsDir} not readable (OK)`
|
|
30812
|
+
});
|
|
30813
|
+
}
|
|
30814
|
+
} else {
|
|
30815
|
+
results.push({
|
|
30816
|
+
name: "cc/native-cache-clean",
|
|
30817
|
+
pass: true,
|
|
30818
|
+
detail: `${versionsDir} does not exist`
|
|
30819
|
+
});
|
|
30820
|
+
}
|
|
30821
|
+
const disableOld = process.env.DISABLE_AUTOUPDATER === "1";
|
|
30822
|
+
const disableNew = process.env.CLAUDE_CODE_AUTOUPDATER_DISABLED === "1";
|
|
30823
|
+
if (!disableOld && !disableNew) {
|
|
30824
|
+
results.push({
|
|
30825
|
+
name: "cc/autoupdater-disabled",
|
|
30826
|
+
pass: false,
|
|
30827
|
+
detail: "Neither DISABLE_AUTOUPDATER=1 nor CLAUDE_CODE_AUTOUPDATER_DISABLED=1 is set. Auto-updater may install infected native binary. Export both in your shell profile."
|
|
30828
|
+
});
|
|
30829
|
+
} else {
|
|
30830
|
+
const which = [
|
|
30831
|
+
disableOld ? "DISABLE_AUTOUPDATER=1" : null,
|
|
30832
|
+
disableNew ? "CLAUDE_CODE_AUTOUPDATER_DISABLED=1" : null
|
|
30833
|
+
].filter(Boolean).join(" + ");
|
|
30834
|
+
results.push({
|
|
30835
|
+
name: "cc/autoupdater-disabled",
|
|
30836
|
+
pass: true,
|
|
30837
|
+
detail: `Auto-updater disabled via ${which}`
|
|
30838
|
+
});
|
|
30839
|
+
}
|
|
30840
|
+
try {
|
|
30841
|
+
const ccVersion = execSync14("claude --version 2>/dev/null || echo unknown", {
|
|
30842
|
+
encoding: "utf8",
|
|
30843
|
+
timeout: 5e3
|
|
30844
|
+
}).trim();
|
|
30845
|
+
const versionMatch = ccVersion.match(/(\d+\.\d+\.\d+)/);
|
|
30846
|
+
if (versionMatch) {
|
|
30847
|
+
const ver = versionMatch[1];
|
|
30848
|
+
const [, minor] = ver.split(".").map(Number);
|
|
30849
|
+
const isRisky = minor !== void 0 && minor >= 1 && parseInt(ver.split(".")[2] ?? "0") >= 119;
|
|
30850
|
+
results.push({
|
|
30851
|
+
name: "cc/version",
|
|
30852
|
+
pass: !isRisky,
|
|
30853
|
+
detail: isRisky ? `CC version ${ver} \u2014 \u22652.1.119 ships native binary only. Pin: npm install -g @anthropic-ai/claude-code@2.1.98` : `CC version ${ver}`
|
|
30854
|
+
});
|
|
30855
|
+
}
|
|
30856
|
+
} catch {
|
|
30857
|
+
}
|
|
30858
|
+
return results;
|
|
30859
|
+
}
|
|
30860
|
+
function runHealthCheck() {
|
|
30861
|
+
const pkgRoot = findPackageRoot2();
|
|
30862
|
+
const results = [
|
|
30863
|
+
...checkBuildIntegrity(pkgRoot),
|
|
30864
|
+
...checkEmbedPipeline(pkgRoot),
|
|
30865
|
+
...checkTaskSystem(pkgRoot),
|
|
30866
|
+
...checkWorkerSpawning(pkgRoot),
|
|
30867
|
+
...checkMcpTransport(),
|
|
30868
|
+
...checkClaudeCodeInstall()
|
|
30869
|
+
];
|
|
30870
|
+
const passed = results.filter((r) => r.pass).length;
|
|
30871
|
+
const failed = results.filter((r) => !r.pass).length;
|
|
30872
|
+
return { results, passed, failed };
|
|
30873
|
+
}
|
|
30874
|
+
var init_exe_healthcheck = __esm({
|
|
30875
|
+
"src/bin/exe-healthcheck.ts"() {
|
|
30876
|
+
"use strict";
|
|
30877
|
+
init_is_main();
|
|
30878
|
+
init_config();
|
|
30879
|
+
init_mcp_transport_health();
|
|
30880
|
+
if (isMainModule(import.meta.url)) {
|
|
30881
|
+
const { results, passed, failed } = runHealthCheck();
|
|
30882
|
+
console.log("\n exe-os Health Check\n");
|
|
30883
|
+
for (const r of results) {
|
|
30884
|
+
const icon = r.pass ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
30885
|
+
console.log(` ${icon} ${r.name}`);
|
|
30886
|
+
console.log(` ${r.detail}`);
|
|
30887
|
+
}
|
|
30888
|
+
console.log(`
|
|
30889
|
+
${passed} passed, ${failed} failed
|
|
30890
|
+
`);
|
|
30891
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
30892
|
+
}
|
|
30893
|
+
}
|
|
30894
|
+
});
|
|
30895
|
+
|
|
30896
|
+
// src/lib/update-check.ts
|
|
30897
|
+
var update_check_exports = {};
|
|
30898
|
+
__export(update_check_exports, {
|
|
30899
|
+
checkForUpdate: () => checkForUpdate,
|
|
30900
|
+
getLocalVersion: () => getLocalVersion,
|
|
30901
|
+
getRemoteVersion: () => getRemoteVersion
|
|
30902
|
+
});
|
|
30903
|
+
import { execSync as execSync15 } from "child_process";
|
|
30904
|
+
import { readFileSync as readFileSync37 } from "fs";
|
|
30905
|
+
import path56 from "path";
|
|
30906
|
+
function getLocalVersion(packageRoot) {
|
|
30907
|
+
const pkgPath = path56.join(packageRoot, "package.json");
|
|
30908
|
+
const pkg = JSON.parse(readFileSync37(pkgPath, "utf-8"));
|
|
30909
|
+
return pkg.version;
|
|
30910
|
+
}
|
|
30911
|
+
function getRemoteVersion() {
|
|
30912
|
+
try {
|
|
30913
|
+
const output = execSync15("npm view @askexenow/exe-os version", {
|
|
30914
|
+
encoding: "utf-8",
|
|
30915
|
+
timeout: 15e3,
|
|
30916
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
30917
|
+
});
|
|
30918
|
+
return output.trim();
|
|
30919
|
+
} catch {
|
|
30920
|
+
return null;
|
|
30921
|
+
}
|
|
30922
|
+
}
|
|
30923
|
+
function checkForUpdate(packageRoot) {
|
|
30924
|
+
const localVersion = getLocalVersion(packageRoot);
|
|
30925
|
+
const remoteVersion = getRemoteVersion();
|
|
30926
|
+
if (!remoteVersion) {
|
|
30927
|
+
return {
|
|
30928
|
+
updateAvailable: false,
|
|
30929
|
+
localVersion,
|
|
30930
|
+
error: "Could not reach npm registry or package not published yet"
|
|
30931
|
+
};
|
|
30932
|
+
}
|
|
30933
|
+
if (remoteVersion === localVersion) {
|
|
30934
|
+
return { updateAvailable: false, localVersion, remoteVersion };
|
|
30935
|
+
}
|
|
30936
|
+
return { updateAvailable: true, localVersion, remoteVersion };
|
|
30937
|
+
}
|
|
30938
|
+
var init_update_check = __esm({
|
|
30939
|
+
"src/lib/update-check.ts"() {
|
|
30940
|
+
"use strict";
|
|
30941
|
+
}
|
|
30942
|
+
});
|
|
30943
|
+
|
|
30944
|
+
// src/mcp/tools/cli-parity.ts
|
|
30945
|
+
import { execFile as execFile2 } from "child_process";
|
|
30946
|
+
import { promisify as promisify2 } from "util";
|
|
30947
|
+
import { z as z90 } from "zod";
|
|
30948
|
+
async function runCommand(command, args, timeout = 6e4) {
|
|
30949
|
+
const printable = [command, ...args].join(" ");
|
|
30950
|
+
try {
|
|
30951
|
+
const { stdout, stderr } = await execFileAsync2(command, args, {
|
|
30952
|
+
timeout,
|
|
30953
|
+
maxBuffer: 1024 * 1024,
|
|
30954
|
+
env: process.env
|
|
30955
|
+
});
|
|
30956
|
+
return { ok: true, command: printable, text: `${stdout}${stderr ? `
|
|
30957
|
+
${stderr}` : ""}`.trim() || "OK" };
|
|
30958
|
+
} catch (err) {
|
|
30959
|
+
const e = err;
|
|
30960
|
+
const text3 = `${e.stdout ?? ""}${e.stderr ? `
|
|
30961
|
+
${e.stderr}` : ""}`.trim() || e.message || "Command failed";
|
|
30962
|
+
return { ok: false, command: printable, text: text3 };
|
|
30963
|
+
}
|
|
30964
|
+
}
|
|
30965
|
+
function result2(text3, structured, isError = false) {
|
|
30966
|
+
return { content: [{ type: "text", text: text3 }], structuredContent: structured, isError };
|
|
30967
|
+
}
|
|
30968
|
+
function registerCliParityTools(server) {
|
|
30969
|
+
server.registerTool("healthcheck", {
|
|
30970
|
+
title: "Health Check",
|
|
30971
|
+
description: "Run the exe-os product health check and return structured pass/fail results.",
|
|
30972
|
+
inputSchema: {}
|
|
30973
|
+
}, async () => {
|
|
30974
|
+
const out = runHealthCheck();
|
|
30975
|
+
const text3 = ["exe-os healthcheck", "", ...out.results.map((r) => `${r.pass ? "\u2705" : "\u274C"} ${r.name}: ${r.detail}`), "", `${out.passed} passed, ${out.failed} failed`].join("\n");
|
|
30976
|
+
return result2(text3, out, out.failed > 0);
|
|
30977
|
+
});
|
|
30978
|
+
server.registerTool("doctor", {
|
|
30979
|
+
title: "Doctor",
|
|
30980
|
+
description: "Run exe-os doctor audit. Defaults to read-only diagnostics; optional dry-run/fix flags mirror CLI.",
|
|
30981
|
+
inputSchema: {
|
|
30982
|
+
agent: z90.string().optional(),
|
|
30983
|
+
project: z90.string().optional(),
|
|
30984
|
+
verbose: z90.boolean().default(false),
|
|
30985
|
+
conflicts: z90.boolean().default(false),
|
|
30986
|
+
dry_run: z90.boolean().default(false),
|
|
30987
|
+
fix: z90.boolean().default(false)
|
|
30988
|
+
}
|
|
30989
|
+
}, async ({ agent, project, verbose, conflicts, dry_run, fix }) => {
|
|
30990
|
+
const args = [];
|
|
30991
|
+
if (agent) args.push("--agent", agent);
|
|
30992
|
+
if (project) args.push("--project", project);
|
|
30993
|
+
if (verbose) args.push("--verbose");
|
|
30994
|
+
if (conflicts) args.push("--conflicts");
|
|
30995
|
+
if (dry_run) args.push("--dry-run");
|
|
30996
|
+
if (fix) args.push("--fix");
|
|
30997
|
+
const out = await runCommand("exe-doctor", args, 12e4);
|
|
30998
|
+
return result2(out.text, { ok: out.ok, command: out.command }, !out.ok);
|
|
30999
|
+
});
|
|
31000
|
+
server.registerTool("rename_employee", {
|
|
31001
|
+
title: "Rename Employee",
|
|
31002
|
+
description: "Rename an employee using the same path as `exe-os rename <old> <new>`. Use for customer roster/identity renames.",
|
|
31003
|
+
inputSchema: {
|
|
31004
|
+
old_name: z90.string().min(1),
|
|
31005
|
+
new_name: z90.string().min(1),
|
|
31006
|
+
dry_run: z90.boolean().default(false)
|
|
31007
|
+
}
|
|
31008
|
+
}, async ({ old_name, new_name, dry_run }) => {
|
|
31009
|
+
if (dry_run) {
|
|
31010
|
+
const text3 = `Would run: exe-os rename ${old_name} ${new_name}`;
|
|
31011
|
+
return result2(text3, { ok: true, dry_run: true, old_name, new_name });
|
|
31012
|
+
}
|
|
31013
|
+
const out = await runCommand("exe-os", ["rename", old_name, new_name], 6e4);
|
|
31014
|
+
return result2(out.text, { ok: out.ok, command: out.command, old_name, new_name }, !out.ok);
|
|
31015
|
+
});
|
|
31016
|
+
server.registerTool("status_brief", {
|
|
31017
|
+
title: "Status Brief",
|
|
31018
|
+
description: "Return current employee/tmux status. Mirrors `exe-status` and supports optional deep view for one employee.",
|
|
31019
|
+
inputSchema: { employee: z90.string().optional() }
|
|
31020
|
+
}, async ({ employee }) => {
|
|
31021
|
+
const text3 = await status(employee);
|
|
31022
|
+
return result2(text3, { ok: true, employee: employee ?? null });
|
|
31023
|
+
});
|
|
31024
|
+
server.registerTool("pending_work_summary", {
|
|
31025
|
+
title: "Pending Work Summary",
|
|
31026
|
+
description: "Return pending reviews, messages, and notifications using the same summaries as the CLI tools.",
|
|
31027
|
+
inputSchema: { agent: z90.string().optional() }
|
|
31028
|
+
}, async ({ agent }) => {
|
|
31029
|
+
const parts = await Promise.all([
|
|
31030
|
+
runCommand("exe-pending-reviews", [], 3e4),
|
|
31031
|
+
runCommand("exe-pending-messages", agent ? [agent] : [], 3e4),
|
|
31032
|
+
runCommand("exe-pending-notifications", agent ? [agent] : [], 3e4)
|
|
31033
|
+
]);
|
|
31034
|
+
const text3 = ["Pending work summary", "", "## Reviews", parts[0].text, "", "## Messages", parts[1].text, "", "## Notifications", parts[2].text].join("\n");
|
|
31035
|
+
return result2(text3, { ok: parts.every((p) => p.ok), commands: parts.map((p) => p.command) }, parts.some((p) => !p.ok));
|
|
31036
|
+
});
|
|
31037
|
+
server.registerTool("key_status", {
|
|
31038
|
+
title: "Key Status",
|
|
31039
|
+
description: "Read-only Exe OS key status. Does not reveal recovery phrase or rotate keys.",
|
|
31040
|
+
inputSchema: {}
|
|
31041
|
+
}, async () => {
|
|
31042
|
+
const out = await runCommand("exe-os", ["key", "status"], 3e4);
|
|
31043
|
+
return result2(out.text, { ok: out.ok, command: out.command }, !out.ok);
|
|
31044
|
+
});
|
|
31045
|
+
server.registerTool("key_rotation_preflight", {
|
|
31046
|
+
title: "Key Rotation Preflight",
|
|
31047
|
+
description: "Dry-run key rotation/update preflight. No destructive changes.",
|
|
31048
|
+
inputSchema: { mode: z90.enum(["rotate", "update"]).default("rotate") }
|
|
31049
|
+
}, async ({ mode }) => {
|
|
31050
|
+
const out = await runCommand("exe-os", ["key", mode, "--dry-run"], 6e4);
|
|
31051
|
+
return result2(out.text, { ok: out.ok, command: out.command, mode }, !out.ok);
|
|
31052
|
+
});
|
|
31053
|
+
server.registerTool("check_update", {
|
|
31054
|
+
title: "Check Update",
|
|
31055
|
+
description: "Check npm for an available exe-os update without installing it.",
|
|
31056
|
+
inputSchema: {}
|
|
31057
|
+
}, async () => {
|
|
31058
|
+
const packageRoot = new URL("../../..", import.meta.url).pathname;
|
|
31059
|
+
const info = checkForUpdate(packageRoot);
|
|
31060
|
+
const text3 = info.error ? `Update check failed: ${info.error}` : info.updateAvailable ? `Update available: v${info.localVersion} \u2192 v${info.remoteVersion}` : `exe-os is up to date (v${info.localVersion})`;
|
|
31061
|
+
return result2(text3, { ok: !info.error, ...info }, Boolean(info.error));
|
|
31062
|
+
});
|
|
31063
|
+
server.registerTool("stack_update_check", {
|
|
31064
|
+
title: "Stack Update Check",
|
|
31065
|
+
description: "Plan/check a customer stack update without applying Docker changes. Mirrors `exe-os stack-update --check`.",
|
|
31066
|
+
inputSchema: {
|
|
31067
|
+
target: z90.string().optional(),
|
|
31068
|
+
manifest: z90.string().optional(),
|
|
31069
|
+
compose_file: z90.string().optional(),
|
|
31070
|
+
env_file: z90.string().optional(),
|
|
31071
|
+
deployment_persona: z90.enum(["customer", "askexe-control-plane"]).default("customer")
|
|
31072
|
+
}
|
|
31073
|
+
}, async ({ target, manifest, compose_file, env_file, deployment_persona }) => {
|
|
31074
|
+
const args = ["stack-update", "--check", "--deployment-persona", deployment_persona];
|
|
31075
|
+
if (target) args.push("--target", target);
|
|
31076
|
+
if (manifest) args.push("--manifest", manifest);
|
|
31077
|
+
if (compose_file) args.push("--compose-file", compose_file);
|
|
31078
|
+
if (env_file) args.push("--env-file", env_file);
|
|
31079
|
+
const out = await runCommand("exe-os", args, 9e4);
|
|
31080
|
+
return result2(out.text, { ok: out.ok, command: out.command }, !out.ok);
|
|
31081
|
+
});
|
|
31082
|
+
server.registerTool("cloud_status", {
|
|
31083
|
+
title: "Cloud Status",
|
|
31084
|
+
description: "Read-only cloud sync status. Does not reveal recovery phrase.",
|
|
31085
|
+
inputSchema: {}
|
|
31086
|
+
}, async () => {
|
|
31087
|
+
const out = await runCommand("exe-os", ["cloud", "status"], 45e3);
|
|
31088
|
+
return result2(out.text, { ok: out.ok, command: out.command }, !out.ok);
|
|
31089
|
+
});
|
|
31090
|
+
}
|
|
31091
|
+
var execFileAsync2;
|
|
31092
|
+
var init_cli_parity = __esm({
|
|
31093
|
+
"src/mcp/tools/cli-parity.ts"() {
|
|
31094
|
+
"use strict";
|
|
31095
|
+
init_exe_status();
|
|
31096
|
+
init_exe_healthcheck();
|
|
31097
|
+
init_update_check();
|
|
31098
|
+
execFileAsync2 = promisify2(execFile2);
|
|
31099
|
+
}
|
|
31100
|
+
});
|
|
31101
|
+
|
|
30364
31102
|
// src/lib/session-events.ts
|
|
30365
31103
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
30366
31104
|
async function ensureSessionEventsTable(client) {
|
|
@@ -30415,7 +31153,7 @@ async function listRecentSessionEvents(client, options) {
|
|
|
30415
31153
|
const where = `WHERE ${conditions.join(" AND ")}${scope.sql}`;
|
|
30416
31154
|
args.push(...scope.args);
|
|
30417
31155
|
args.push(Math.min(Math.max(options.limit ?? 20, 1), 100));
|
|
30418
|
-
const
|
|
31156
|
+
const result3 = await client.execute({
|
|
30419
31157
|
sql: `SELECT id, agent_id, agent_role, session_id, session_scope,
|
|
30420
31158
|
project_name, event_index, event_type, tool_name, tool_use_id,
|
|
30421
31159
|
content, payload_json, has_error, created_at
|
|
@@ -30425,7 +31163,7 @@ async function listRecentSessionEvents(client, options) {
|
|
|
30425
31163
|
LIMIT ?`,
|
|
30426
31164
|
args
|
|
30427
31165
|
});
|
|
30428
|
-
return
|
|
31166
|
+
return result3.rows.map((row) => ({
|
|
30429
31167
|
id: String(row.id),
|
|
30430
31168
|
agentId: String(row.agent_id),
|
|
30431
31169
|
agentRole: String(row.agent_role),
|
|
@@ -30451,7 +31189,7 @@ var init_session_events = __esm({
|
|
|
30451
31189
|
});
|
|
30452
31190
|
|
|
30453
31191
|
// src/mcp/tools/get-session-events.ts
|
|
30454
|
-
import { z as
|
|
31192
|
+
import { z as z91 } from "zod";
|
|
30455
31193
|
function canReadAgent(activeRole, activeAgent, requestedAgent) {
|
|
30456
31194
|
return requestedAgent === activeAgent || activeRole === "COO" || activeRole === "CTO";
|
|
30457
31195
|
}
|
|
@@ -30475,11 +31213,11 @@ function registerGetSessionEvents(server) {
|
|
|
30475
31213
|
title: "Get Session Events",
|
|
30476
31214
|
description: "Return exact recent chronological user prompts, assistant responses, and tool calls from the append-only session journal. Use this when asked what happened last, not semantic memory search.",
|
|
30477
31215
|
inputSchema: {
|
|
30478
|
-
agent_id:
|
|
30479
|
-
session_id:
|
|
31216
|
+
agent_id: z91.string().optional().describe("Agent to inspect. Defaults to active agent. COO/CTO may inspect others."),
|
|
31217
|
+
session_id: z91.string().optional().describe("Optional exact runtime session id."),
|
|
30480
31218
|
event_type: EVENT_TYPE.optional().describe("Filter to one event type."),
|
|
30481
|
-
project_name:
|
|
30482
|
-
limit:
|
|
31219
|
+
project_name: z91.string().optional().describe("Optional project filter. Pass 'all' for all projects."),
|
|
31220
|
+
limit: z91.number().int().min(1).max(100).default(20).describe("Number of events to return.")
|
|
30483
31221
|
}
|
|
30484
31222
|
},
|
|
30485
31223
|
async ({ agent_id, session_id, event_type, project_name, limit }) => {
|
|
@@ -30515,8 +31253,8 @@ function registerGetLastAssistantResponse(server) {
|
|
|
30515
31253
|
title: "Get Last Assistant Response",
|
|
30516
31254
|
description: "Return the exact last assistant response for an agent from the session event journal. Use for 'what was the last thing you said?'",
|
|
30517
31255
|
inputSchema: {
|
|
30518
|
-
agent_id:
|
|
30519
|
-
project_name:
|
|
31256
|
+
agent_id: z91.string().optional().describe("Agent to inspect. Defaults to active agent. COO/CTO may inspect others."),
|
|
31257
|
+
project_name: z91.string().optional().describe("Optional project filter. Pass 'all' for all projects.")
|
|
30520
31258
|
}
|
|
30521
31259
|
},
|
|
30522
31260
|
async ({ agent_id, project_name }) => {
|
|
@@ -30551,7 +31289,7 @@ var init_get_session_events = __esm({
|
|
|
30551
31289
|
init_active_agent();
|
|
30552
31290
|
init_fast_db_init();
|
|
30553
31291
|
init_session_events();
|
|
30554
|
-
EVENT_TYPE =
|
|
31292
|
+
EVENT_TYPE = z91.enum([
|
|
30555
31293
|
"user_prompt",
|
|
30556
31294
|
"assistant_response",
|
|
30557
31295
|
"tool_call",
|
|
@@ -30563,28 +31301,28 @@ var init_get_session_events = __esm({
|
|
|
30563
31301
|
|
|
30564
31302
|
// src/lib/code-context-index.ts
|
|
30565
31303
|
import crypto20 from "crypto";
|
|
30566
|
-
import
|
|
30567
|
-
import { existsSync as
|
|
31304
|
+
import path57 from "path";
|
|
31305
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync22, readFileSync as readFileSync38, readdirSync as readdirSync15, statSync as statSync10, writeFileSync as writeFileSync25 } from "fs";
|
|
30568
31306
|
import { spawnSync } from "child_process";
|
|
30569
31307
|
function normalizeProjectRoot(projectRoot) {
|
|
30570
|
-
return
|
|
31308
|
+
return path57.resolve(projectRoot || process.cwd());
|
|
30571
31309
|
}
|
|
30572
31310
|
function hashText(text3) {
|
|
30573
31311
|
return crypto20.createHash("sha256").update(text3).digest("hex");
|
|
30574
31312
|
}
|
|
30575
31313
|
function indexDir() {
|
|
30576
|
-
const dir =
|
|
31314
|
+
const dir = path57.join(EXE_AI_DIR, "code-context");
|
|
30577
31315
|
mkdirSync22(dir, { recursive: true });
|
|
30578
31316
|
return dir;
|
|
30579
31317
|
}
|
|
30580
31318
|
function getCodeContextIndexPath(projectRoot) {
|
|
30581
31319
|
const root = normalizeProjectRoot(projectRoot);
|
|
30582
31320
|
const rootHash = hashText(root).slice(0, 16);
|
|
30583
|
-
return
|
|
31321
|
+
return path57.join(indexDir(), `${rootHash}.json`);
|
|
30584
31322
|
}
|
|
30585
31323
|
function currentBranch(projectRoot) {
|
|
30586
|
-
const
|
|
30587
|
-
const branch =
|
|
31324
|
+
const result3 = spawnSync("git", ["branch", "--show-current"], { cwd: projectRoot, encoding: "utf8", timeout: 2e3 });
|
|
31325
|
+
const branch = result3.status === 0 ? result3.stdout.trim() : "";
|
|
30588
31326
|
return branch || "detached-or-unknown";
|
|
30589
31327
|
}
|
|
30590
31328
|
function shouldIgnore(relPath) {
|
|
@@ -30592,9 +31330,9 @@ function shouldIgnore(relPath) {
|
|
|
30592
31330
|
return parts.some((part) => IGNORE_SEGMENTS.has(part));
|
|
30593
31331
|
}
|
|
30594
31332
|
function listRecursive(projectRoot, dir = projectRoot, out = []) {
|
|
30595
|
-
for (const entry of
|
|
30596
|
-
const abs =
|
|
30597
|
-
const rel =
|
|
31333
|
+
for (const entry of readdirSync15(dir, { withFileTypes: true })) {
|
|
31334
|
+
const abs = path57.join(dir, entry.name);
|
|
31335
|
+
const rel = path57.relative(projectRoot, abs).replaceAll(path57.sep, "/");
|
|
30598
31336
|
if (shouldIgnore(rel)) continue;
|
|
30599
31337
|
if (entry.isDirectory()) listRecursive(projectRoot, abs, out);
|
|
30600
31338
|
else if (entry.isFile()) out.push(rel);
|
|
@@ -30610,7 +31348,7 @@ function listCodeFiles(projectRoot, maxFiles) {
|
|
|
30610
31348
|
const rg = spawnSync("rg", ["--files"], { cwd: projectRoot, encoding: "utf8", timeout: 5e3, maxBuffer: 1024 * 1024 * 16 });
|
|
30611
31349
|
files = rg.status === 0 && rg.stdout.trim() ? rg.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : listRecursive(projectRoot);
|
|
30612
31350
|
}
|
|
30613
|
-
return files.map((file) => file.replaceAll(
|
|
31351
|
+
return files.map((file) => file.replaceAll(path57.sep, "/")).filter((file) => isChunkable(file) && !shouldIgnore(file)).slice(0, maxFiles).sort();
|
|
30614
31352
|
}
|
|
30615
31353
|
function parseImportPaths2(importText) {
|
|
30616
31354
|
const paths = [];
|
|
@@ -30623,13 +31361,13 @@ function parseImportPaths2(importText) {
|
|
|
30623
31361
|
}
|
|
30624
31362
|
function resolveImport(fromFile, importPath, allFiles) {
|
|
30625
31363
|
if (!importPath.startsWith(".")) return null;
|
|
30626
|
-
const base =
|
|
31364
|
+
const base = path57.posix.normalize(path57.posix.join(path57.posix.dirname(fromFile.replaceAll(path57.sep, "/")), importPath));
|
|
30627
31365
|
const withoutKnownExt = base.replace(/\.(?:[a-z0-9]+)$/i, "");
|
|
30628
31366
|
const candidates = [base];
|
|
30629
31367
|
for (const ext of ["ts", "tsx", "js", "jsx", "py", "rs", "go", "java", "cs", "cpp", "c", "rb", "php", "swift", "kt", "scala", "sql", "md", "json", "yaml", "yml"]) {
|
|
30630
31368
|
candidates.push(`${withoutKnownExt}.${ext}`, `${base}.${ext}`);
|
|
30631
31369
|
}
|
|
30632
|
-
for (const indexName of ["index.ts", "index.tsx", "index.js", "mod.rs", "__init__.py"]) candidates.push(
|
|
31370
|
+
for (const indexName of ["index.ts", "index.tsx", "index.js", "mod.rs", "__init__.py"]) candidates.push(path57.posix.join(base, indexName));
|
|
30633
31371
|
return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
|
|
30634
31372
|
}
|
|
30635
31373
|
function symbolId(filePath, chunk) {
|
|
@@ -30637,9 +31375,9 @@ function symbolId(filePath, chunk) {
|
|
|
30637
31375
|
}
|
|
30638
31376
|
function loadIndex(projectRoot) {
|
|
30639
31377
|
const file = getCodeContextIndexPath(projectRoot);
|
|
30640
|
-
if (!
|
|
31378
|
+
if (!existsSync44(file)) return null;
|
|
30641
31379
|
try {
|
|
30642
|
-
const parsed = JSON.parse(
|
|
31380
|
+
const parsed = JSON.parse(readFileSync38(file, "utf8"));
|
|
30643
31381
|
if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
|
|
30644
31382
|
return parsed;
|
|
30645
31383
|
} catch {
|
|
@@ -30650,7 +31388,7 @@ function saveIndex(index) {
|
|
|
30650
31388
|
writeFileSync25(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
|
|
30651
31389
|
}
|
|
30652
31390
|
function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
30653
|
-
const absPath =
|
|
31391
|
+
const absPath = path57.join(projectRoot, relPath);
|
|
30654
31392
|
let stat;
|
|
30655
31393
|
try {
|
|
30656
31394
|
stat = statSync10(absPath);
|
|
@@ -30660,7 +31398,7 @@ function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
|
30660
31398
|
if (!stat.isFile()) return { record: null, reused: false };
|
|
30661
31399
|
const language = languageForFile(relPath);
|
|
30662
31400
|
if (!language || !isChunkable(relPath)) return { record: null, reused: false };
|
|
30663
|
-
const source =
|
|
31401
|
+
const source = readFileSync38(absPath, "utf8");
|
|
30664
31402
|
const hash = hashText(source);
|
|
30665
31403
|
if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size && previous.language === language) {
|
|
30666
31404
|
return { record: previous, reused: true };
|
|
@@ -30688,13 +31426,13 @@ function buildCodeContextIndex(options = {}) {
|
|
|
30688
31426
|
const branch = currentBranch(projectRoot);
|
|
30689
31427
|
const previous = options.force ? null : loadIndex(projectRoot);
|
|
30690
31428
|
const files = listCodeFiles(projectRoot, maxFiles);
|
|
30691
|
-
const allFiles = new Set(files.map((file) => file.replaceAll(
|
|
31429
|
+
const allFiles = new Set(files.map((file) => file.replaceAll(path57.sep, "/")));
|
|
30692
31430
|
const fileRecords = {};
|
|
30693
31431
|
let rebuiltFiles = 0;
|
|
30694
31432
|
let reusedFiles = 0;
|
|
30695
31433
|
let skippedFiles = 0;
|
|
30696
31434
|
for (const rel of files) {
|
|
30697
|
-
const normalized = rel.replaceAll(
|
|
31435
|
+
const normalized = rel.replaceAll(path57.sep, "/");
|
|
30698
31436
|
const { record, reused } = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
|
|
30699
31437
|
if (record) {
|
|
30700
31438
|
fileRecords[normalized] = record;
|
|
@@ -30723,11 +31461,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
|
|
|
30723
31461
|
if (loaded) {
|
|
30724
31462
|
const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
|
|
30725
31463
|
const unchanged = currentFiles.every((rel) => {
|
|
30726
|
-
const normalized = rel.replaceAll(
|
|
31464
|
+
const normalized = rel.replaceAll(path57.sep, "/");
|
|
30727
31465
|
const existing = loaded.files[normalized];
|
|
30728
31466
|
if (!existing) return false;
|
|
30729
31467
|
try {
|
|
30730
|
-
const stat = statSync10(
|
|
31468
|
+
const stat = statSync10(path57.join(projectRoot, normalized));
|
|
30731
31469
|
return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
|
|
30732
31470
|
} catch {
|
|
30733
31471
|
return false;
|
|
@@ -30780,9 +31518,9 @@ function globToRegex(pattern) {
|
|
|
30780
31518
|
}
|
|
30781
31519
|
function matchesPath(filePath, patterns) {
|
|
30782
31520
|
if (!patterns || patterns.length === 0) return true;
|
|
30783
|
-
const normalized = filePath.replaceAll(
|
|
31521
|
+
const normalized = filePath.replaceAll(path57.sep, "/");
|
|
30784
31522
|
return patterns.some((pattern) => {
|
|
30785
|
-
const p = pattern.replaceAll(
|
|
31523
|
+
const p = pattern.replaceAll(path57.sep, "/").replace(/^\.\//, "");
|
|
30786
31524
|
return normalized === p || normalized.startsWith(`${p}/`) || normalized.endsWith(p) || globToRegex(p).test(normalized);
|
|
30787
31525
|
});
|
|
30788
31526
|
}
|
|
@@ -30900,7 +31638,7 @@ function traceCodeSymbol(symbolName, options = {}) {
|
|
|
30900
31638
|
}
|
|
30901
31639
|
function resolveTargetFile(index, input) {
|
|
30902
31640
|
if (input.filePath) {
|
|
30903
|
-
const normalized = input.filePath.replaceAll(
|
|
31641
|
+
const normalized = input.filePath.replaceAll(path57.sep, "/").replace(/^\.\//, "");
|
|
30904
31642
|
if (index.files[normalized]) return { filePath: normalized, target: normalized };
|
|
30905
31643
|
const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
|
|
30906
31644
|
if (suffix) return { filePath: suffix, target: input.filePath };
|
|
@@ -30930,7 +31668,7 @@ function analyzeBlastRadius(input) {
|
|
|
30930
31668
|
}
|
|
30931
31669
|
}
|
|
30932
31670
|
}
|
|
30933
|
-
const targetBase =
|
|
31671
|
+
const targetBase = path57.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
|
|
30934
31672
|
const symbolLower = input.symbol?.toLowerCase();
|
|
30935
31673
|
const tests = Object.keys(index.files).filter((file) => {
|
|
30936
31674
|
const lower = file.toLowerCase();
|
|
@@ -30971,7 +31709,7 @@ var init_code_context_index = __esm({
|
|
|
30971
31709
|
});
|
|
30972
31710
|
|
|
30973
31711
|
// src/mcp/tools/code-context.ts
|
|
30974
|
-
import { z as
|
|
31712
|
+
import { z as z92 } from "zod";
|
|
30975
31713
|
function errorResult10(text3) {
|
|
30976
31714
|
return { content: [{ type: "text", text: text3 }], isError: true };
|
|
30977
31715
|
}
|
|
@@ -30983,19 +31721,19 @@ function registerCodeContext(server) {
|
|
|
30983
31721
|
title: "Code Context",
|
|
30984
31722
|
description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
|
|
30985
31723
|
inputSchema: {
|
|
30986
|
-
action:
|
|
30987
|
-
project_root:
|
|
30988
|
-
query:
|
|
30989
|
-
symbol:
|
|
30990
|
-
file_path:
|
|
30991
|
-
force:
|
|
30992
|
-
limit:
|
|
30993
|
-
offset:
|
|
30994
|
-
refresh_index:
|
|
30995
|
-
languages:
|
|
30996
|
-
paths:
|
|
30997
|
-
depth:
|
|
30998
|
-
max_files:
|
|
31724
|
+
action: z92.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
|
|
31725
|
+
project_root: z92.string().optional().describe("Repository root. Defaults to current working directory."),
|
|
31726
|
+
query: z92.string().optional().describe("Search query for action=search"),
|
|
31727
|
+
symbol: z92.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
|
|
31728
|
+
file_path: z92.string().optional().describe("File path for blast_radius"),
|
|
31729
|
+
force: z92.boolean().optional().describe("Force rebuild before answering"),
|
|
31730
|
+
limit: z92.coerce.number().int().min(1).max(100).optional().describe("Max results"),
|
|
31731
|
+
offset: z92.coerce.number().int().min(0).optional().describe("Search pagination offset"),
|
|
31732
|
+
refresh_index: z92.boolean().optional().describe("Refresh/rebuild index before searching"),
|
|
31733
|
+
languages: z92.array(z92.string()).optional().describe('Language filters, e.g. ["python", "typescript"]'),
|
|
31734
|
+
paths: z92.array(z92.string()).optional().describe("Path/glob filters"),
|
|
31735
|
+
depth: z92.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
|
|
31736
|
+
max_files: z92.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
|
|
30999
31737
|
}
|
|
31000
31738
|
}, async ({ action, project_root, query, symbol, file_path, force, limit, offset, refresh_index, languages, paths, depth, max_files }) => {
|
|
31001
31739
|
const opts = { projectRoot: project_root, force, maxFiles: max_files };
|
|
@@ -31031,9 +31769,9 @@ function registerCodeContext(server) {
|
|
|
31031
31769
|
}
|
|
31032
31770
|
if (action === "blast_radius") {
|
|
31033
31771
|
if (!symbol && !file_path) return errorResult10('code_context action "blast_radius" requires symbol or file_path');
|
|
31034
|
-
const
|
|
31035
|
-
if (!
|
|
31036
|
-
return jsonResult(
|
|
31772
|
+
const result3 = analyzeBlastRadius({ projectRoot: project_root, force, symbol, filePath: file_path, depth });
|
|
31773
|
+
if (!result3) return errorResult10(`No code context target found for ${symbol || file_path}`);
|
|
31774
|
+
return jsonResult(result3);
|
|
31037
31775
|
}
|
|
31038
31776
|
return errorResult10(`Unknown code_context action: ${String(action)}`);
|
|
31039
31777
|
});
|
|
@@ -31046,7 +31784,7 @@ var init_code_context = __esm({
|
|
|
31046
31784
|
});
|
|
31047
31785
|
|
|
31048
31786
|
// src/mcp/tools/support-inbox.ts
|
|
31049
|
-
import { z as
|
|
31787
|
+
import { z as z93 } from "zod";
|
|
31050
31788
|
function adminToken() {
|
|
31051
31789
|
return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
|
|
31052
31790
|
}
|
|
@@ -31085,14 +31823,14 @@ function registerListBugReports(server) {
|
|
|
31085
31823
|
title: "List Bug Reports",
|
|
31086
31824
|
description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
|
|
31087
31825
|
inputSchema: {
|
|
31088
|
-
status:
|
|
31089
|
-
severity:
|
|
31090
|
-
limit:
|
|
31826
|
+
status: z93.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
|
|
31827
|
+
severity: z93.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
31828
|
+
limit: z93.number().int().min(1).max(100).default(25)
|
|
31091
31829
|
}
|
|
31092
31830
|
},
|
|
31093
|
-
async ({ status, severity, limit }) => {
|
|
31831
|
+
async ({ status: status2, severity, limit }) => {
|
|
31094
31832
|
const url = new URL(endpoint());
|
|
31095
|
-
url.searchParams.set("status",
|
|
31833
|
+
url.searchParams.set("status", status2);
|
|
31096
31834
|
url.searchParams.set("limit", String(limit));
|
|
31097
31835
|
if (severity) url.searchParams.set("severity", severity);
|
|
31098
31836
|
const data = await requestJson(url.toString());
|
|
@@ -31106,7 +31844,7 @@ function registerGetBugReport(server) {
|
|
|
31106
31844
|
{
|
|
31107
31845
|
title: "Get Bug Report",
|
|
31108
31846
|
description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
|
|
31109
|
-
inputSchema: { id:
|
|
31847
|
+
inputSchema: { id: z93.string().min(8) }
|
|
31110
31848
|
},
|
|
31111
31849
|
async ({ id }) => {
|
|
31112
31850
|
const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
|
|
@@ -31121,18 +31859,18 @@ function registerTriageBugReport(server) {
|
|
|
31121
31859
|
title: "Triage Bug Report",
|
|
31122
31860
|
description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
|
|
31123
31861
|
inputSchema: {
|
|
31124
|
-
id:
|
|
31862
|
+
id: z93.string().min(8),
|
|
31125
31863
|
status: STATUS.optional(),
|
|
31126
|
-
triage_notes:
|
|
31127
|
-
linked_task_id:
|
|
31128
|
-
linked_commit:
|
|
31129
|
-
fixed_version:
|
|
31864
|
+
triage_notes: z93.string().optional(),
|
|
31865
|
+
linked_task_id: z93.string().optional(),
|
|
31866
|
+
linked_commit: z93.string().optional(),
|
|
31867
|
+
fixed_version: z93.string().optional()
|
|
31130
31868
|
}
|
|
31131
31869
|
},
|
|
31132
|
-
async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
|
|
31870
|
+
async ({ id, status: status2, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
|
|
31133
31871
|
const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`, {
|
|
31134
31872
|
method: "PATCH",
|
|
31135
|
-
body: JSON.stringify({ status, triage_notes, linked_task_id, linked_commit, fixed_version })
|
|
31873
|
+
body: JSON.stringify({ status: status2, triage_notes, linked_task_id, linked_commit, fixed_version })
|
|
31136
31874
|
});
|
|
31137
31875
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
31138
31876
|
}
|
|
@@ -31143,7 +31881,7 @@ var init_support_inbox = __esm({
|
|
|
31143
31881
|
"src/mcp/tools/support-inbox.ts"() {
|
|
31144
31882
|
"use strict";
|
|
31145
31883
|
DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
|
|
31146
|
-
STATUS =
|
|
31884
|
+
STATUS = z93.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
|
|
31147
31885
|
}
|
|
31148
31886
|
});
|
|
31149
31887
|
|
|
@@ -31190,7 +31928,7 @@ var init_tool_gates = __esm({
|
|
|
31190
31928
|
documents: ["COO", "CTO", "Wiki Agent"],
|
|
31191
31929
|
// ingest, list, purge, set_importance, rerank
|
|
31192
31930
|
gateway: ["COO", "Gateway Agent"],
|
|
31193
|
-
// send_whatsapp, query_conversations, query_company_brain
|
|
31931
|
+
// send_whatsapp, query_conversations, query_company_brain, company_actions
|
|
31194
31932
|
admin: ["COO"],
|
|
31195
31933
|
// deploy, backup, daemon health, auto-wake, worker gate, memory audit, consolidation, cloud sync, agent config, list employees, agent spend, sessions, session kills
|
|
31196
31934
|
licensing: ["COO"],
|
|
@@ -31218,6 +31956,7 @@ var init_tool_gates = __esm({
|
|
|
31218
31956
|
registerGetDecision: "core",
|
|
31219
31957
|
registerCreateBugReport: "core",
|
|
31220
31958
|
registerSupportTools: "core",
|
|
31959
|
+
registerCliParityTools: "admin",
|
|
31221
31960
|
registerGetSessionEvents: "core",
|
|
31222
31961
|
registerGetLastAssistantResponse: "core",
|
|
31223
31962
|
registerCodeContext: "graph-read",
|
|
@@ -31278,6 +32017,7 @@ var init_tool_gates = __esm({
|
|
|
31278
32017
|
registerSendWhatsapp: "gateway",
|
|
31279
32018
|
registerQueryConversations: "gateway",
|
|
31280
32019
|
registerQueryCompanyBrain: "gateway",
|
|
32020
|
+
registerCompanyActions: "gateway",
|
|
31281
32021
|
// admin
|
|
31282
32022
|
registerConfig: "admin",
|
|
31283
32023
|
registerDeployClient: "admin",
|
|
@@ -31478,6 +32218,7 @@ function registerAllTools(server) {
|
|
|
31478
32218
|
gate("registerGetDecision", registerGetDecision);
|
|
31479
32219
|
gate("registerCreateBugReport", registerCreateBugReport);
|
|
31480
32220
|
gate("registerSupportTools", registerSupportTools);
|
|
32221
|
+
gate("registerCliParityTools", registerCliParityTools);
|
|
31481
32222
|
gate("registerGetSessionEvents", registerGetSessionEvents);
|
|
31482
32223
|
gate("registerGetLastAssistantResponse", registerGetLastAssistantResponse);
|
|
31483
32224
|
gate("registerCodeContext", registerCodeContext);
|
|
@@ -31531,6 +32272,7 @@ function registerAllTools(server) {
|
|
|
31531
32272
|
}
|
|
31532
32273
|
if (exposeLegacyGateway) {
|
|
31533
32274
|
gate("registerQueryCompanyBrain", registerQueryCompanyBrain);
|
|
32275
|
+
gate("registerCompanyActions", registerCompanyActions);
|
|
31534
32276
|
}
|
|
31535
32277
|
}
|
|
31536
32278
|
var init_register_tools = __esm({
|
|
@@ -31624,8 +32366,10 @@ var init_register_tools = __esm({
|
|
|
31624
32366
|
init_list_licenses();
|
|
31625
32367
|
init_activate_license();
|
|
31626
32368
|
init_query_company_brain();
|
|
32369
|
+
init_company_actions();
|
|
31627
32370
|
init_create_bug_report();
|
|
31628
32371
|
init_support();
|
|
32372
|
+
init_cli_parity();
|
|
31629
32373
|
init_get_session_events();
|
|
31630
32374
|
init_code_context();
|
|
31631
32375
|
init_support_inbox();
|
|
@@ -31639,7 +32383,7 @@ __export(review_polling_exports, {
|
|
|
31639
32383
|
createRealDeps: () => createRealDeps,
|
|
31640
32384
|
pollPendingReviews: () => pollPendingReviews
|
|
31641
32385
|
});
|
|
31642
|
-
import { execSync as
|
|
32386
|
+
import { execSync as execSync16 } from "child_process";
|
|
31643
32387
|
async function pollPendingReviews(deps, _state) {
|
|
31644
32388
|
let sessions;
|
|
31645
32389
|
try {
|
|
@@ -31746,7 +32490,7 @@ async function pollPendingReviews(deps, _state) {
|
|
|
31746
32490
|
function createRealDeps(getClient2) {
|
|
31747
32491
|
return {
|
|
31748
32492
|
listTmuxSessions: () => {
|
|
31749
|
-
return
|
|
32493
|
+
return execSync16("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
31750
32494
|
encoding: "utf8",
|
|
31751
32495
|
timeout: 3e3
|
|
31752
32496
|
}).trim().split("\n").filter(Boolean);
|
|
@@ -31754,12 +32498,12 @@ function createRealDeps(getClient2) {
|
|
|
31754
32498
|
countPendingReviews: async (sessionScope) => {
|
|
31755
32499
|
const client = getClient2();
|
|
31756
32500
|
const rpScope = strictSessionScopeFilter(sessionScope);
|
|
31757
|
-
const
|
|
32501
|
+
const result3 = await client.execute({
|
|
31758
32502
|
sql: `SELECT COUNT(*) as count FROM tasks
|
|
31759
32503
|
WHERE status = 'needs_review'${rpScope.sql}`,
|
|
31760
32504
|
args: [...rpScope.args]
|
|
31761
32505
|
});
|
|
31762
|
-
return Number(
|
|
32506
|
+
return Number(result3.rows[0]?.count ?? 0);
|
|
31763
32507
|
},
|
|
31764
32508
|
sendIntercom: (session) => {
|
|
31765
32509
|
const { sendIntercom: centralSend } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
@@ -31769,7 +32513,7 @@ function createRealDeps(getClient2) {
|
|
|
31769
32513
|
const client = getClient2();
|
|
31770
32514
|
const coordinatorName = getCoordinatorName();
|
|
31771
32515
|
const odScope = strictSessionScopeFilter(sessionScope, "t");
|
|
31772
|
-
const
|
|
32516
|
+
const result3 = await client.execute({
|
|
31773
32517
|
sql: `SELECT t.id, t.title, t.assigned_to, t.assigned_by,
|
|
31774
32518
|
t.project_name, t.task_file, t.result, t.status
|
|
31775
32519
|
FROM tasks t
|
|
@@ -31779,7 +32523,7 @@ function createRealDeps(getClient2) {
|
|
|
31779
32523
|
AND (t.result IS NULL OR t.result NOT LIKE '%## Review notes%')`,
|
|
31780
32524
|
args: [coordinatorName, ...odScope.args]
|
|
31781
32525
|
});
|
|
31782
|
-
return
|
|
32526
|
+
return result3.rows;
|
|
31783
32527
|
},
|
|
31784
32528
|
createReviewForOrphan: async (task) => {
|
|
31785
32529
|
const { createReviewForCompletedTask: createReviewForCompletedTask2 } = await Promise.resolve().then(() => (init_tasks_review(), tasks_review_exports));
|
|
@@ -31796,7 +32540,7 @@ function createRealDeps(getClient2) {
|
|
|
31796
32540
|
findUrgentUnread: async (sessionScope) => {
|
|
31797
32541
|
const client = getClient2();
|
|
31798
32542
|
const msgScope = strictSessionScopeFilter(sessionScope);
|
|
31799
|
-
const
|
|
32543
|
+
const result3 = await client.execute({
|
|
31800
32544
|
sql: `SELECT id, target_agent, content, created_at
|
|
31801
32545
|
FROM messages
|
|
31802
32546
|
WHERE priority = 'urgent'
|
|
@@ -31806,13 +32550,13 @@ function createRealDeps(getClient2) {
|
|
|
31806
32550
|
LIMIT 10`,
|
|
31807
32551
|
args: [...msgScope.args]
|
|
31808
32552
|
});
|
|
31809
|
-
return
|
|
32553
|
+
return result3.rows;
|
|
31810
32554
|
},
|
|
31811
32555
|
findUnstartedTasks: async (sessionScope) => {
|
|
31812
32556
|
const client = getClient2();
|
|
31813
32557
|
const coordinatorName = getCoordinatorName();
|
|
31814
32558
|
const usScope = strictSessionScopeFilter(sessionScope);
|
|
31815
|
-
const
|
|
32559
|
+
const result3 = await client.execute({
|
|
31816
32560
|
sql: `SELECT id, title, assigned_to, created_at
|
|
31817
32561
|
FROM tasks
|
|
31818
32562
|
WHERE status = 'open'
|
|
@@ -31825,7 +32569,7 @@ function createRealDeps(getClient2) {
|
|
|
31825
32569
|
LIMIT 20`,
|
|
31826
32570
|
args: [coordinatorName, ...usScope.args]
|
|
31827
32571
|
});
|
|
31828
|
-
return
|
|
32572
|
+
return result3.rows;
|
|
31829
32573
|
}
|
|
31830
32574
|
};
|
|
31831
32575
|
}
|
|
@@ -31854,7 +32598,7 @@ __export(task_enforcement_exports, {
|
|
|
31854
32598
|
sendNudge: () => sendNudge
|
|
31855
32599
|
});
|
|
31856
32600
|
import { writeFileSync as writeFileSync26 } from "fs";
|
|
31857
|
-
import
|
|
32601
|
+
import path58 from "path";
|
|
31858
32602
|
function writeAuditEntry(entry) {
|
|
31859
32603
|
try {
|
|
31860
32604
|
const line = JSON.stringify(entry) + "\n";
|
|
@@ -32029,7 +32773,7 @@ var init_task_enforcement = __esm({
|
|
|
32029
32773
|
"What do you need?"
|
|
32030
32774
|
];
|
|
32031
32775
|
MANAGER_ROLES = ["COO", "CTO"];
|
|
32032
|
-
AUDIT_LOG_PATH =
|
|
32776
|
+
AUDIT_LOG_PATH = path58.join(
|
|
32033
32777
|
process.env.HOME ?? process.env.USERPROFILE ?? "/tmp",
|
|
32034
32778
|
".exe-os",
|
|
32035
32779
|
"enforcement-audit.jsonl"
|
|
@@ -32051,10 +32795,10 @@ __export(background_jobs_exports, {
|
|
|
32051
32795
|
reniceCurrentProcess: () => reniceCurrentProcess,
|
|
32052
32796
|
startManagedJob: () => startManagedJob
|
|
32053
32797
|
});
|
|
32054
|
-
import { existsSync as
|
|
32798
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync23, readFileSync as readFileSync39, writeFileSync as writeFileSync27, unlinkSync as unlinkSync14 } from "fs";
|
|
32055
32799
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
32056
32800
|
import os22 from "os";
|
|
32057
|
-
import
|
|
32801
|
+
import path59 from "path";
|
|
32058
32802
|
function ensureDirs() {
|
|
32059
32803
|
mkdirSync23(LOCK_DIR, { recursive: true });
|
|
32060
32804
|
}
|
|
@@ -32072,9 +32816,9 @@ function isAlive(pid) {
|
|
|
32072
32816
|
}
|
|
32073
32817
|
function readJobsRaw() {
|
|
32074
32818
|
ensureDirs();
|
|
32075
|
-
if (!
|
|
32819
|
+
if (!existsSync45(JOBS_FILE)) return [];
|
|
32076
32820
|
try {
|
|
32077
|
-
const parsed = JSON.parse(
|
|
32821
|
+
const parsed = JSON.parse(readFileSync39(JOBS_FILE, "utf8"));
|
|
32078
32822
|
return Array.isArray(parsed) ? parsed : [];
|
|
32079
32823
|
} catch {
|
|
32080
32824
|
return [];
|
|
@@ -32100,14 +32844,14 @@ function listBackgroundJobs() {
|
|
|
32100
32844
|
return jobs;
|
|
32101
32845
|
}
|
|
32102
32846
|
function lockPath(type) {
|
|
32103
|
-
return
|
|
32847
|
+
return path59.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
32104
32848
|
}
|
|
32105
32849
|
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
32106
32850
|
ensureDirs();
|
|
32107
32851
|
const file = lockPath(type);
|
|
32108
|
-
if (
|
|
32852
|
+
if (existsSync45(file)) {
|
|
32109
32853
|
try {
|
|
32110
|
-
const lock = JSON.parse(
|
|
32854
|
+
const lock = JSON.parse(readFileSync39(file, "utf8"));
|
|
32111
32855
|
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
32112
32856
|
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
32113
32857
|
} catch {
|
|
@@ -32127,8 +32871,8 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
32127
32871
|
function releaseJobLock(type) {
|
|
32128
32872
|
const file = lockPath(type);
|
|
32129
32873
|
try {
|
|
32130
|
-
if (!
|
|
32131
|
-
const lock = JSON.parse(
|
|
32874
|
+
if (!existsSync45(file)) return;
|
|
32875
|
+
const lock = JSON.parse(readFileSync39(file, "utf8"));
|
|
32132
32876
|
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync14(file);
|
|
32133
32877
|
} catch {
|
|
32134
32878
|
try {
|
|
@@ -32174,9 +32918,9 @@ function startManagedJob(options) {
|
|
|
32174
32918
|
upsert({});
|
|
32175
32919
|
const timer = setInterval(() => upsert({ lastHeartbeatAt: now() }), 3e4);
|
|
32176
32920
|
timer.unref?.();
|
|
32177
|
-
const cleanup = (
|
|
32921
|
+
const cleanup = (status2, error) => {
|
|
32178
32922
|
clearInterval(timer);
|
|
32179
|
-
upsert({ status, error, lastHeartbeatAt: now() });
|
|
32923
|
+
upsert({ status: status2, error, lastHeartbeatAt: now() });
|
|
32180
32924
|
releaseJobLock(options.type);
|
|
32181
32925
|
};
|
|
32182
32926
|
process.once("SIGTERM", () => {
|
|
@@ -32327,62 +33071,14 @@ var init_background_jobs = __esm({
|
|
|
32327
33071
|
"src/lib/background-jobs.ts"() {
|
|
32328
33072
|
"use strict";
|
|
32329
33073
|
init_config();
|
|
32330
|
-
JOB_DIR =
|
|
32331
|
-
JOBS_FILE =
|
|
32332
|
-
LOCK_DIR =
|
|
33074
|
+
JOB_DIR = path59.join(EXE_AI_DIR, "jobs");
|
|
33075
|
+
JOBS_FILE = path59.join(JOB_DIR, "jobs.json");
|
|
33076
|
+
LOCK_DIR = path59.join(JOB_DIR, "locks");
|
|
32333
33077
|
DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
32334
33078
|
MAX_HISTORY = 200;
|
|
32335
33079
|
}
|
|
32336
33080
|
});
|
|
32337
33081
|
|
|
32338
|
-
// src/lib/update-check.ts
|
|
32339
|
-
var update_check_exports = {};
|
|
32340
|
-
__export(update_check_exports, {
|
|
32341
|
-
checkForUpdate: () => checkForUpdate,
|
|
32342
|
-
getLocalVersion: () => getLocalVersion,
|
|
32343
|
-
getRemoteVersion: () => getRemoteVersion
|
|
32344
|
-
});
|
|
32345
|
-
import { execSync as execSync15 } from "child_process";
|
|
32346
|
-
import { readFileSync as readFileSync38 } from "fs";
|
|
32347
|
-
import path58 from "path";
|
|
32348
|
-
function getLocalVersion(packageRoot) {
|
|
32349
|
-
const pkgPath = path58.join(packageRoot, "package.json");
|
|
32350
|
-
const pkg = JSON.parse(readFileSync38(pkgPath, "utf-8"));
|
|
32351
|
-
return pkg.version;
|
|
32352
|
-
}
|
|
32353
|
-
function getRemoteVersion() {
|
|
32354
|
-
try {
|
|
32355
|
-
const output = execSync15("npm view @askexenow/exe-os version", {
|
|
32356
|
-
encoding: "utf-8",
|
|
32357
|
-
timeout: 15e3,
|
|
32358
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
32359
|
-
});
|
|
32360
|
-
return output.trim();
|
|
32361
|
-
} catch {
|
|
32362
|
-
return null;
|
|
32363
|
-
}
|
|
32364
|
-
}
|
|
32365
|
-
function checkForUpdate(packageRoot) {
|
|
32366
|
-
const localVersion = getLocalVersion(packageRoot);
|
|
32367
|
-
const remoteVersion = getRemoteVersion();
|
|
32368
|
-
if (!remoteVersion) {
|
|
32369
|
-
return {
|
|
32370
|
-
updateAvailable: false,
|
|
32371
|
-
localVersion,
|
|
32372
|
-
error: "Could not reach npm registry or package not published yet"
|
|
32373
|
-
};
|
|
32374
|
-
}
|
|
32375
|
-
if (remoteVersion === localVersion) {
|
|
32376
|
-
return { updateAvailable: false, localVersion, remoteVersion };
|
|
32377
|
-
}
|
|
32378
|
-
return { updateAvailable: true, localVersion, remoteVersion };
|
|
32379
|
-
}
|
|
32380
|
-
var init_update_check = __esm({
|
|
32381
|
-
"src/lib/update-check.ts"() {
|
|
32382
|
-
"use strict";
|
|
32383
|
-
}
|
|
32384
|
-
});
|
|
32385
|
-
|
|
32386
33082
|
// src/lib/ws-auth.ts
|
|
32387
33083
|
var ws_auth_exports = {};
|
|
32388
33084
|
__export(ws_auth_exports, {
|
|
@@ -32419,12 +33115,12 @@ __export(device_registry_exports, {
|
|
|
32419
33115
|
});
|
|
32420
33116
|
import crypto22 from "crypto";
|
|
32421
33117
|
import os23 from "os";
|
|
32422
|
-
import { readFileSync as
|
|
32423
|
-
import
|
|
33118
|
+
import { readFileSync as readFileSync40, writeFileSync as writeFileSync28, mkdirSync as mkdirSync24, existsSync as existsSync46 } from "fs";
|
|
33119
|
+
import path60 from "path";
|
|
32424
33120
|
function getDeviceInfo() {
|
|
32425
|
-
if (
|
|
33121
|
+
if (existsSync46(DEVICE_JSON_PATH)) {
|
|
32426
33122
|
try {
|
|
32427
|
-
const raw =
|
|
33123
|
+
const raw = readFileSync40(DEVICE_JSON_PATH, "utf8");
|
|
32428
33124
|
const data = JSON.parse(raw);
|
|
32429
33125
|
if (data.deviceId && data.friendlyName && data.hostname) {
|
|
32430
33126
|
return data;
|
|
@@ -32438,7 +33134,7 @@ function getDeviceInfo() {
|
|
|
32438
33134
|
friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
|
|
32439
33135
|
hostname
|
|
32440
33136
|
};
|
|
32441
|
-
mkdirSync24(
|
|
33137
|
+
mkdirSync24(path60.dirname(DEVICE_JSON_PATH), { recursive: true });
|
|
32442
33138
|
writeFileSync28(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
|
|
32443
33139
|
return info;
|
|
32444
33140
|
}
|
|
@@ -32461,11 +33157,11 @@ async function resolveTargetDevice(targetAgent, targetProject) {
|
|
|
32461
33157
|
WHERE connected = 1 AND agents LIKE ?`;
|
|
32462
33158
|
args = [`%"${targetAgent}"%`];
|
|
32463
33159
|
}
|
|
32464
|
-
const
|
|
32465
|
-
if (
|
|
32466
|
-
return
|
|
33160
|
+
const result3 = await client.execute({ sql, args });
|
|
33161
|
+
if (result3.rows.length === 1) {
|
|
33162
|
+
return result3.rows[0].device_id;
|
|
32467
33163
|
}
|
|
32468
|
-
if (
|
|
33164
|
+
if (result3.rows.length > 1) {
|
|
32469
33165
|
const sorted = await client.execute({
|
|
32470
33166
|
sql: sql + " ORDER BY last_seen DESC LIMIT 1",
|
|
32471
33167
|
args
|
|
@@ -32479,7 +33175,7 @@ var init_device_registry = __esm({
|
|
|
32479
33175
|
"src/lib/device-registry.ts"() {
|
|
32480
33176
|
"use strict";
|
|
32481
33177
|
init_config();
|
|
32482
|
-
DEVICE_JSON_PATH =
|
|
33178
|
+
DEVICE_JSON_PATH = path60.join(EXE_AI_DIR, "device.json");
|
|
32483
33179
|
}
|
|
32484
33180
|
});
|
|
32485
33181
|
|
|
@@ -32695,8 +33391,8 @@ import os24 from "os";
|
|
|
32695
33391
|
import net2 from "net";
|
|
32696
33392
|
import { createServer as createHttpServer } from "http";
|
|
32697
33393
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
32698
|
-
import { writeFileSync as writeFileSync29, unlinkSync as unlinkSync15, mkdirSync as mkdirSync25, existsSync as
|
|
32699
|
-
import
|
|
33394
|
+
import { writeFileSync as writeFileSync29, unlinkSync as unlinkSync15, mkdirSync as mkdirSync25, existsSync as existsSync47, readFileSync as readFileSync41, chmodSync as chmodSync2 } from "fs";
|
|
33395
|
+
import path61 from "path";
|
|
32700
33396
|
|
|
32701
33397
|
// src/lib/orchestration-metrics.ts
|
|
32702
33398
|
init_config();
|
|
@@ -32769,8 +33465,8 @@ function initMetrics() {
|
|
|
32769
33465
|
// src/lib/exe-daemon.ts
|
|
32770
33466
|
init_memory_write_governor();
|
|
32771
33467
|
init_mcp_transport_health();
|
|
32772
|
-
var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ??
|
|
32773
|
-
var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ??
|
|
33468
|
+
var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path61.join(EXE_AI_DIR, "exed.sock");
|
|
33469
|
+
var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path61.join(EXE_AI_DIR, "exed.pid");
|
|
32774
33470
|
var MODEL_FILE = "jina-embeddings-v5-small-q4_k_m.gguf";
|
|
32775
33471
|
var IDLE_TIMEOUT_MS2 = parseInt(process.env.EXE_DAEMON_IDLE_TIMEOUT_MS || "0", 10);
|
|
32776
33472
|
var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
|
|
@@ -32799,8 +33495,8 @@ function enqueue(queue, entry) {
|
|
|
32799
33495
|
queue.push(entry);
|
|
32800
33496
|
}
|
|
32801
33497
|
async function loadModel() {
|
|
32802
|
-
const modelPath =
|
|
32803
|
-
if (!
|
|
33498
|
+
const modelPath = path61.join(MODELS_DIR, MODEL_FILE);
|
|
33499
|
+
if (!existsSync47(modelPath)) {
|
|
32804
33500
|
process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
|
|
32805
33501
|
`);
|
|
32806
33502
|
return;
|
|
@@ -32984,9 +33680,9 @@ async function handleDbExecute(socket, requestId, sql, args) {
|
|
|
32984
33680
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
32985
33681
|
const client = getClient2();
|
|
32986
33682
|
const deserializedArgs = deserializeArgs(args);
|
|
32987
|
-
const
|
|
33683
|
+
const result3 = await client.execute({ sql, args: deserializedArgs });
|
|
32988
33684
|
_dbRequestsServed++;
|
|
32989
|
-
sendResponse(socket, { id: requestId, db: serializeResultSet(
|
|
33685
|
+
sendResponse(socket, { id: requestId, db: serializeResultSet(result3) });
|
|
32990
33686
|
} catch (err) {
|
|
32991
33687
|
sendResponse(socket, {
|
|
32992
33688
|
id: requestId,
|
|
@@ -33241,17 +33937,17 @@ function startMemoryQueueDrain() {
|
|
|
33241
33937
|
`);
|
|
33242
33938
|
}
|
|
33243
33939
|
function startServer() {
|
|
33244
|
-
mkdirSync25(
|
|
33940
|
+
mkdirSync25(path61.dirname(SOCKET_PATH2), { recursive: true });
|
|
33245
33941
|
try {
|
|
33246
|
-
chmodSync2(
|
|
33942
|
+
chmodSync2(path61.dirname(SOCKET_PATH2), 448);
|
|
33247
33943
|
} catch {
|
|
33248
33944
|
}
|
|
33249
33945
|
_daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV2] ?? null);
|
|
33250
33946
|
for (const oldFile of ["embed.sock", "embed.pid"]) {
|
|
33251
|
-
const oldPath =
|
|
33947
|
+
const oldPath = path61.join(path61.dirname(SOCKET_PATH2), oldFile);
|
|
33252
33948
|
try {
|
|
33253
33949
|
if (oldFile.endsWith(".pid")) {
|
|
33254
|
-
const pid = parseInt(
|
|
33950
|
+
const pid = parseInt(readFileSync41(oldPath, "utf8").trim(), 10);
|
|
33255
33951
|
if (pid > 0) try {
|
|
33256
33952
|
process.kill(pid, "SIGKILL");
|
|
33257
33953
|
} catch {
|
|
@@ -33412,14 +34108,14 @@ async function startMcpHttpServer() {
|
|
|
33412
34108
|
if (typeof id === "string" || typeof id === "number") return id;
|
|
33413
34109
|
}
|
|
33414
34110
|
return "unknown";
|
|
33415
|
-
}, sendJsonRpcError2 = function(res,
|
|
33416
|
-
res.writeHead(
|
|
34111
|
+
}, sendJsonRpcError2 = function(res, status2, message, id, extra) {
|
|
34112
|
+
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
33417
34113
|
res.end(JSON.stringify({
|
|
33418
34114
|
jsonrpc: "2.0",
|
|
33419
34115
|
error: { code: -32e3, message },
|
|
33420
34116
|
id
|
|
33421
34117
|
}));
|
|
33422
|
-
recordMcpHttpEvent({ level: "warn", message, status, ...extra });
|
|
34118
|
+
recordMcpHttpEvent({ level: "warn", message, status: status2, ...extra });
|
|
33423
34119
|
};
|
|
33424
34120
|
var parseDurationMs = parseDurationMs2, closeMcpSession = closeMcpSession2, sweepStaleMcpSessions = sweepStaleMcpSessions2, getJsonRpcId = getJsonRpcId2, sendJsonRpcError = sendJsonRpcError2;
|
|
33425
34121
|
const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
|
|
@@ -33762,14 +34458,14 @@ function startConsolidation() {
|
|
|
33762
34458
|
}
|
|
33763
34459
|
process.stderr.write(`[exed] Starting consolidation (${count} unconsolidated memories)...
|
|
33764
34460
|
`);
|
|
33765
|
-
const
|
|
34461
|
+
const result3 = await runConsolidation2(client, {
|
|
33766
34462
|
model: config2.consolidationModel,
|
|
33767
34463
|
maxCalls: config2.consolidationMaxCallsPerRun,
|
|
33768
34464
|
embedFn
|
|
33769
34465
|
});
|
|
33770
34466
|
acted("consolidation");
|
|
33771
34467
|
process.stderr.write(
|
|
33772
|
-
`[exed] Consolidation complete: ${
|
|
34468
|
+
`[exed] Consolidation complete: ${result3.clustersProcessed} clusters, ${result3.memoriesConsolidated} memories consolidated
|
|
33773
34469
|
`
|
|
33774
34470
|
);
|
|
33775
34471
|
} catch (err) {
|
|
@@ -33797,14 +34493,14 @@ function startCloudSyncTimer() {
|
|
|
33797
34493
|
const config2 = await loadConfig2();
|
|
33798
34494
|
if (!config2.cloud?.apiKey || !config2.cloud?.endpoint) return;
|
|
33799
34495
|
const { cloudSync: cloudSync2 } = await Promise.resolve().then(() => (init_cloud_sync(), cloud_sync_exports));
|
|
33800
|
-
const
|
|
34496
|
+
const result3 = await cloudSync2({
|
|
33801
34497
|
apiKey: config2.cloud.apiKey,
|
|
33802
34498
|
endpoint: config2.cloud.endpoint
|
|
33803
34499
|
});
|
|
33804
|
-
if (
|
|
34500
|
+
if (result3.pushed > 0 || result3.pulled > 0) {
|
|
33805
34501
|
acted("cloud_sync");
|
|
33806
34502
|
process.stderr.write(
|
|
33807
|
-
`[exed] Cloud sync: pushed=${
|
|
34503
|
+
`[exed] Cloud sync: pushed=${result3.pushed} pulled=${result3.pulled} total=${result3.totalMemories}
|
|
33808
34504
|
`
|
|
33809
34505
|
);
|
|
33810
34506
|
}
|
|
@@ -33830,11 +34526,11 @@ function startSkillSweep() {
|
|
|
33830
34526
|
if (!process.env.ANTHROPIC_API_KEY) return;
|
|
33831
34527
|
if (!await ensureStoreForPolling()) return;
|
|
33832
34528
|
const { sweepTrajectories: sweepTrajectories2 } = await Promise.resolve().then(() => (init_skill_learning(), skill_learning_exports));
|
|
33833
|
-
const
|
|
33834
|
-
if (
|
|
34529
|
+
const result3 = await sweepTrajectories2(config2.skillThreshold, config2.skillModel);
|
|
34530
|
+
if (result3.clustersProcessed > 0) {
|
|
33835
34531
|
acted("skill_sweep");
|
|
33836
34532
|
process.stderr.write(
|
|
33837
|
-
`[exed] Skill sweep: ${
|
|
34533
|
+
`[exed] Skill sweep: ${result3.clustersProcessed} clusters processed, ${result3.skillsExtracted} skills extracted
|
|
33838
34534
|
`
|
|
33839
34535
|
);
|
|
33840
34536
|
}
|
|
@@ -33863,11 +34559,11 @@ function startGraphExtraction() {
|
|
|
33863
34559
|
const idle = await isUserIdle2(client, 30);
|
|
33864
34560
|
if (!idle) return;
|
|
33865
34561
|
const { extractBatch: extractBatch2 } = await Promise.resolve().then(() => (init_graph_rag(), graph_rag_exports));
|
|
33866
|
-
const
|
|
33867
|
-
if (
|
|
34562
|
+
const result3 = await extractBatch2(client, 50, config2.selfQueryModel);
|
|
34563
|
+
if (result3.processed > 0) {
|
|
33868
34564
|
acted("graph_extraction");
|
|
33869
34565
|
process.stderr.write(
|
|
33870
|
-
`[exed] GraphRAG: processed ${
|
|
34566
|
+
`[exed] GraphRAG: processed ${result3.processed} memories, ${result3.entities} entities, ${result3.relationships} relationships
|
|
33871
34567
|
`
|
|
33872
34568
|
);
|
|
33873
34569
|
}
|
|
@@ -33882,7 +34578,7 @@ function startGraphExtraction() {
|
|
|
33882
34578
|
`);
|
|
33883
34579
|
}
|
|
33884
34580
|
var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
|
|
33885
|
-
var AGENT_STATS_PATH =
|
|
34581
|
+
var AGENT_STATS_PATH = path61.join(EXE_AI_DIR, "agent-stats.json");
|
|
33886
34582
|
async function writeAgentStats() {
|
|
33887
34583
|
fired("agent_stats");
|
|
33888
34584
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -33890,7 +34586,7 @@ async function writeAgentStats() {
|
|
|
33890
34586
|
acted("agent_stats");
|
|
33891
34587
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33892
34588
|
const client = getClient2();
|
|
33893
|
-
const
|
|
34589
|
+
const result3 = await client.execute({
|
|
33894
34590
|
sql: `SELECT agent_id,
|
|
33895
34591
|
COUNT(*) as total,
|
|
33896
34592
|
SUM(CASE WHEN timestamp > datetime('now', '-1 day') THEN 1 ELSE 0 END) as growth_24h,
|
|
@@ -33902,7 +34598,7 @@ async function writeAgentStats() {
|
|
|
33902
34598
|
ORDER BY total DESC`,
|
|
33903
34599
|
args: []
|
|
33904
34600
|
});
|
|
33905
|
-
const agentsBase =
|
|
34601
|
+
const agentsBase = result3.rows.map((row) => ({
|
|
33906
34602
|
id: row.agent_id,
|
|
33907
34603
|
total: Number(row.total),
|
|
33908
34604
|
growth24h: Number(row.growth_24h),
|
|
@@ -33963,7 +34659,7 @@ function startConfidenceDecay() {
|
|
|
33963
34659
|
try {
|
|
33964
34660
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33965
34661
|
const client = getClient2();
|
|
33966
|
-
const
|
|
34662
|
+
const result3 = await client.execute({
|
|
33967
34663
|
sql: `UPDATE memories
|
|
33968
34664
|
SET confidence = MAX(0.3, COALESCE(confidence, 0.7) - 0.01)
|
|
33969
34665
|
WHERE COALESCE(last_accessed, timestamp) < datetime('now', '-30 days')
|
|
@@ -33971,7 +34667,7 @@ function startConfidenceDecay() {
|
|
|
33971
34667
|
AND COALESCE(status, 'active') = 'active'`,
|
|
33972
34668
|
args: []
|
|
33973
34669
|
});
|
|
33974
|
-
const affected =
|
|
34670
|
+
const affected = result3.rowsAffected;
|
|
33975
34671
|
if (affected > 0) {
|
|
33976
34672
|
acted("confidence_decay");
|
|
33977
34673
|
process.stderr.write(`[exed] Confidence decay: ${affected} memories decayed
|
|
@@ -34024,11 +34720,11 @@ function startSoftDeletePurge() {
|
|
|
34024
34720
|
const { SOFT_DELETE_RETENTION_DAYS: SOFT_DELETE_RETENTION_DAYS2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
34025
34721
|
const client = getClient2();
|
|
34026
34722
|
const cutoffDate = new Date(Date.now() - SOFT_DELETE_RETENTION_DAYS2 * 24 * 60 * 60 * 1e3).toISOString();
|
|
34027
|
-
const
|
|
34723
|
+
const result3 = await client.execute({
|
|
34028
34724
|
sql: `SELECT COUNT(*) as cnt FROM memories WHERE status = 'deleted' AND deleted_at IS NOT NULL AND deleted_at < ?`,
|
|
34029
34725
|
args: [cutoffDate]
|
|
34030
34726
|
});
|
|
34031
|
-
const count = Number(
|
|
34727
|
+
const count = Number(result3.rows[0]?.cnt ?? 0);
|
|
34032
34728
|
if (count === 0) return;
|
|
34033
34729
|
await client.execute({
|
|
34034
34730
|
sql: `DELETE FROM memories WHERE status = 'deleted' AND deleted_at IS NOT NULL AND deleted_at < ?`,
|
|
@@ -34059,17 +34755,17 @@ function startIntercomQueueDrain() {
|
|
|
34059
34755
|
const hasInProgressTask = (session) => {
|
|
34060
34756
|
try {
|
|
34061
34757
|
const { baseAgentName: ban } = (init_employees(), __toCommonJS(employees_exports));
|
|
34062
|
-
const
|
|
34063
|
-
const { existsSync:
|
|
34758
|
+
const path62 = __require("path");
|
|
34759
|
+
const { existsSync: existsSync48 } = __require("fs");
|
|
34064
34760
|
const os25 = __require("os");
|
|
34065
34761
|
const agent = ban(session.split("-")[0] ?? session);
|
|
34066
|
-
const markerPath =
|
|
34067
|
-
return
|
|
34762
|
+
const markerPath = path62.join(os25.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
|
|
34763
|
+
return existsSync48(markerPath);
|
|
34068
34764
|
} catch {
|
|
34069
34765
|
return false;
|
|
34070
34766
|
}
|
|
34071
34767
|
};
|
|
34072
|
-
const
|
|
34768
|
+
const result3 = drainQueue3(
|
|
34073
34769
|
(session) => isSessionBusy2(session) || hasInProgressTask(session),
|
|
34074
34770
|
(session) => {
|
|
34075
34771
|
try {
|
|
@@ -34094,10 +34790,10 @@ function startIntercomQueueDrain() {
|
|
|
34094
34790
|
}
|
|
34095
34791
|
}
|
|
34096
34792
|
);
|
|
34097
|
-
if (
|
|
34793
|
+
if (result3.drained > 0 || result3.failed > 0) {
|
|
34098
34794
|
acted("intercom_queue_drain");
|
|
34099
34795
|
process.stderr.write(
|
|
34100
|
-
`[exed] Intercom queue: ${
|
|
34796
|
+
`[exed] Intercom queue: ${result3.drained} drained, ${result3.failed} failed
|
|
34101
34797
|
`
|
|
34102
34798
|
);
|
|
34103
34799
|
}
|
|
@@ -34276,8 +34972,8 @@ process.on("SIGINT", handleSignalShutdown);
|
|
|
34276
34972
|
process.on("SIGTERM", handleSignalShutdown);
|
|
34277
34973
|
function checkExistingDaemon() {
|
|
34278
34974
|
try {
|
|
34279
|
-
if (!
|
|
34280
|
-
const pid = parseInt(
|
|
34975
|
+
if (!existsSync47(PID_PATH4)) return false;
|
|
34976
|
+
const pid = parseInt(readFileSync41(PID_PATH4, "utf8").trim(), 10);
|
|
34281
34977
|
if (!pid || isNaN(pid)) return false;
|
|
34282
34978
|
if (pid === process.pid) {
|
|
34283
34979
|
try {
|
|
@@ -34313,22 +35009,22 @@ function startAutoUpdateCheck() {
|
|
|
34313
35009
|
if (!autoInstall && !config2.autoUpdate.checkOnBoot) return;
|
|
34314
35010
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update_check(), update_check_exports));
|
|
34315
35011
|
const packageRoot = new URL("../..", import.meta.url).pathname;
|
|
34316
|
-
const
|
|
34317
|
-
if (!
|
|
35012
|
+
const result3 = checkForUpdate2(packageRoot);
|
|
35013
|
+
if (!result3.updateAvailable) return;
|
|
34318
35014
|
acted("auto_update_check");
|
|
34319
35015
|
process.stderr.write(
|
|
34320
|
-
`[exed] Update available: v${
|
|
35016
|
+
`[exed] Update available: v${result3.localVersion} \u2192 v${result3.remoteVersion}
|
|
34321
35017
|
`
|
|
34322
35018
|
);
|
|
34323
35019
|
if (autoInstall) {
|
|
34324
35020
|
process.stderr.write("[exed] Auto-installing update...\n");
|
|
34325
|
-
const { execSync:
|
|
34326
|
-
|
|
35021
|
+
const { execSync: execSync17 } = await import("child_process");
|
|
35022
|
+
execSync17("npm install -g @askexenow/exe-os@latest", {
|
|
34327
35023
|
timeout: 12e4,
|
|
34328
35024
|
stdio: ["pipe", "pipe", "pipe"]
|
|
34329
35025
|
});
|
|
34330
35026
|
process.stderr.write(
|
|
34331
|
-
`[exed] Updated to v${
|
|
35027
|
+
`[exed] Updated to v${result3.remoteVersion}. Restart daemon to apply.
|
|
34332
35028
|
`
|
|
34333
35029
|
);
|
|
34334
35030
|
}
|