@askexenow/exe-os 0.9.37 → 0.9.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deploy/stack-manifests/v0.9.json +55 -0
- package/dist/bin/backfill-conversations.js +36 -9
- package/dist/bin/backfill-responses.js +36 -9
- package/dist/bin/backfill-vectors.js +36 -9
- package/dist/bin/cleanup-stale-review-tasks.js +37 -10
- package/dist/bin/cli.js +624 -204
- package/dist/bin/exe-agent.js +13 -5
- package/dist/bin/exe-assign.js +36 -9
- package/dist/bin/exe-boot.js +50 -20
- package/dist/bin/exe-call.js +134 -342
- package/dist/bin/exe-dispatch.js +36 -9
- package/dist/bin/exe-doctor.js +39 -12
- package/dist/bin/exe-export-behaviors.js +38 -11
- package/dist/bin/exe-forget.js +36 -9
- package/dist/bin/exe-gateway.js +64 -15
- package/dist/bin/exe-heartbeat.js +37 -10
- package/dist/bin/exe-kill.js +36 -9
- package/dist/bin/exe-launch-agent.js +287 -1081
- package/dist/bin/exe-new-employee.js +100 -14
- package/dist/bin/exe-pending-messages.js +36 -9
- package/dist/bin/exe-pending-notifications.js +36 -9
- package/dist/bin/exe-pending-reviews.js +36 -9
- package/dist/bin/exe-rename.js +1780 -204
- package/dist/bin/exe-review.js +36 -9
- package/dist/bin/exe-search.js +38 -11
- package/dist/bin/exe-session-cleanup.js +38 -11
- package/dist/bin/exe-start-codex.js +38 -11
- package/dist/bin/exe-start-opencode.js +38 -11
- package/dist/bin/exe-status.js +37 -10
- package/dist/bin/exe-team.js +36 -9
- package/dist/bin/git-sweep.js +36 -9
- package/dist/bin/graph-backfill.js +36 -9
- package/dist/bin/graph-export.js +36 -9
- package/dist/bin/install.js +70 -3
- package/dist/bin/intercom-check.js +38 -11
- package/dist/bin/scan-tasks.js +36 -9
- package/dist/bin/setup.js +20 -19
- package/dist/bin/shard-migrate.js +36 -9
- package/dist/bin/stack-update.js +308 -0
- package/dist/gateway/index.js +62 -13
- package/dist/hooks/bug-report-worker.js +40 -12
- package/dist/hooks/codex-stop-task-finalizer.js +38 -11
- package/dist/hooks/commit-complete.js +36 -9
- package/dist/hooks/error-recall.js +38 -11
- package/dist/hooks/ingest.js +38 -10
- package/dist/hooks/instructions-loaded.js +44 -12
- package/dist/hooks/notification.js +36 -9
- package/dist/hooks/post-compact.js +36 -9
- package/dist/hooks/post-tool-combined.js +39 -12
- package/dist/hooks/pre-compact.js +37 -10
- package/dist/hooks/pre-tool-use.js +38 -10
- package/dist/hooks/prompt-submit.js +43 -15
- package/dist/hooks/session-end.js +37 -10
- package/dist/hooks/session-start.js +49 -16
- package/dist/hooks/stop.js +37 -10
- package/dist/hooks/subagent-stop.js +36 -9
- package/dist/hooks/summary-worker.js +45 -18
- package/dist/index.js +60 -11
- package/dist/lib/consolidation.js +2 -1
- package/dist/lib/employee-templates.js +4 -3
- package/dist/lib/employees.js +2 -1
- package/dist/lib/exe-daemon.js +11229 -10537
- package/dist/lib/hybrid-search.js +38 -11
- package/dist/lib/identity.js +8 -3
- package/dist/lib/schedules.js +36 -9
- package/dist/lib/store.js +36 -9
- package/dist/mcp/server.js +6873 -6249
- package/dist/mcp/tools/create-task.js +10 -4
- package/dist/runtime/index.js +36 -9
- package/dist/tui/App.js +42 -13
- package/package.json +4 -1
- package/stack.release.json +31 -0
- package/stack.release.schema.json +31 -0
package/dist/bin/exe-review.js
CHANGED
|
@@ -3264,7 +3264,7 @@ __export(shard_manager_exports, {
|
|
|
3264
3264
|
shardExists: () => shardExists
|
|
3265
3265
|
});
|
|
3266
3266
|
import path7 from "path";
|
|
3267
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
3267
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
3268
3268
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3269
3269
|
function initShardManager(encryptionKey) {
|
|
3270
3270
|
_encryptionKey = encryptionKey;
|
|
@@ -3286,7 +3286,7 @@ function getShardClient(projectName) {
|
|
|
3286
3286
|
if (!_encryptionKey) {
|
|
3287
3287
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3288
3288
|
}
|
|
3289
|
-
const safeName = projectName
|
|
3289
|
+
const safeName = safeShardName(projectName);
|
|
3290
3290
|
if (!safeName || safeName === "unknown") {
|
|
3291
3291
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3292
3292
|
}
|
|
@@ -3308,9 +3308,12 @@ function getShardClient(projectName) {
|
|
|
3308
3308
|
return client;
|
|
3309
3309
|
}
|
|
3310
3310
|
function shardExists(projectName) {
|
|
3311
|
-
const safeName = projectName
|
|
3311
|
+
const safeName = safeShardName(projectName);
|
|
3312
3312
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3313
3313
|
}
|
|
3314
|
+
function safeShardName(projectName) {
|
|
3315
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3316
|
+
}
|
|
3314
3317
|
function listShards() {
|
|
3315
3318
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
3316
3319
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3404,7 +3407,8 @@ async function ensureShardSchema(client) {
|
|
|
3404
3407
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3405
3408
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3406
3409
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3407
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3410
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3411
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3408
3412
|
]) {
|
|
3409
3413
|
try {
|
|
3410
3414
|
await client.execute(col);
|
|
@@ -3500,9 +3504,32 @@ async function ensureShardSchema(client) {
|
|
|
3500
3504
|
}
|
|
3501
3505
|
}
|
|
3502
3506
|
async function getReadyShardClient(projectName) {
|
|
3503
|
-
const
|
|
3504
|
-
|
|
3505
|
-
|
|
3507
|
+
const safeName = safeShardName(projectName);
|
|
3508
|
+
let client = getShardClient(projectName);
|
|
3509
|
+
try {
|
|
3510
|
+
await ensureShardSchema(client);
|
|
3511
|
+
return client;
|
|
3512
|
+
} catch (err) {
|
|
3513
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3514
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3515
|
+
client.close();
|
|
3516
|
+
_shards.delete(safeName);
|
|
3517
|
+
_shardLastAccess.delete(safeName);
|
|
3518
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3519
|
+
if (existsSync7(dbPath)) {
|
|
3520
|
+
const stat = statSync2(dbPath);
|
|
3521
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3522
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3523
|
+
renameSync3(dbPath, archivedPath);
|
|
3524
|
+
process.stderr.write(
|
|
3525
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3526
|
+
`
|
|
3527
|
+
);
|
|
3528
|
+
}
|
|
3529
|
+
client = getShardClient(projectName);
|
|
3530
|
+
await ensureShardSchema(client);
|
|
3531
|
+
return client;
|
|
3532
|
+
}
|
|
3506
3533
|
}
|
|
3507
3534
|
function evictLRU() {
|
|
3508
3535
|
let oldest = null;
|
|
@@ -3723,7 +3750,7 @@ var init_platform_procedures = __esm({
|
|
|
3723
3750
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3724
3751
|
domain: "tool-use",
|
|
3725
3752
|
priority: "p1",
|
|
3726
|
-
content: "
|
|
3753
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3727
3754
|
},
|
|
3728
3755
|
{
|
|
3729
3756
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -3741,7 +3768,7 @@ var init_platform_procedures = __esm({
|
|
|
3741
3768
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3742
3769
|
domain: "tool-use",
|
|
3743
3770
|
priority: "p1",
|
|
3744
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
3771
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3745
3772
|
}
|
|
3746
3773
|
];
|
|
3747
3774
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
package/dist/bin/exe-search.js
CHANGED
|
@@ -3239,7 +3239,7 @@ __export(shard_manager_exports, {
|
|
|
3239
3239
|
shardExists: () => shardExists
|
|
3240
3240
|
});
|
|
3241
3241
|
import path7 from "path";
|
|
3242
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
3242
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
3243
3243
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3244
3244
|
function initShardManager(encryptionKey) {
|
|
3245
3245
|
_encryptionKey = encryptionKey;
|
|
@@ -3261,7 +3261,7 @@ function getShardClient(projectName) {
|
|
|
3261
3261
|
if (!_encryptionKey) {
|
|
3262
3262
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3263
3263
|
}
|
|
3264
|
-
const safeName = projectName
|
|
3264
|
+
const safeName = safeShardName(projectName);
|
|
3265
3265
|
if (!safeName || safeName === "unknown") {
|
|
3266
3266
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3267
3267
|
}
|
|
@@ -3283,9 +3283,12 @@ function getShardClient(projectName) {
|
|
|
3283
3283
|
return client;
|
|
3284
3284
|
}
|
|
3285
3285
|
function shardExists(projectName) {
|
|
3286
|
-
const safeName = projectName
|
|
3286
|
+
const safeName = safeShardName(projectName);
|
|
3287
3287
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3288
3288
|
}
|
|
3289
|
+
function safeShardName(projectName) {
|
|
3290
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3291
|
+
}
|
|
3289
3292
|
function listShards() {
|
|
3290
3293
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
3291
3294
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3379,7 +3382,8 @@ async function ensureShardSchema(client) {
|
|
|
3379
3382
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3380
3383
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3381
3384
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3382
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3385
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3386
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3383
3387
|
]) {
|
|
3384
3388
|
try {
|
|
3385
3389
|
await client.execute(col);
|
|
@@ -3475,9 +3479,32 @@ async function ensureShardSchema(client) {
|
|
|
3475
3479
|
}
|
|
3476
3480
|
}
|
|
3477
3481
|
async function getReadyShardClient(projectName) {
|
|
3478
|
-
const
|
|
3479
|
-
|
|
3480
|
-
|
|
3482
|
+
const safeName = safeShardName(projectName);
|
|
3483
|
+
let client = getShardClient(projectName);
|
|
3484
|
+
try {
|
|
3485
|
+
await ensureShardSchema(client);
|
|
3486
|
+
return client;
|
|
3487
|
+
} catch (err) {
|
|
3488
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3489
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3490
|
+
client.close();
|
|
3491
|
+
_shards.delete(safeName);
|
|
3492
|
+
_shardLastAccess.delete(safeName);
|
|
3493
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3494
|
+
if (existsSync7(dbPath)) {
|
|
3495
|
+
const stat = statSync2(dbPath);
|
|
3496
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3497
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3498
|
+
renameSync3(dbPath, archivedPath);
|
|
3499
|
+
process.stderr.write(
|
|
3500
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3501
|
+
`
|
|
3502
|
+
);
|
|
3503
|
+
}
|
|
3504
|
+
client = getShardClient(projectName);
|
|
3505
|
+
await ensureShardSchema(client);
|
|
3506
|
+
return client;
|
|
3507
|
+
}
|
|
3481
3508
|
}
|
|
3482
3509
|
function evictLRU() {
|
|
3483
3510
|
let oldest = null;
|
|
@@ -3698,7 +3725,7 @@ var init_platform_procedures = __esm({
|
|
|
3698
3725
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3699
3726
|
domain: "tool-use",
|
|
3700
3727
|
priority: "p1",
|
|
3701
|
-
content: "
|
|
3728
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3702
3729
|
},
|
|
3703
3730
|
{
|
|
3704
3731
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -3716,7 +3743,7 @@ var init_platform_procedures = __esm({
|
|
|
3716
3743
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3717
3744
|
domain: "tool-use",
|
|
3718
3745
|
priority: "p1",
|
|
3719
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
3746
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3720
3747
|
}
|
|
3721
3748
|
];
|
|
3722
3749
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -4752,7 +4779,7 @@ __export(file_grep_exports, {
|
|
|
4752
4779
|
grepProjectFiles: () => grepProjectFiles
|
|
4753
4780
|
});
|
|
4754
4781
|
import { execSync as execSync4 } from "child_process";
|
|
4755
|
-
import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as
|
|
4782
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3, existsSync as existsSync9 } from "fs";
|
|
4756
4783
|
import path10 from "path";
|
|
4757
4784
|
import crypto2 from "crypto";
|
|
4758
4785
|
function hasRipgrep() {
|
|
@@ -4869,7 +4896,7 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
|
|
|
4869
4896
|
for (const filePath of files.slice(0, MAX_FILES)) {
|
|
4870
4897
|
const absPath = path10.join(projectRoot, filePath);
|
|
4871
4898
|
try {
|
|
4872
|
-
const stat =
|
|
4899
|
+
const stat = statSync3(absPath);
|
|
4873
4900
|
if (stat.size > MAX_FILE_SIZE) continue;
|
|
4874
4901
|
const content = readFileSync5(absPath, "utf8");
|
|
4875
4902
|
const lines = content.split("\n");
|
|
@@ -3283,7 +3283,7 @@ __export(shard_manager_exports, {
|
|
|
3283
3283
|
shardExists: () => shardExists
|
|
3284
3284
|
});
|
|
3285
3285
|
import path7 from "path";
|
|
3286
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
3286
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
3287
3287
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3288
3288
|
function initShardManager(encryptionKey) {
|
|
3289
3289
|
_encryptionKey = encryptionKey;
|
|
@@ -3305,7 +3305,7 @@ function getShardClient(projectName) {
|
|
|
3305
3305
|
if (!_encryptionKey) {
|
|
3306
3306
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
3307
3307
|
}
|
|
3308
|
-
const safeName = projectName
|
|
3308
|
+
const safeName = safeShardName(projectName);
|
|
3309
3309
|
if (!safeName || safeName === "unknown") {
|
|
3310
3310
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
3311
3311
|
}
|
|
@@ -3327,9 +3327,12 @@ function getShardClient(projectName) {
|
|
|
3327
3327
|
return client;
|
|
3328
3328
|
}
|
|
3329
3329
|
function shardExists(projectName) {
|
|
3330
|
-
const safeName = projectName
|
|
3330
|
+
const safeName = safeShardName(projectName);
|
|
3331
3331
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3332
3332
|
}
|
|
3333
|
+
function safeShardName(projectName) {
|
|
3334
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3335
|
+
}
|
|
3333
3336
|
function listShards() {
|
|
3334
3337
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
3335
3338
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -3423,7 +3426,8 @@ async function ensureShardSchema(client) {
|
|
|
3423
3426
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
3424
3427
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
3425
3428
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
3426
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
3429
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
3430
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
3427
3431
|
]) {
|
|
3428
3432
|
try {
|
|
3429
3433
|
await client.execute(col);
|
|
@@ -3519,9 +3523,32 @@ async function ensureShardSchema(client) {
|
|
|
3519
3523
|
}
|
|
3520
3524
|
}
|
|
3521
3525
|
async function getReadyShardClient(projectName) {
|
|
3522
|
-
const
|
|
3523
|
-
|
|
3524
|
-
|
|
3526
|
+
const safeName = safeShardName(projectName);
|
|
3527
|
+
let client = getShardClient(projectName);
|
|
3528
|
+
try {
|
|
3529
|
+
await ensureShardSchema(client);
|
|
3530
|
+
return client;
|
|
3531
|
+
} catch (err) {
|
|
3532
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3533
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
3534
|
+
client.close();
|
|
3535
|
+
_shards.delete(safeName);
|
|
3536
|
+
_shardLastAccess.delete(safeName);
|
|
3537
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3538
|
+
if (existsSync7(dbPath)) {
|
|
3539
|
+
const stat = statSync2(dbPath);
|
|
3540
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3541
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3542
|
+
renameSync3(dbPath, archivedPath);
|
|
3543
|
+
process.stderr.write(
|
|
3544
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
3545
|
+
`
|
|
3546
|
+
);
|
|
3547
|
+
}
|
|
3548
|
+
client = getShardClient(projectName);
|
|
3549
|
+
await ensureShardSchema(client);
|
|
3550
|
+
return client;
|
|
3551
|
+
}
|
|
3525
3552
|
}
|
|
3526
3553
|
function evictLRU() {
|
|
3527
3554
|
let oldest = null;
|
|
@@ -3742,7 +3769,7 @@ var init_platform_procedures = __esm({
|
|
|
3742
3769
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3743
3770
|
domain: "tool-use",
|
|
3744
3771
|
priority: "p1",
|
|
3745
|
-
content: "
|
|
3772
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3746
3773
|
},
|
|
3747
3774
|
{
|
|
3748
3775
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -3760,7 +3787,7 @@ var init_platform_procedures = __esm({
|
|
|
3760
3787
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3761
3788
|
domain: "tool-use",
|
|
3762
3789
|
priority: "p1",
|
|
3763
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
3790
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3764
3791
|
}
|
|
3765
3792
|
];
|
|
3766
3793
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -4816,7 +4843,7 @@ __export(intercom_queue_exports, {
|
|
|
4816
4843
|
queueIntercom: () => queueIntercom,
|
|
4817
4844
|
readQueue: () => readQueue
|
|
4818
4845
|
});
|
|
4819
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as
|
|
4846
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as existsSync10, mkdirSync as mkdirSync4 } from "fs";
|
|
4820
4847
|
import path10 from "path";
|
|
4821
4848
|
import os7 from "os";
|
|
4822
4849
|
function ensureDir() {
|
|
@@ -4835,7 +4862,7 @@ function writeQueue(queue) {
|
|
|
4835
4862
|
ensureDir();
|
|
4836
4863
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
4837
4864
|
writeFileSync5(tmp, JSON.stringify(queue, null, 2));
|
|
4838
|
-
|
|
4865
|
+
renameSync4(tmp, QUEUE_PATH);
|
|
4839
4866
|
}
|
|
4840
4867
|
function queueIntercom(targetSession, reason) {
|
|
4841
4868
|
const queue = readQueue();
|
|
@@ -2678,7 +2678,7 @@ __export(shard_manager_exports, {
|
|
|
2678
2678
|
shardExists: () => shardExists
|
|
2679
2679
|
});
|
|
2680
2680
|
import path7 from "path";
|
|
2681
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2681
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
2682
2682
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2683
2683
|
function initShardManager(encryptionKey) {
|
|
2684
2684
|
_encryptionKey = encryptionKey;
|
|
@@ -2700,7 +2700,7 @@ function getShardClient(projectName) {
|
|
|
2700
2700
|
if (!_encryptionKey) {
|
|
2701
2701
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2702
2702
|
}
|
|
2703
|
-
const safeName = projectName
|
|
2703
|
+
const safeName = safeShardName(projectName);
|
|
2704
2704
|
if (!safeName || safeName === "unknown") {
|
|
2705
2705
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2706
2706
|
}
|
|
@@ -2722,9 +2722,12 @@ function getShardClient(projectName) {
|
|
|
2722
2722
|
return client;
|
|
2723
2723
|
}
|
|
2724
2724
|
function shardExists(projectName) {
|
|
2725
|
-
const safeName = projectName
|
|
2725
|
+
const safeName = safeShardName(projectName);
|
|
2726
2726
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2727
2727
|
}
|
|
2728
|
+
function safeShardName(projectName) {
|
|
2729
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2730
|
+
}
|
|
2728
2731
|
function listShards() {
|
|
2729
2732
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
2730
2733
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -2818,7 +2821,8 @@ async function ensureShardSchema(client) {
|
|
|
2818
2821
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
2819
2822
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
2820
2823
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
2821
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
2824
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
2825
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
2822
2826
|
]) {
|
|
2823
2827
|
try {
|
|
2824
2828
|
await client.execute(col);
|
|
@@ -2914,9 +2918,32 @@ async function ensureShardSchema(client) {
|
|
|
2914
2918
|
}
|
|
2915
2919
|
}
|
|
2916
2920
|
async function getReadyShardClient(projectName) {
|
|
2917
|
-
const
|
|
2918
|
-
|
|
2919
|
-
|
|
2921
|
+
const safeName = safeShardName(projectName);
|
|
2922
|
+
let client = getShardClient(projectName);
|
|
2923
|
+
try {
|
|
2924
|
+
await ensureShardSchema(client);
|
|
2925
|
+
return client;
|
|
2926
|
+
} catch (err) {
|
|
2927
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2928
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
2929
|
+
client.close();
|
|
2930
|
+
_shards.delete(safeName);
|
|
2931
|
+
_shardLastAccess.delete(safeName);
|
|
2932
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
2933
|
+
if (existsSync7(dbPath)) {
|
|
2934
|
+
const stat = statSync2(dbPath);
|
|
2935
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2936
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
2937
|
+
renameSync3(dbPath, archivedPath);
|
|
2938
|
+
process.stderr.write(
|
|
2939
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
2940
|
+
`
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
client = getShardClient(projectName);
|
|
2944
|
+
await ensureShardSchema(client);
|
|
2945
|
+
return client;
|
|
2946
|
+
}
|
|
2920
2947
|
}
|
|
2921
2948
|
function evictLRU() {
|
|
2922
2949
|
let oldest = null;
|
|
@@ -3137,7 +3164,7 @@ var init_platform_procedures = __esm({
|
|
|
3137
3164
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3138
3165
|
domain: "tool-use",
|
|
3139
3166
|
priority: "p1",
|
|
3140
|
-
content: "
|
|
3167
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3141
3168
|
},
|
|
3142
3169
|
{
|
|
3143
3170
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -3155,7 +3182,7 @@ var init_platform_procedures = __esm({
|
|
|
3155
3182
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3156
3183
|
domain: "tool-use",
|
|
3157
3184
|
priority: "p1",
|
|
3158
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
3185
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3159
3186
|
}
|
|
3160
3187
|
];
|
|
3161
3188
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -4619,7 +4646,7 @@ import {
|
|
|
4619
4646
|
existsSync as existsSync8,
|
|
4620
4647
|
mkdirSync as mkdirSync3,
|
|
4621
4648
|
readdirSync as readdirSync2,
|
|
4622
|
-
statSync as
|
|
4649
|
+
statSync as statSync3,
|
|
4623
4650
|
unlinkSync as unlinkSync3,
|
|
4624
4651
|
writeFileSync as writeFileSync3
|
|
4625
4652
|
} from "fs";
|
|
@@ -4684,7 +4711,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
|
|
|
4684
4711
|
for (const entry of entries) {
|
|
4685
4712
|
const filePath = path8.join(BEHAVIORS_EXPORT_DIR, entry);
|
|
4686
4713
|
try {
|
|
4687
|
-
const stat =
|
|
4714
|
+
const stat = statSync3(filePath);
|
|
4688
4715
|
if (now - stat.mtimeMs > STALE_EXPORT_AGE_MS) {
|
|
4689
4716
|
unlinkSync3(filePath);
|
|
4690
4717
|
}
|
|
@@ -2678,7 +2678,7 @@ __export(shard_manager_exports, {
|
|
|
2678
2678
|
shardExists: () => shardExists
|
|
2679
2679
|
});
|
|
2680
2680
|
import path7 from "path";
|
|
2681
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2681
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
2682
2682
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2683
2683
|
function initShardManager(encryptionKey) {
|
|
2684
2684
|
_encryptionKey = encryptionKey;
|
|
@@ -2700,7 +2700,7 @@ function getShardClient(projectName) {
|
|
|
2700
2700
|
if (!_encryptionKey) {
|
|
2701
2701
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2702
2702
|
}
|
|
2703
|
-
const safeName = projectName
|
|
2703
|
+
const safeName = safeShardName(projectName);
|
|
2704
2704
|
if (!safeName || safeName === "unknown") {
|
|
2705
2705
|
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2706
2706
|
}
|
|
@@ -2722,9 +2722,12 @@ function getShardClient(projectName) {
|
|
|
2722
2722
|
return client;
|
|
2723
2723
|
}
|
|
2724
2724
|
function shardExists(projectName) {
|
|
2725
|
-
const safeName = projectName
|
|
2725
|
+
const safeName = safeShardName(projectName);
|
|
2726
2726
|
return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2727
2727
|
}
|
|
2728
|
+
function safeShardName(projectName) {
|
|
2729
|
+
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2730
|
+
}
|
|
2728
2731
|
function listShards() {
|
|
2729
2732
|
if (!existsSync7(SHARDS_DIR)) return [];
|
|
2730
2733
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
@@ -2818,7 +2821,8 @@ async function ensureShardSchema(client) {
|
|
|
2818
2821
|
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
2819
2822
|
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
2820
2823
|
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
2821
|
-
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
2824
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
|
|
2825
|
+
"ALTER TABLE memories ADD COLUMN deleted_at TEXT"
|
|
2822
2826
|
]) {
|
|
2823
2827
|
try {
|
|
2824
2828
|
await client.execute(col);
|
|
@@ -2914,9 +2918,32 @@ async function ensureShardSchema(client) {
|
|
|
2914
2918
|
}
|
|
2915
2919
|
}
|
|
2916
2920
|
async function getReadyShardClient(projectName) {
|
|
2917
|
-
const
|
|
2918
|
-
|
|
2919
|
-
|
|
2921
|
+
const safeName = safeShardName(projectName);
|
|
2922
|
+
let client = getShardClient(projectName);
|
|
2923
|
+
try {
|
|
2924
|
+
await ensureShardSchema(client);
|
|
2925
|
+
return client;
|
|
2926
|
+
} catch (err) {
|
|
2927
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2928
|
+
if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
|
|
2929
|
+
client.close();
|
|
2930
|
+
_shards.delete(safeName);
|
|
2931
|
+
_shardLastAccess.delete(safeName);
|
|
2932
|
+
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
2933
|
+
if (existsSync7(dbPath)) {
|
|
2934
|
+
const stat = statSync2(dbPath);
|
|
2935
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2936
|
+
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
2937
|
+
renameSync3(dbPath, archivedPath);
|
|
2938
|
+
process.stderr.write(
|
|
2939
|
+
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
2940
|
+
`
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
client = getShardClient(projectName);
|
|
2944
|
+
await ensureShardSchema(client);
|
|
2945
|
+
return client;
|
|
2946
|
+
}
|
|
2920
2947
|
}
|
|
2921
2948
|
function evictLRU() {
|
|
2922
2949
|
let oldest = null;
|
|
@@ -3137,7 +3164,7 @@ var init_platform_procedures = __esm({
|
|
|
3137
3164
|
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3138
3165
|
domain: "tool-use",
|
|
3139
3166
|
priority: "p1",
|
|
3140
|
-
content: "
|
|
3167
|
+
content: "wiki: read/list wiki pages only. Direct wiki write tools are removed; wiki updates flow through raw-data ingestion/projection into the curated wiki store. Legacy aliases: list_wiki_pages/get_wiki_page. crm: read/list/get CRM records from exe-db. raw_data: read capped raw landing-pad events from exe-db with payload opt-in. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3141
3168
|
},
|
|
3142
3169
|
{
|
|
3143
3170
|
title: "MCP tools \u2014 system, operations, and admin",
|
|
@@ -3155,7 +3182,7 @@ var init_platform_procedures = __esm({
|
|
|
3155
3182
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3156
3183
|
domain: "tool-use",
|
|
3157
3184
|
priority: "p1",
|
|
3158
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage
|
|
3185
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3159
3186
|
}
|
|
3160
3187
|
];
|
|
3161
3188
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -4484,7 +4511,7 @@ import {
|
|
|
4484
4511
|
existsSync as existsSync8,
|
|
4485
4512
|
mkdirSync as mkdirSync3,
|
|
4486
4513
|
readdirSync as readdirSync2,
|
|
4487
|
-
statSync as
|
|
4514
|
+
statSync as statSync3,
|
|
4488
4515
|
unlinkSync as unlinkSync3,
|
|
4489
4516
|
writeFileSync as writeFileSync3
|
|
4490
4517
|
} from "fs";
|
|
@@ -4549,7 +4576,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
|
|
|
4549
4576
|
for (const entry of entries) {
|
|
4550
4577
|
const filePath = path8.join(BEHAVIORS_EXPORT_DIR, entry);
|
|
4551
4578
|
try {
|
|
4552
|
-
const stat =
|
|
4579
|
+
const stat = statSync3(filePath);
|
|
4553
4580
|
if (now - stat.mtimeMs > STALE_EXPORT_AGE_MS) {
|
|
4554
4581
|
unlinkSync3(filePath);
|
|
4555
4582
|
}
|