engrm 0.4.45 → 0.4.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +396 -118
- package/dist/hooks/elicitation-result.js +81 -15
- package/dist/hooks/post-tool-use.js +250 -23
- package/dist/hooks/pre-compact.js +249 -23
- package/dist/hooks/sentinel.js +81 -15
- package/dist/hooks/session-start.js +105 -17
- package/dist/hooks/stop.js +311 -27
- package/dist/hooks/user-prompt-submit.js +81 -15
- package/dist/server.js +193 -34
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -13564,11 +13564,20 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
13564
13564
|
import { homedir, hostname as hostname3, networkInterfaces } from "node:os";
|
|
13565
13565
|
import { join } from "node:path";
|
|
13566
13566
|
import { createHash } from "node:crypto";
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13567
|
+
function resolveConfigDir() {
|
|
13568
|
+
return process.env["ENGRM_CONFIG_DIR"]?.trim() || join(homedir(), ".engrm");
|
|
13569
|
+
}
|
|
13570
|
+
function resolveSettingsPath() {
|
|
13571
|
+
return join(resolveConfigDir(), "settings.json");
|
|
13572
|
+
}
|
|
13573
|
+
function resolveDbPath() {
|
|
13574
|
+
return join(resolveConfigDir(), "engrm.db");
|
|
13575
|
+
}
|
|
13576
|
+
function resolveAuthBackupPath() {
|
|
13577
|
+
return join(resolveConfigDir(), "auth-backup.json");
|
|
13578
|
+
}
|
|
13570
13579
|
function getDbPath() {
|
|
13571
|
-
return
|
|
13580
|
+
return resolveDbPath();
|
|
13572
13581
|
}
|
|
13573
13582
|
function generateDeviceId() {
|
|
13574
13583
|
const host = hostname3().toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
@@ -13591,7 +13600,7 @@ function generateDeviceId() {
|
|
|
13591
13600
|
return `${host}-${suffix}`;
|
|
13592
13601
|
}
|
|
13593
13602
|
function createDefaultConfig() {
|
|
13594
|
-
|
|
13603
|
+
const merged = {
|
|
13595
13604
|
candengo_url: "",
|
|
13596
13605
|
candengo_api_key: "",
|
|
13597
13606
|
site_id: "",
|
|
@@ -13646,24 +13655,26 @@ function createDefaultConfig() {
|
|
|
13646
13655
|
},
|
|
13647
13656
|
tool_profile: "full"
|
|
13648
13657
|
};
|
|
13658
|
+
return merged;
|
|
13649
13659
|
}
|
|
13650
13660
|
function loadConfig() {
|
|
13651
|
-
|
|
13652
|
-
|
|
13661
|
+
const settingsPath = resolveSettingsPath();
|
|
13662
|
+
if (!existsSync(settingsPath)) {
|
|
13663
|
+
throw new Error(`Config not found at ${settingsPath}. Run 'engrm init --manual' to configure.`);
|
|
13653
13664
|
}
|
|
13654
|
-
const raw = readFileSync(
|
|
13665
|
+
const raw = readFileSync(settingsPath, "utf-8");
|
|
13655
13666
|
let parsed;
|
|
13656
13667
|
try {
|
|
13657
13668
|
parsed = JSON.parse(raw);
|
|
13658
13669
|
} catch {
|
|
13659
|
-
throw new Error(`Invalid JSON in ${
|
|
13670
|
+
throw new Error(`Invalid JSON in ${settingsPath}`);
|
|
13660
13671
|
}
|
|
13661
13672
|
if (typeof parsed !== "object" || parsed === null) {
|
|
13662
|
-
throw new Error(`Config at ${
|
|
13673
|
+
throw new Error(`Config at ${settingsPath} is not a JSON object`);
|
|
13663
13674
|
}
|
|
13664
13675
|
const config2 = parsed;
|
|
13665
13676
|
const defaults = createDefaultConfig();
|
|
13666
|
-
|
|
13677
|
+
const merged = {
|
|
13667
13678
|
candengo_url: asString(config2["candengo_url"], defaults.candengo_url),
|
|
13668
13679
|
candengo_api_key: asString(config2["candengo_api_key"], defaults.candengo_api_key),
|
|
13669
13680
|
site_id: asString(config2["site_id"], defaults.site_id),
|
|
@@ -13718,16 +13729,27 @@ function loadConfig() {
|
|
|
13718
13729
|
},
|
|
13719
13730
|
tool_profile: asToolProfile(config2["tool_profile"], defaults.tool_profile)
|
|
13720
13731
|
};
|
|
13732
|
+
if (looksLikePlaceholderAuth(merged)) {
|
|
13733
|
+
return restoreAuthBackup(merged) ?? merged;
|
|
13734
|
+
}
|
|
13735
|
+
return merged;
|
|
13721
13736
|
}
|
|
13722
13737
|
function saveConfig(config2) {
|
|
13723
|
-
|
|
13724
|
-
|
|
13738
|
+
const configDir = resolveConfigDir();
|
|
13739
|
+
const settingsPath = resolveSettingsPath();
|
|
13740
|
+
const authBackupPath = resolveAuthBackupPath();
|
|
13741
|
+
if (!existsSync(configDir)) {
|
|
13742
|
+
mkdirSync(configDir, { recursive: true });
|
|
13725
13743
|
}
|
|
13726
|
-
writeFileSync(
|
|
13744
|
+
writeFileSync(settingsPath, JSON.stringify(config2, null, 2) + `
|
|
13745
|
+
`, "utf-8");
|
|
13746
|
+
if (!looksLikePlaceholderAuth(config2)) {
|
|
13747
|
+
writeFileSync(authBackupPath, JSON.stringify(extractAuthBackup(config2), null, 2) + `
|
|
13727
13748
|
`, "utf-8");
|
|
13749
|
+
}
|
|
13728
13750
|
}
|
|
13729
13751
|
function configExists() {
|
|
13730
|
-
return existsSync(
|
|
13752
|
+
return existsSync(resolveSettingsPath());
|
|
13731
13753
|
}
|
|
13732
13754
|
function asString(value, fallback) {
|
|
13733
13755
|
return typeof value === "string" ? value : fallback;
|
|
@@ -13781,6 +13803,50 @@ function asTeams(value, fallback) {
|
|
|
13781
13803
|
return fallback;
|
|
13782
13804
|
return value.filter((t) => typeof t === "object" && t !== null && typeof t.id === "string" && typeof t.name === "string" && typeof t.namespace === "string");
|
|
13783
13805
|
}
|
|
13806
|
+
function looksLikePlaceholderAuth(config2) {
|
|
13807
|
+
const apiKey = config2.candengo_api_key.trim();
|
|
13808
|
+
const siteId = config2.site_id.trim();
|
|
13809
|
+
const namespace = config2.namespace.trim();
|
|
13810
|
+
const email3 = config2.user_email.trim().toLowerCase();
|
|
13811
|
+
if (apiKey === "cvk_org" && siteId === "site-1" && namespace === "org-ns")
|
|
13812
|
+
return true;
|
|
13813
|
+
if (siteId === "site-1" && namespace === "org-ns" && email3.endsWith("@example.com"))
|
|
13814
|
+
return true;
|
|
13815
|
+
return false;
|
|
13816
|
+
}
|
|
13817
|
+
function extractAuthBackup(config2) {
|
|
13818
|
+
return {
|
|
13819
|
+
candengo_url: config2.candengo_url,
|
|
13820
|
+
candengo_api_key: config2.candengo_api_key,
|
|
13821
|
+
site_id: config2.site_id,
|
|
13822
|
+
namespace: config2.namespace,
|
|
13823
|
+
user_id: config2.user_id,
|
|
13824
|
+
user_email: config2.user_email,
|
|
13825
|
+
teams: config2.teams
|
|
13826
|
+
};
|
|
13827
|
+
}
|
|
13828
|
+
function restoreAuthBackup(config2) {
|
|
13829
|
+
const authBackupPath = resolveAuthBackupPath();
|
|
13830
|
+
if (!existsSync(authBackupPath))
|
|
13831
|
+
return null;
|
|
13832
|
+
try {
|
|
13833
|
+
const raw = readFileSync(authBackupPath, "utf-8");
|
|
13834
|
+
const parsed = JSON.parse(raw);
|
|
13835
|
+
const restored = {
|
|
13836
|
+
...config2,
|
|
13837
|
+
candengo_url: asString(parsed["candengo_url"], config2.candengo_url),
|
|
13838
|
+
candengo_api_key: asString(parsed["candengo_api_key"], config2.candengo_api_key),
|
|
13839
|
+
site_id: asString(parsed["site_id"], config2.site_id),
|
|
13840
|
+
namespace: asString(parsed["namespace"], config2.namespace),
|
|
13841
|
+
user_id: asString(parsed["user_id"], config2.user_id),
|
|
13842
|
+
user_email: asString(parsed["user_email"], config2.user_email),
|
|
13843
|
+
teams: asTeams(parsed["teams"], config2.teams)
|
|
13844
|
+
};
|
|
13845
|
+
return looksLikePlaceholderAuth(restored) ? null : restored;
|
|
13846
|
+
} catch {
|
|
13847
|
+
return null;
|
|
13848
|
+
}
|
|
13849
|
+
}
|
|
13784
13850
|
|
|
13785
13851
|
// src/storage/migrations.ts
|
|
13786
13852
|
var MIGRATIONS = [
|
|
@@ -19600,13 +19666,8 @@ function getCaptureStatus(db, input = {}) {
|
|
|
19600
19666
|
FROM sessions s
|
|
19601
19667
|
WHERE COALESCE(s.completed_at_epoch, s.started_at_epoch, 0) >= ?
|
|
19602
19668
|
${input.user_id ? "AND s.user_id = ?" : ""}
|
|
19603
|
-
AND
|
|
19604
|
-
|
|
19605
|
-
OR (
|
|
19606
|
-
EXISTS (SELECT 1 FROM user_prompts up WHERE up.session_id = s.session_id)
|
|
19607
|
-
AND NOT EXISTS (SELECT 1 FROM tool_events te WHERE te.session_id = s.session_id)
|
|
19608
|
-
)
|
|
19609
|
-
)`).get(...params)?.count ?? 0;
|
|
19669
|
+
AND s.tool_calls_count > 0
|
|
19670
|
+
AND NOT EXISTS (SELECT 1 FROM tool_events te WHERE te.session_id = s.session_id)`).get(...params)?.count ?? 0;
|
|
19610
19671
|
const latestPromptEpoch = db.db.query(`SELECT created_at_epoch FROM user_prompts
|
|
19611
19672
|
WHERE 1 = 1${input.user_id ? " AND user_id = ?" : ""}
|
|
19612
19673
|
ORDER BY created_at_epoch DESC, prompt_number DESC
|
|
@@ -20648,14 +20709,18 @@ function captureRepoScan(input = {}) {
|
|
|
20648
20709
|
|
|
20649
20710
|
// src/capture/transcript.ts
|
|
20650
20711
|
import { createHash as createHash3 } from "node:crypto";
|
|
20651
|
-
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
20712
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6, statSync, readdirSync } from "node:fs";
|
|
20652
20713
|
import { join as join4 } from "node:path";
|
|
20653
20714
|
import { homedir as homedir3 } from "node:os";
|
|
20654
20715
|
function resolveTranscriptPath(sessionId, cwd, transcriptPath) {
|
|
20655
20716
|
if (transcriptPath)
|
|
20656
20717
|
return transcriptPath;
|
|
20657
20718
|
const encodedCwd = cwd.replace(/\//g, "-");
|
|
20658
|
-
|
|
20719
|
+
const directPath = join4(homedir3(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
|
|
20720
|
+
if (existsSync6(directPath))
|
|
20721
|
+
return directPath;
|
|
20722
|
+
const discovered = findTranscriptPathBySessionId(sessionId);
|
|
20723
|
+
return discovered ?? directPath;
|
|
20659
20724
|
}
|
|
20660
20725
|
function readTranscript(sessionId, cwd, transcriptPath) {
|
|
20661
20726
|
const path = resolveTranscriptPath(sessionId, cwd, transcriptPath);
|
|
@@ -20678,10 +20743,10 @@ function readTranscript(sessionId, cwd, transcriptPath) {
|
|
|
20678
20743
|
} catch {
|
|
20679
20744
|
continue;
|
|
20680
20745
|
}
|
|
20681
|
-
const role = entry
|
|
20746
|
+
const role = getTranscriptRole(entry);
|
|
20682
20747
|
if (role !== "user" && role !== "assistant")
|
|
20683
20748
|
continue;
|
|
20684
|
-
const content = entry
|
|
20749
|
+
const content = getTranscriptContent(entry);
|
|
20685
20750
|
if (typeof content === "string") {
|
|
20686
20751
|
messages.push({ role, text: content });
|
|
20687
20752
|
continue;
|
|
@@ -20766,9 +20831,22 @@ function readHistoryFallback(sessionId, cwd, opts) {
|
|
|
20766
20831
|
createdAtEpoch: entry.timestamp
|
|
20767
20832
|
})));
|
|
20768
20833
|
}
|
|
20769
|
-
async function syncTranscriptChat(db, config2, sessionId, cwd, transcriptPath) {
|
|
20834
|
+
async function syncTranscriptChat(db, config2, sessionId, cwd, transcriptPath, options = {}) {
|
|
20835
|
+
const embed = options.embed ?? true;
|
|
20770
20836
|
const session = db.getSessionById(sessionId);
|
|
20771
|
-
const
|
|
20837
|
+
const resolvedTranscriptPath = resolveTranscriptPath(sessionId, cwd, transcriptPath);
|
|
20838
|
+
const syncCursorKey = `transcript_sync_cursor:${sessionId}`;
|
|
20839
|
+
if (existsSync6(resolvedTranscriptPath)) {
|
|
20840
|
+
try {
|
|
20841
|
+
const stat = statSync(resolvedTranscriptPath);
|
|
20842
|
+
const cursor = `${stat.size}:${Math.floor(stat.mtimeMs)}`;
|
|
20843
|
+
if (db.getSyncState(syncCursorKey) === cursor) {
|
|
20844
|
+
return { imported: 0, total: 0 };
|
|
20845
|
+
}
|
|
20846
|
+
db.setSyncState(syncCursorKey, cursor);
|
|
20847
|
+
} catch {}
|
|
20848
|
+
}
|
|
20849
|
+
const transcriptMessages = readTranscript(sessionId, cwd, resolvedTranscriptPath).map((message) => ({
|
|
20772
20850
|
...message,
|
|
20773
20851
|
text: message.text.trim()
|
|
20774
20852
|
})).filter((message) => message.text.length > 0);
|
|
@@ -20830,7 +20908,7 @@ async function syncTranscriptChat(db, config2, sessionId, cwd, transcriptPath) {
|
|
|
20830
20908
|
created_at_epoch: createdAtEpoch
|
|
20831
20909
|
});
|
|
20832
20910
|
}
|
|
20833
|
-
if (db.vecAvailable) {
|
|
20911
|
+
if (embed && db.vecAvailable) {
|
|
20834
20912
|
const embedding = await embedText(composeChatEmbeddingText(message.text));
|
|
20835
20913
|
if (embedding) {
|
|
20836
20914
|
db.vecChatInsert(row.id, embedding);
|
|
@@ -20857,6 +20935,29 @@ function buildHistorySourceId(sessionId, createdAtEpoch, text) {
|
|
|
20857
20935
|
const digest = createHash3("sha1").update(text).digest("hex").slice(0, 12);
|
|
20858
20936
|
return `history:${sessionId}:${createdAtEpoch}:${digest}`;
|
|
20859
20937
|
}
|
|
20938
|
+
function getTranscriptRole(entry) {
|
|
20939
|
+
return entry.role ?? entry.message?.role ?? entry.type ?? entry.message?.type;
|
|
20940
|
+
}
|
|
20941
|
+
function getTranscriptContent(entry) {
|
|
20942
|
+
return entry.content ?? entry.message?.content;
|
|
20943
|
+
}
|
|
20944
|
+
function findTranscriptPathBySessionId(sessionId) {
|
|
20945
|
+
const projectsDir = join4(homedir3(), ".claude", "projects");
|
|
20946
|
+
if (!existsSync6(projectsDir))
|
|
20947
|
+
return null;
|
|
20948
|
+
try {
|
|
20949
|
+
for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
|
|
20950
|
+
if (!entry.isDirectory())
|
|
20951
|
+
continue;
|
|
20952
|
+
const candidate = join4(projectsDir, entry.name, `${sessionId}.jsonl`);
|
|
20953
|
+
if (existsSync6(candidate))
|
|
20954
|
+
return candidate;
|
|
20955
|
+
}
|
|
20956
|
+
} catch {
|
|
20957
|
+
return null;
|
|
20958
|
+
}
|
|
20959
|
+
return null;
|
|
20960
|
+
}
|
|
20860
20961
|
|
|
20861
20962
|
// src/tools/repair-recall.ts
|
|
20862
20963
|
async function repairRecall(db, config2, input = {}) {
|
|
@@ -21664,6 +21765,10 @@ function isDue(db, key, interval, now) {
|
|
|
21664
21765
|
// src/sync/auth.ts
|
|
21665
21766
|
import { createHash as createHash4 } from "node:crypto";
|
|
21666
21767
|
var LEGACY_PUBLIC_HOSTS = new Set(["www.candengo.com", "candengo.com"]);
|
|
21768
|
+
var PLACEHOLDER_API_KEYS = new Set(["cvk_org"]);
|
|
21769
|
+
var PLACEHOLDER_SITE_IDS = new Set(["site-1"]);
|
|
21770
|
+
var PLACEHOLDER_NAMESPACES = new Set(["org-ns", "fleet-ns"]);
|
|
21771
|
+
var PLACEHOLDER_EMAIL_SUFFIXES = ["@example.com"];
|
|
21667
21772
|
function normalizeBaseUrl(url2) {
|
|
21668
21773
|
const trimmed = url2.trim();
|
|
21669
21774
|
if (!trimmed)
|
|
@@ -21682,7 +21787,7 @@ function getApiKey(config2) {
|
|
|
21682
21787
|
const envKey = process.env.ENGRM_TOKEN;
|
|
21683
21788
|
if (envKey && envKey.startsWith("cvk_"))
|
|
21684
21789
|
return envKey;
|
|
21685
|
-
if (config2.candengo_api_key && config2.candengo_api_key.length > 0) {
|
|
21790
|
+
if (config2.candengo_api_key && config2.candengo_api_key.length > 0 && !looksLikePlaceholderConfig(config2)) {
|
|
21686
21791
|
return config2.candengo_api_key;
|
|
21687
21792
|
}
|
|
21688
21793
|
return null;
|
|
@@ -21703,6 +21808,23 @@ ${apiKey}
|
|
|
21703
21808
|
${config2.namespace}
|
|
21704
21809
|
${config2.site_id}`).digest("hex");
|
|
21705
21810
|
}
|
|
21811
|
+
function looksLikePlaceholderConfig(config2) {
|
|
21812
|
+
const apiKey = config2.candengo_api_key?.trim() ?? "";
|
|
21813
|
+
const siteId = config2.site_id?.trim() ?? "";
|
|
21814
|
+
const namespace = config2.namespace?.trim() ?? "";
|
|
21815
|
+
const email3 = config2.user_email?.trim().toLowerCase() ?? "";
|
|
21816
|
+
if (PLACEHOLDER_API_KEYS.has(apiKey) && PLACEHOLDER_SITE_IDS.has(siteId) && PLACEHOLDER_NAMESPACES.has(namespace)) {
|
|
21817
|
+
return true;
|
|
21818
|
+
}
|
|
21819
|
+
if (PLACEHOLDER_SITE_IDS.has(siteId) && PLACEHOLDER_NAMESPACES.has(namespace) && PLACEHOLDER_EMAIL_SUFFIXES.some((suffix) => email3.endsWith(suffix))) {
|
|
21820
|
+
return true;
|
|
21821
|
+
}
|
|
21822
|
+
return false;
|
|
21823
|
+
}
|
|
21824
|
+
function clearSyncPushBlock(db) {
|
|
21825
|
+
db.setSyncState("sync_push_blocked_until", "0");
|
|
21826
|
+
db.setSyncState("sync_push_block_reason", "");
|
|
21827
|
+
}
|
|
21706
21828
|
function recoverOutboxAfterAuthChange(db, config2) {
|
|
21707
21829
|
const fingerprint = getAuthFingerprint(config2);
|
|
21708
21830
|
if (!fingerprint) {
|
|
@@ -21721,6 +21843,7 @@ function recoverOutboxAfterAuthChange(db, config2) {
|
|
|
21721
21843
|
const syncingReset = resetSyncingEntries(db);
|
|
21722
21844
|
const staleSyncingReset = 0;
|
|
21723
21845
|
db.setSyncState(key, fingerprint);
|
|
21846
|
+
clearSyncPushBlock(db);
|
|
21724
21847
|
return { fingerprintChanged: true, failedReset, authFailedReset: 0, syncingReset, staleSyncingReset };
|
|
21725
21848
|
}
|
|
21726
21849
|
function buildSourceId(config2, localId, type = "obs") {
|
|
@@ -22093,10 +22216,16 @@ function buildSummaryVectorDocument(summary, config2, project, targetOrObservati
|
|
|
22093
22216
|
};
|
|
22094
22217
|
}
|
|
22095
22218
|
async function pushOutbox(db, config2, batchSize = 50, options = {}) {
|
|
22219
|
+
resetStaleSyncingEntries(db);
|
|
22220
|
+
if (isPushBlocked(db)) {
|
|
22221
|
+
return { pushed: 0, failed: 0, skipped: 0, blocked: true };
|
|
22222
|
+
}
|
|
22096
22223
|
const entries = getPendingEntries(db, batchSize);
|
|
22097
22224
|
let pushed = 0;
|
|
22098
22225
|
let failed = 0;
|
|
22099
22226
|
let skipped = 0;
|
|
22227
|
+
let authFailures = 0;
|
|
22228
|
+
let rateLimitFailures = 0;
|
|
22100
22229
|
const batch = [];
|
|
22101
22230
|
for (const entry of entries) {
|
|
22102
22231
|
if (entry.record_type === "summary") {
|
|
@@ -22231,14 +22360,44 @@ async function pushOutbox(db, config2, batchSize = 50, options = {}) {
|
|
|
22231
22360
|
markSynced(db, entryId);
|
|
22232
22361
|
pushed++;
|
|
22233
22362
|
} catch (err) {
|
|
22234
|
-
|
|
22363
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
22364
|
+
const kind = classifyOutboxFailure(message);
|
|
22365
|
+
if (kind === "auth")
|
|
22366
|
+
authFailures++;
|
|
22367
|
+
if (kind === "rate_limit")
|
|
22368
|
+
rateLimitFailures++;
|
|
22369
|
+
markFailed(db, entryId, message);
|
|
22235
22370
|
failed++;
|
|
22236
22371
|
}
|
|
22237
22372
|
}
|
|
22238
22373
|
}
|
|
22239
22374
|
}
|
|
22375
|
+
updatePushCooldown(db, { pushed, authFailures, rateLimitFailures });
|
|
22240
22376
|
return { pushed, failed, skipped };
|
|
22241
22377
|
}
|
|
22378
|
+
var PUSH_BLOCK_UNTIL_KEY = "sync_push_blocked_until";
|
|
22379
|
+
var PUSH_BLOCK_REASON_KEY = "sync_push_block_reason";
|
|
22380
|
+
function isPushBlocked(db) {
|
|
22381
|
+
const blockedUntil = parseInt(db.getSyncState(PUSH_BLOCK_UNTIL_KEY) ?? "0", 10);
|
|
22382
|
+
return Number.isFinite(blockedUntil) && blockedUntil > Math.floor(Date.now() / 1000);
|
|
22383
|
+
}
|
|
22384
|
+
function updatePushCooldown(db, result) {
|
|
22385
|
+
const now = Math.floor(Date.now() / 1000);
|
|
22386
|
+
if (result.authFailures > 0) {
|
|
22387
|
+
db.setSyncState(PUSH_BLOCK_UNTIL_KEY, String(now + 365 * 24 * 60 * 60));
|
|
22388
|
+
db.setSyncState(PUSH_BLOCK_REASON_KEY, "auth");
|
|
22389
|
+
return;
|
|
22390
|
+
}
|
|
22391
|
+
if (result.rateLimitFailures > 0) {
|
|
22392
|
+
db.setSyncState(PUSH_BLOCK_UNTIL_KEY, String(now + 2 * 60));
|
|
22393
|
+
db.setSyncState(PUSH_BLOCK_REASON_KEY, "rate_limit");
|
|
22394
|
+
return;
|
|
22395
|
+
}
|
|
22396
|
+
if (result.pushed > 0) {
|
|
22397
|
+
db.setSyncState(PUSH_BLOCK_UNTIL_KEY, "0");
|
|
22398
|
+
db.setSyncState(PUSH_BLOCK_REASON_KEY, "");
|
|
22399
|
+
}
|
|
22400
|
+
}
|
|
22242
22401
|
function maybeScrubFleetDocument(doc2, target) {
|
|
22243
22402
|
if (!target.isFleet)
|
|
22244
22403
|
return doc2;
|
|
@@ -22637,7 +22796,7 @@ async function backfillEmbeddings(db, batchSize = 50) {
|
|
|
22637
22796
|
}
|
|
22638
22797
|
|
|
22639
22798
|
// src/packs/recommender.ts
|
|
22640
|
-
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync5 } from "node:fs";
|
|
22799
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
22641
22800
|
import { join as join5, basename as basename2, dirname as dirname2 } from "node:path";
|
|
22642
22801
|
import { fileURLToPath } from "node:url";
|
|
22643
22802
|
function getPacksDir() {
|
|
@@ -23290,7 +23449,7 @@ function installStdioLivenessGuards() {
|
|
|
23290
23449
|
function buildServer() {
|
|
23291
23450
|
const server = new McpServer({
|
|
23292
23451
|
name: "engrm",
|
|
23293
|
-
version: "0.4.
|
|
23452
|
+
version: "0.4.46"
|
|
23294
23453
|
});
|
|
23295
23454
|
const enabledToolNames = getEnabledToolNames(config2.tool_profile);
|
|
23296
23455
|
const originalTool = server.tool.bind(server);
|
|
@@ -25306,7 +25465,7 @@ async function main() {
|
|
|
25306
25465
|
await server.connect(transport);
|
|
25307
25466
|
}
|
|
25308
25467
|
function shouldStartHttpMode() {
|
|
25309
|
-
return process.argv.includes("--http") || Boolean(process.env.ENGRM_HTTP_PORT)
|
|
25468
|
+
return process.argv.includes("--http") || Boolean(process.env.ENGRM_HTTP_PORT);
|
|
25310
25469
|
}
|
|
25311
25470
|
function resolveHttpPort() {
|
|
25312
25471
|
const raw = process.env.ENGRM_HTTP_PORT;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engrm",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.46",
|
|
4
4
|
"description": "Shared memory across devices, sessions, and agents, with thin MCP tools for durable capture, live continuity, and Hermes-ready remote MCP support",
|
|
5
5
|
"mcpName": "io.github.dr12hes/engrm",
|
|
6
6
|
"type": "module",
|