@askexenow/exe-os 0.9.34 → 0.9.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/backfill-conversations.js +210 -10
- package/dist/bin/backfill-responses.js +210 -10
- package/dist/bin/backfill-vectors.js +13 -2
- package/dist/bin/cleanup-stale-review-tasks.js +217 -10
- package/dist/bin/cli.js +222 -11
- package/dist/bin/exe-assign.js +210 -10
- package/dist/bin/exe-boot.js +24 -3
- package/dist/bin/exe-dispatch.js +222 -11
- package/dist/bin/exe-doctor.js +13 -2
- package/dist/bin/exe-export-behaviors.js +217 -10
- package/dist/bin/exe-forget.js +217 -10
- package/dist/bin/exe-gateway.js +222 -11
- package/dist/bin/exe-heartbeat.js +217 -10
- package/dist/bin/exe-kill.js +217 -10
- package/dist/bin/exe-launch-agent.js +92 -2
- package/dist/bin/exe-link.js +8 -0
- package/dist/bin/exe-pending-messages.js +217 -10
- package/dist/bin/exe-pending-notifications.js +217 -10
- package/dist/bin/exe-pending-reviews.js +217 -10
- package/dist/bin/exe-rename.js +8 -0
- package/dist/bin/exe-review.js +217 -10
- package/dist/bin/exe-search.js +217 -10
- package/dist/bin/exe-session-cleanup.js +222 -11
- package/dist/bin/exe-start-codex.js +92 -2
- package/dist/bin/exe-start-opencode.js +92 -2
- package/dist/bin/exe-status.js +217 -10
- package/dist/bin/exe-team.js +217 -10
- package/dist/bin/git-sweep.js +222 -11
- package/dist/bin/graph-backfill.js +92 -2
- package/dist/bin/graph-export.js +217 -10
- package/dist/bin/intercom-check.js +222 -11
- package/dist/bin/scan-tasks.js +222 -11
- package/dist/bin/setup.js +8 -0
- package/dist/bin/shard-migrate.js +92 -2
- package/dist/gateway/index.js +222 -11
- package/dist/hooks/bug-report-worker.js +222 -11
- package/dist/hooks/codex-stop-task-finalizer.js +217 -10
- package/dist/hooks/commit-complete.js +222 -11
- package/dist/hooks/error-recall.js +217 -10
- package/dist/hooks/ingest.js +217 -10
- package/dist/hooks/instructions-loaded.js +217 -10
- package/dist/hooks/notification.js +217 -10
- package/dist/hooks/post-compact.js +217 -10
- package/dist/hooks/post-tool-combined.js +217 -10
- package/dist/hooks/pre-compact.js +222 -11
- package/dist/hooks/pre-tool-use.js +217 -10
- package/dist/hooks/prompt-submit.js +222 -11
- package/dist/hooks/session-end.js +222 -11
- package/dist/hooks/session-start.js +217 -10
- package/dist/hooks/stop.js +217 -10
- package/dist/hooks/subagent-stop.js +217 -10
- package/dist/hooks/summary-worker.js +14 -1
- package/dist/index.js +222 -11
- package/dist/lib/cloud-sync.js +8 -0
- package/dist/lib/consolidation.js +3 -1
- package/dist/lib/database.js +8 -0
- package/dist/lib/db.js +8 -0
- package/dist/lib/device-registry.js +8 -0
- package/dist/lib/exe-daemon.js +1667 -1413
- package/dist/lib/hybrid-search.js +217 -10
- package/dist/lib/schedules.js +13 -2
- package/dist/lib/store.js +210 -10
- package/dist/lib/tasks.js +5 -1
- package/dist/lib/tmux-routing.js +5 -1
- package/dist/mcp/server.js +222 -11
- package/dist/mcp/tools/create-task.js +5 -1
- package/dist/mcp/tools/update-task.js +5 -1
- package/dist/runtime/index.js +222 -11
- package/dist/tui/App.js +222 -11
- package/package.json +1 -1
|
@@ -2073,6 +2073,14 @@ async function ensureSchema() {
|
|
|
2073
2073
|
);
|
|
2074
2074
|
} catch {
|
|
2075
2075
|
}
|
|
2076
|
+
try {
|
|
2077
|
+
await client.execute(
|
|
2078
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2079
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2080
|
+
WHERE content_hash IS NOT NULL`
|
|
2081
|
+
);
|
|
2082
|
+
} catch {
|
|
2083
|
+
}
|
|
2076
2084
|
await client.executeMultiple(`
|
|
2077
2085
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2078
2086
|
id TEXT PRIMARY KEY,
|
|
@@ -2742,7 +2750,8 @@ async function ensureShardSchema(client) {
|
|
|
2742
2750
|
}
|
|
2743
2751
|
for (const idx of [
|
|
2744
2752
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
2745
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
2753
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
2754
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash ON memories(content_hash, agent_id, project_name, memory_type) WHERE content_hash IS NOT NULL"
|
|
2746
2755
|
]) {
|
|
2747
2756
|
try {
|
|
2748
2757
|
await client.execute(idx);
|
|
@@ -3152,7 +3161,6 @@ ${p.content}`).join("\n\n");
|
|
|
3152
3161
|
// src/lib/store.ts
|
|
3153
3162
|
init_memory();
|
|
3154
3163
|
init_database();
|
|
3155
|
-
import { createHash } from "crypto";
|
|
3156
3164
|
|
|
3157
3165
|
// src/lib/keychain.ts
|
|
3158
3166
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
@@ -3385,6 +3393,87 @@ var StateBus = class {
|
|
|
3385
3393
|
};
|
|
3386
3394
|
var orgBus = new StateBus();
|
|
3387
3395
|
|
|
3396
|
+
// src/lib/memory-write-governor.ts
|
|
3397
|
+
import { createHash } from "crypto";
|
|
3398
|
+
var HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
3399
|
+
"decision",
|
|
3400
|
+
"adr",
|
|
3401
|
+
"behavior",
|
|
3402
|
+
"procedure"
|
|
3403
|
+
]);
|
|
3404
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3405
|
+
try {
|
|
3406
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3407
|
+
const client = getClient2();
|
|
3408
|
+
const current = await client.execute({
|
|
3409
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
3410
|
+
importance, timestamp
|
|
3411
|
+
FROM memories
|
|
3412
|
+
WHERE id = ?
|
|
3413
|
+
LIMIT 1`,
|
|
3414
|
+
args: [memoryId]
|
|
3415
|
+
});
|
|
3416
|
+
const row = current.rows[0];
|
|
3417
|
+
if (!row) return;
|
|
3418
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
3419
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
3420
|
+
const agentId = String(row.agent_id);
|
|
3421
|
+
const projectName = String(row.project_name);
|
|
3422
|
+
if (contentHash) {
|
|
3423
|
+
await client.execute({
|
|
3424
|
+
sql: `UPDATE memories
|
|
3425
|
+
SET status = 'deleted',
|
|
3426
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3427
|
+
WHERE id != ?
|
|
3428
|
+
AND content_hash = ?
|
|
3429
|
+
AND agent_id = ?
|
|
3430
|
+
AND project_name = ?
|
|
3431
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3432
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
3433
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
3437
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
3438
|
+
const old = await client.execute({
|
|
3439
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
3440
|
+
args: [supersedesId]
|
|
3441
|
+
});
|
|
3442
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
3443
|
+
const newImportance = Number(row.importance ?? 0);
|
|
3444
|
+
await client.batch([
|
|
3445
|
+
{
|
|
3446
|
+
sql: `UPDATE memories
|
|
3447
|
+
SET status = 'archived',
|
|
3448
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3449
|
+
WHERE id = ?`,
|
|
3450
|
+
args: [supersedesId]
|
|
3451
|
+
},
|
|
3452
|
+
{
|
|
3453
|
+
sql: `UPDATE memories
|
|
3454
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
3455
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
3456
|
+
WHERE id = ?`,
|
|
3457
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
3458
|
+
}
|
|
3459
|
+
], "write");
|
|
3460
|
+
}
|
|
3461
|
+
} catch (err) {
|
|
3462
|
+
process.stderr.write(
|
|
3463
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
3464
|
+
`
|
|
3465
|
+
);
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3468
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
3469
|
+
if (memoryIds.length === 0) return;
|
|
3470
|
+
const run = () => {
|
|
3471
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
3472
|
+
};
|
|
3473
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
3474
|
+
else setTimeout(run, 0);
|
|
3475
|
+
}
|
|
3476
|
+
|
|
3388
3477
|
// src/lib/store.ts
|
|
3389
3478
|
var INIT_MAX_RETRIES = 3;
|
|
3390
3479
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
@@ -3584,6 +3673,7 @@ async function flushBatch() {
|
|
|
3584
3673
|
const globalClient = getClient();
|
|
3585
3674
|
const globalStmts = batch.map(buildStmt);
|
|
3586
3675
|
await globalClient.batch(globalStmts, "write");
|
|
3676
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
3587
3677
|
_pendingRecords.splice(0, batch.length);
|
|
3588
3678
|
try {
|
|
3589
3679
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
package/dist/gateway/index.js
CHANGED
|
@@ -2932,6 +2932,14 @@ async function ensureSchema() {
|
|
|
2932
2932
|
);
|
|
2933
2933
|
} catch {
|
|
2934
2934
|
}
|
|
2935
|
+
try {
|
|
2936
|
+
await client.execute(
|
|
2937
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2938
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2939
|
+
WHERE content_hash IS NOT NULL`
|
|
2940
|
+
);
|
|
2941
|
+
} catch {
|
|
2942
|
+
}
|
|
2935
2943
|
await client.executeMultiple(`
|
|
2936
2944
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2937
2945
|
id TEXT PRIMARY KEY,
|
|
@@ -3690,6 +3698,196 @@ var init_keychain = __esm({
|
|
|
3690
3698
|
}
|
|
3691
3699
|
});
|
|
3692
3700
|
|
|
3701
|
+
// src/lib/memory-write-governor.ts
|
|
3702
|
+
import { createHash } from "crypto";
|
|
3703
|
+
function normalizeMemoryText(text) {
|
|
3704
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
3705
|
+
}
|
|
3706
|
+
function classifyMemoryType(input) {
|
|
3707
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
3708
|
+
const tool = input.tool_name.toLowerCase();
|
|
3709
|
+
const text = input.raw_text.toLowerCase();
|
|
3710
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
3711
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
3712
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
3713
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
3714
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
3715
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
3716
|
+
return "raw";
|
|
3717
|
+
}
|
|
3718
|
+
function shouldDropMemory(text) {
|
|
3719
|
+
const normalized = normalizeMemoryText(text);
|
|
3720
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
3721
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
3722
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
3723
|
+
}
|
|
3724
|
+
return { drop: false };
|
|
3725
|
+
}
|
|
3726
|
+
function shouldSkipEmbedding(input) {
|
|
3727
|
+
const type = classifyMemoryType(input);
|
|
3728
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
3729
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
3730
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
3731
|
+
return false;
|
|
3732
|
+
}
|
|
3733
|
+
function hashMemoryContent(text) {
|
|
3734
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
3735
|
+
}
|
|
3736
|
+
function scopedDedupArgs(input) {
|
|
3737
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
3738
|
+
}
|
|
3739
|
+
function governMemoryRecord(record) {
|
|
3740
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
3741
|
+
const memoryType = classifyMemoryType({
|
|
3742
|
+
raw_text: normalized,
|
|
3743
|
+
agent_id: record.agent_id,
|
|
3744
|
+
project_name: record.project_name,
|
|
3745
|
+
tool_name: record.tool_name,
|
|
3746
|
+
memory_type: record.memory_type
|
|
3747
|
+
});
|
|
3748
|
+
const drop = shouldDropMemory(normalized);
|
|
3749
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
3750
|
+
raw_text: normalized,
|
|
3751
|
+
agent_id: record.agent_id,
|
|
3752
|
+
project_name: record.project_name,
|
|
3753
|
+
tool_name: record.tool_name,
|
|
3754
|
+
memory_type: memoryType
|
|
3755
|
+
});
|
|
3756
|
+
return {
|
|
3757
|
+
record: {
|
|
3758
|
+
...record,
|
|
3759
|
+
raw_text: normalized,
|
|
3760
|
+
memory_type: memoryType,
|
|
3761
|
+
vector: skipEmbedding ? null : record.vector
|
|
3762
|
+
},
|
|
3763
|
+
contentHash: hashMemoryContent(normalized),
|
|
3764
|
+
shouldDrop: drop.drop,
|
|
3765
|
+
dropReason: drop.reason,
|
|
3766
|
+
skipEmbedding,
|
|
3767
|
+
hygiene: {
|
|
3768
|
+
dedup: true,
|
|
3769
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3773
|
+
async function findScopedDuplicate(input) {
|
|
3774
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3775
|
+
const client = getClient2();
|
|
3776
|
+
const args = scopedDedupArgs(input);
|
|
3777
|
+
let sql = `SELECT id FROM memories
|
|
3778
|
+
WHERE content_hash = ?
|
|
3779
|
+
AND agent_id = ?
|
|
3780
|
+
AND project_name = ?
|
|
3781
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3782
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
3783
|
+
if (input.excludeId) {
|
|
3784
|
+
sql += " AND id != ?";
|
|
3785
|
+
args.push(input.excludeId);
|
|
3786
|
+
}
|
|
3787
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
3788
|
+
const result = await client.execute({ sql, args });
|
|
3789
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
3790
|
+
}
|
|
3791
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3792
|
+
try {
|
|
3793
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3794
|
+
const client = getClient2();
|
|
3795
|
+
const current = await client.execute({
|
|
3796
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
3797
|
+
importance, timestamp
|
|
3798
|
+
FROM memories
|
|
3799
|
+
WHERE id = ?
|
|
3800
|
+
LIMIT 1`,
|
|
3801
|
+
args: [memoryId]
|
|
3802
|
+
});
|
|
3803
|
+
const row = current.rows[0];
|
|
3804
|
+
if (!row) return;
|
|
3805
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
3806
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
3807
|
+
const agentId = String(row.agent_id);
|
|
3808
|
+
const projectName = String(row.project_name);
|
|
3809
|
+
if (contentHash) {
|
|
3810
|
+
await client.execute({
|
|
3811
|
+
sql: `UPDATE memories
|
|
3812
|
+
SET status = 'deleted',
|
|
3813
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3814
|
+
WHERE id != ?
|
|
3815
|
+
AND content_hash = ?
|
|
3816
|
+
AND agent_id = ?
|
|
3817
|
+
AND project_name = ?
|
|
3818
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3819
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
3820
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
3821
|
+
});
|
|
3822
|
+
}
|
|
3823
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
3824
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
3825
|
+
const old = await client.execute({
|
|
3826
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
3827
|
+
args: [supersedesId]
|
|
3828
|
+
});
|
|
3829
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
3830
|
+
const newImportance = Number(row.importance ?? 0);
|
|
3831
|
+
await client.batch([
|
|
3832
|
+
{
|
|
3833
|
+
sql: `UPDATE memories
|
|
3834
|
+
SET status = 'archived',
|
|
3835
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3836
|
+
WHERE id = ?`,
|
|
3837
|
+
args: [supersedesId]
|
|
3838
|
+
},
|
|
3839
|
+
{
|
|
3840
|
+
sql: `UPDATE memories
|
|
3841
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
3842
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
3843
|
+
WHERE id = ?`,
|
|
3844
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
3845
|
+
}
|
|
3846
|
+
], "write");
|
|
3847
|
+
}
|
|
3848
|
+
} catch (err) {
|
|
3849
|
+
process.stderr.write(
|
|
3850
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
3851
|
+
`
|
|
3852
|
+
);
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
3856
|
+
if (memoryIds.length === 0) return;
|
|
3857
|
+
const run = () => {
|
|
3858
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
3859
|
+
};
|
|
3860
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
3861
|
+
else setTimeout(run, 0);
|
|
3862
|
+
}
|
|
3863
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
3864
|
+
var init_memory_write_governor = __esm({
|
|
3865
|
+
"src/lib/memory-write-governor.ts"() {
|
|
3866
|
+
"use strict";
|
|
3867
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
3868
|
+
"decision",
|
|
3869
|
+
"adr",
|
|
3870
|
+
"behavior",
|
|
3871
|
+
"procedure"
|
|
3872
|
+
]);
|
|
3873
|
+
NOISE_DROP_PATTERNS = [
|
|
3874
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
3875
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
3876
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
3877
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
3878
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
3879
|
+
];
|
|
3880
|
+
SKIP_EMBED_PATTERNS = [
|
|
3881
|
+
/tmux capture-pane\b/i,
|
|
3882
|
+
/docker ps\b/i,
|
|
3883
|
+
/docker images\b/i,
|
|
3884
|
+
/git status\b/i,
|
|
3885
|
+
/grep .*node_modules/i,
|
|
3886
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
3887
|
+
];
|
|
3888
|
+
}
|
|
3889
|
+
});
|
|
3890
|
+
|
|
3693
3891
|
// src/lib/shard-manager.ts
|
|
3694
3892
|
var shard_manager_exports = {};
|
|
3695
3893
|
__export(shard_manager_exports, {
|
|
@@ -3854,7 +4052,8 @@ async function ensureShardSchema(client) {
|
|
|
3854
4052
|
}
|
|
3855
4053
|
for (const idx of [
|
|
3856
4054
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
3857
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
4055
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
4056
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash ON memories(content_hash, agent_id, project_name, memory_type) WHERE content_hash IS NOT NULL"
|
|
3858
4057
|
]) {
|
|
3859
4058
|
try {
|
|
3860
4059
|
await client.execute(idx);
|
|
@@ -4279,7 +4478,6 @@ __export(store_exports, {
|
|
|
4279
4478
|
vectorToBlob: () => vectorToBlob,
|
|
4280
4479
|
writeMemory: () => writeMemory
|
|
4281
4480
|
});
|
|
4282
|
-
import { createHash } from "crypto";
|
|
4283
4481
|
function isBusyError2(err) {
|
|
4284
4482
|
if (err instanceof Error) {
|
|
4285
4483
|
const msg = err.message.toLowerCase();
|
|
@@ -4393,17 +4591,24 @@ async function writeMemory(record) {
|
|
|
4393
4591
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
4394
4592
|
);
|
|
4395
4593
|
}
|
|
4396
|
-
const
|
|
4397
|
-
if (
|
|
4594
|
+
const governed = governMemoryRecord(record);
|
|
4595
|
+
if (governed.shouldDrop) return;
|
|
4596
|
+
record = governed.record;
|
|
4597
|
+
const contentHash = governed.contentHash;
|
|
4598
|
+
const memoryType = record.memory_type ?? "raw";
|
|
4599
|
+
if (_pendingRecords.some(
|
|
4600
|
+
(r) => r.content_hash === contentHash && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
4601
|
+
)) {
|
|
4398
4602
|
return;
|
|
4399
4603
|
}
|
|
4400
4604
|
try {
|
|
4401
|
-
const
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4605
|
+
const existing = await findScopedDuplicate({
|
|
4606
|
+
contentHash,
|
|
4607
|
+
agentId: record.agent_id,
|
|
4608
|
+
projectName: record.project_name,
|
|
4609
|
+
memoryType
|
|
4405
4610
|
});
|
|
4406
|
-
if (existing
|
|
4611
|
+
if (existing) return;
|
|
4407
4612
|
} catch {
|
|
4408
4613
|
}
|
|
4409
4614
|
const dbRow = {
|
|
@@ -4434,7 +4639,7 @@ async function writeMemory(record) {
|
|
|
4434
4639
|
tier: record.tier ?? classifyTier(record),
|
|
4435
4640
|
supersedes_id: record.supersedes_id ?? null,
|
|
4436
4641
|
draft: record.draft ? 1 : 0,
|
|
4437
|
-
memory_type:
|
|
4642
|
+
memory_type: memoryType,
|
|
4438
4643
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
4439
4644
|
content_hash: contentHash,
|
|
4440
4645
|
intent: record.intent ?? null,
|
|
@@ -4593,6 +4798,7 @@ async function flushBatch() {
|
|
|
4593
4798
|
const globalClient = getClient();
|
|
4594
4799
|
const globalStmts = batch.map(buildStmt);
|
|
4595
4800
|
await globalClient.batch(globalStmts, "write");
|
|
4801
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4596
4802
|
_pendingRecords.splice(0, batch.length);
|
|
4597
4803
|
try {
|
|
4598
4804
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -4851,6 +5057,7 @@ var init_store = __esm({
|
|
|
4851
5057
|
init_keychain();
|
|
4852
5058
|
init_config();
|
|
4853
5059
|
init_state_bus();
|
|
5060
|
+
init_memory_write_governor();
|
|
4854
5061
|
INIT_MAX_RETRIES = 3;
|
|
4855
5062
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
4856
5063
|
_pendingRecords = [];
|
|
@@ -9293,7 +9500,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9293
9500
|
}
|
|
9294
9501
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
9295
9502
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
9296
|
-
|
|
9503
|
+
let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
9504
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
9505
|
+
ccModel += "[1m]";
|
|
9506
|
+
}
|
|
9507
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
9297
9508
|
}
|
|
9298
9509
|
}
|
|
9299
9510
|
let spawnCommand;
|