@askexenow/exe-os 0.9.34 → 0.9.36
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 +212 -11
- package/dist/bin/backfill-responses.js +212 -11
- package/dist/bin/backfill-vectors.js +14 -3
- package/dist/bin/cleanup-stale-review-tasks.js +224 -12
- package/dist/bin/cli.js +265 -23
- package/dist/bin/exe-agent.js +1 -1
- package/dist/bin/exe-assign.js +217 -12
- package/dist/bin/exe-boot.js +25 -4
- package/dist/bin/exe-call.js +7 -5
- package/dist/bin/exe-dispatch.js +229 -13
- package/dist/bin/exe-doctor.js +14 -3
- package/dist/bin/exe-export-behaviors.js +301 -14
- package/dist/bin/exe-forget.js +245 -21
- package/dist/bin/exe-gateway.js +229 -13
- package/dist/bin/exe-heartbeat.js +224 -12
- package/dist/bin/exe-kill.js +224 -12
- package/dist/bin/exe-launch-agent.js +177 -9
- package/dist/bin/exe-link.js +8 -0
- package/dist/bin/exe-new-employee.js +26 -2
- package/dist/bin/exe-pending-messages.js +224 -12
- package/dist/bin/exe-pending-notifications.js +224 -12
- package/dist/bin/exe-pending-reviews.js +224 -12
- package/dist/bin/exe-rename.js +9 -1
- package/dist/bin/exe-review.js +224 -12
- package/dist/bin/exe-search.js +246 -21
- package/dist/bin/exe-session-cleanup.js +229 -13
- package/dist/bin/exe-start-codex.js +161 -5
- package/dist/bin/exe-start-opencode.js +172 -5
- package/dist/bin/exe-status.js +224 -12
- package/dist/bin/exe-team.js +224 -12
- package/dist/bin/git-sweep.js +229 -13
- package/dist/bin/graph-backfill.js +94 -3
- package/dist/bin/graph-export.js +224 -12
- package/dist/bin/install.js +25 -1
- package/dist/bin/intercom-check.js +229 -13
- package/dist/bin/scan-tasks.js +229 -13
- package/dist/bin/setup.js +15 -5
- package/dist/bin/shard-migrate.js +94 -3
- package/dist/gateway/index.js +229 -13
- package/dist/hooks/bug-report-worker.js +229 -13
- package/dist/hooks/codex-stop-task-finalizer.js +224 -12
- package/dist/hooks/commit-complete.js +229 -13
- package/dist/hooks/error-recall.js +246 -21
- package/dist/hooks/ingest.js +224 -12
- package/dist/hooks/instructions-loaded.js +224 -12
- package/dist/hooks/notification.js +224 -12
- package/dist/hooks/post-compact.js +224 -12
- package/dist/hooks/post-tool-combined.js +246 -21
- package/dist/hooks/pre-compact.js +229 -13
- package/dist/hooks/pre-tool-use.js +234 -18
- package/dist/hooks/prompt-submit.js +346 -23
- package/dist/hooks/session-end.js +229 -13
- package/dist/hooks/session-start.js +418 -42
- package/dist/hooks/stop.js +224 -12
- package/dist/hooks/subagent-stop.js +224 -12
- package/dist/hooks/summary-worker.js +15 -2
- package/dist/index.js +229 -13
- 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/employee-templates.js +7 -5
- package/dist/lib/exe-daemon.js +1776 -1433
- package/dist/lib/hybrid-search.js +246 -21
- package/dist/lib/schedules.js +14 -3
- package/dist/lib/store.js +217 -12
- package/dist/lib/tasks.js +5 -1
- package/dist/lib/tmux-routing.js +5 -1
- package/dist/mcp/server.js +331 -37
- package/dist/mcp/tools/create-task.js +5 -1
- package/dist/mcp/tools/update-task.js +5 -1
- package/dist/runtime/index.js +229 -13
- package/dist/tui/App.js +229 -13
- package/package.json +1 -1
- package/src/commands/exe/save.md +48 -0
|
@@ -2276,6 +2276,14 @@ async function ensureSchema() {
|
|
|
2276
2276
|
);
|
|
2277
2277
|
} catch {
|
|
2278
2278
|
}
|
|
2279
|
+
try {
|
|
2280
|
+
await client.execute(
|
|
2281
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2282
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2283
|
+
WHERE content_hash IS NOT NULL`
|
|
2284
|
+
);
|
|
2285
|
+
} catch {
|
|
2286
|
+
}
|
|
2279
2287
|
await client.executeMultiple(`
|
|
2280
2288
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2281
2289
|
id TEXT PRIMARY KEY,
|
|
@@ -3021,6 +3029,197 @@ var init_state_bus = __esm({
|
|
|
3021
3029
|
}
|
|
3022
3030
|
});
|
|
3023
3031
|
|
|
3032
|
+
// src/lib/memory-write-governor.ts
|
|
3033
|
+
import { createHash } from "crypto";
|
|
3034
|
+
function normalizeMemoryText(text) {
|
|
3035
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
3036
|
+
}
|
|
3037
|
+
function classifyMemoryType(input) {
|
|
3038
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
3039
|
+
const tool = input.tool_name.toLowerCase();
|
|
3040
|
+
const text = input.raw_text.toLowerCase();
|
|
3041
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
3042
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
3043
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
3044
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
3045
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
3046
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
3047
|
+
return "raw";
|
|
3048
|
+
}
|
|
3049
|
+
function shouldDropMemory(text) {
|
|
3050
|
+
const normalized = normalizeMemoryText(text);
|
|
3051
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
3052
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
3053
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
3054
|
+
}
|
|
3055
|
+
return { drop: false };
|
|
3056
|
+
}
|
|
3057
|
+
function shouldSkipEmbedding(input) {
|
|
3058
|
+
const type = classifyMemoryType(input);
|
|
3059
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
3060
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
3061
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
3062
|
+
return false;
|
|
3063
|
+
}
|
|
3064
|
+
function hashMemoryContent(text) {
|
|
3065
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
3066
|
+
}
|
|
3067
|
+
function scopedDedupArgs(input) {
|
|
3068
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
3069
|
+
}
|
|
3070
|
+
function governMemoryRecord(record) {
|
|
3071
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
3072
|
+
const memoryType = classifyMemoryType({
|
|
3073
|
+
raw_text: normalized,
|
|
3074
|
+
agent_id: record.agent_id,
|
|
3075
|
+
project_name: record.project_name,
|
|
3076
|
+
tool_name: record.tool_name,
|
|
3077
|
+
memory_type: record.memory_type
|
|
3078
|
+
});
|
|
3079
|
+
const drop = shouldDropMemory(normalized);
|
|
3080
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
3081
|
+
raw_text: normalized,
|
|
3082
|
+
agent_id: record.agent_id,
|
|
3083
|
+
project_name: record.project_name,
|
|
3084
|
+
tool_name: record.tool_name,
|
|
3085
|
+
memory_type: memoryType
|
|
3086
|
+
});
|
|
3087
|
+
return {
|
|
3088
|
+
record: {
|
|
3089
|
+
...record,
|
|
3090
|
+
raw_text: normalized,
|
|
3091
|
+
memory_type: memoryType,
|
|
3092
|
+
vector: skipEmbedding ? null : record.vector
|
|
3093
|
+
},
|
|
3094
|
+
contentHash: hashMemoryContent(normalized),
|
|
3095
|
+
shouldDrop: drop.drop,
|
|
3096
|
+
dropReason: drop.reason,
|
|
3097
|
+
skipEmbedding,
|
|
3098
|
+
hygiene: {
|
|
3099
|
+
dedup: true,
|
|
3100
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
3101
|
+
}
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
async function findScopedDuplicate(input) {
|
|
3105
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3106
|
+
const client = getClient2();
|
|
3107
|
+
const args = scopedDedupArgs(input);
|
|
3108
|
+
let sql = `SELECT id FROM memories
|
|
3109
|
+
WHERE content_hash = ?
|
|
3110
|
+
AND agent_id = ?
|
|
3111
|
+
AND project_name = ?
|
|
3112
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3113
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
3114
|
+
if (input.excludeId) {
|
|
3115
|
+
sql += " AND id != ?";
|
|
3116
|
+
args.push(input.excludeId);
|
|
3117
|
+
}
|
|
3118
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
3119
|
+
const result = await client.execute({ sql, args });
|
|
3120
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
3121
|
+
}
|
|
3122
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3123
|
+
try {
|
|
3124
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3125
|
+
const client = getClient2();
|
|
3126
|
+
const current = await client.execute({
|
|
3127
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
3128
|
+
importance, timestamp
|
|
3129
|
+
FROM memories
|
|
3130
|
+
WHERE id = ?
|
|
3131
|
+
LIMIT 1`,
|
|
3132
|
+
args: [memoryId]
|
|
3133
|
+
});
|
|
3134
|
+
const row = current.rows[0];
|
|
3135
|
+
if (!row) return;
|
|
3136
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
3137
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
3138
|
+
const agentId = String(row.agent_id);
|
|
3139
|
+
const projectName = String(row.project_name);
|
|
3140
|
+
if (contentHash) {
|
|
3141
|
+
await client.execute({
|
|
3142
|
+
sql: `UPDATE memories
|
|
3143
|
+
SET status = 'deleted',
|
|
3144
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3145
|
+
WHERE id != ?
|
|
3146
|
+
AND content_hash = ?
|
|
3147
|
+
AND agent_id = ?
|
|
3148
|
+
AND project_name = ?
|
|
3149
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3150
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
3151
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
3152
|
+
});
|
|
3153
|
+
}
|
|
3154
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
3155
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
3156
|
+
const old = await client.execute({
|
|
3157
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
3158
|
+
args: [supersedesId]
|
|
3159
|
+
});
|
|
3160
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
3161
|
+
const newImportance = Number(row.importance ?? 0);
|
|
3162
|
+
await client.batch([
|
|
3163
|
+
{
|
|
3164
|
+
sql: `UPDATE memories
|
|
3165
|
+
SET status = 'archived',
|
|
3166
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3167
|
+
WHERE id = ?`,
|
|
3168
|
+
args: [supersedesId]
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
sql: `UPDATE memories
|
|
3172
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
3173
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
3174
|
+
WHERE id = ?`,
|
|
3175
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
3176
|
+
}
|
|
3177
|
+
], "write");
|
|
3178
|
+
}
|
|
3179
|
+
} catch (err) {
|
|
3180
|
+
process.stderr.write(
|
|
3181
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
3182
|
+
`
|
|
3183
|
+
);
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
3187
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
3188
|
+
if (memoryIds.length === 0) return;
|
|
3189
|
+
const run = () => {
|
|
3190
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
3191
|
+
};
|
|
3192
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
3193
|
+
else setTimeout(run, 0);
|
|
3194
|
+
}
|
|
3195
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
3196
|
+
var init_memory_write_governor = __esm({
|
|
3197
|
+
"src/lib/memory-write-governor.ts"() {
|
|
3198
|
+
"use strict";
|
|
3199
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
3200
|
+
"decision",
|
|
3201
|
+
"adr",
|
|
3202
|
+
"behavior",
|
|
3203
|
+
"procedure"
|
|
3204
|
+
]);
|
|
3205
|
+
NOISE_DROP_PATTERNS = [
|
|
3206
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
3207
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
3208
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
3209
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
3210
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
3211
|
+
];
|
|
3212
|
+
SKIP_EMBED_PATTERNS = [
|
|
3213
|
+
/tmux capture-pane\b/i,
|
|
3214
|
+
/docker ps\b/i,
|
|
3215
|
+
/docker images\b/i,
|
|
3216
|
+
/git status\b/i,
|
|
3217
|
+
/grep .*node_modules/i,
|
|
3218
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
3219
|
+
];
|
|
3220
|
+
}
|
|
3221
|
+
});
|
|
3222
|
+
|
|
3024
3223
|
// src/lib/shard-manager.ts
|
|
3025
3224
|
var shard_manager_exports = {};
|
|
3026
3225
|
__export(shard_manager_exports, {
|
|
@@ -3185,7 +3384,8 @@ async function ensureShardSchema(client) {
|
|
|
3185
3384
|
}
|
|
3186
3385
|
for (const idx of [
|
|
3187
3386
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
3188
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
3387
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
3388
|
+
"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"
|
|
3189
3389
|
]) {
|
|
3190
3390
|
try {
|
|
3191
3391
|
await client.execute(idx);
|
|
@@ -3379,7 +3579,7 @@ var init_platform_procedures = __esm({
|
|
|
3379
3579
|
title: "Chain of command \u2014 who talks to whom",
|
|
3380
3580
|
domain: "workflow",
|
|
3381
3581
|
priority: "p0",
|
|
3382
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
3582
|
+
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
3383
3583
|
},
|
|
3384
3584
|
{
|
|
3385
3585
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -3610,7 +3810,6 @@ __export(store_exports, {
|
|
|
3610
3810
|
vectorToBlob: () => vectorToBlob,
|
|
3611
3811
|
writeMemory: () => writeMemory
|
|
3612
3812
|
});
|
|
3613
|
-
import { createHash } from "crypto";
|
|
3614
3813
|
function isBusyError2(err) {
|
|
3615
3814
|
if (err instanceof Error) {
|
|
3616
3815
|
const msg = err.message.toLowerCase();
|
|
@@ -3724,17 +3923,24 @@ async function writeMemory(record) {
|
|
|
3724
3923
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
3725
3924
|
);
|
|
3726
3925
|
}
|
|
3727
|
-
const
|
|
3728
|
-
if (
|
|
3926
|
+
const governed = governMemoryRecord(record);
|
|
3927
|
+
if (governed.shouldDrop) return;
|
|
3928
|
+
record = governed.record;
|
|
3929
|
+
const contentHash = governed.contentHash;
|
|
3930
|
+
const memoryType = record.memory_type ?? "raw";
|
|
3931
|
+
if (_pendingRecords.some(
|
|
3932
|
+
(r) => r.content_hash === contentHash && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
3933
|
+
)) {
|
|
3729
3934
|
return;
|
|
3730
3935
|
}
|
|
3731
3936
|
try {
|
|
3732
|
-
const
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3937
|
+
const existing = await findScopedDuplicate({
|
|
3938
|
+
contentHash,
|
|
3939
|
+
agentId: record.agent_id,
|
|
3940
|
+
projectName: record.project_name,
|
|
3941
|
+
memoryType
|
|
3736
3942
|
});
|
|
3737
|
-
if (existing
|
|
3943
|
+
if (existing) return;
|
|
3738
3944
|
} catch {
|
|
3739
3945
|
}
|
|
3740
3946
|
const dbRow = {
|
|
@@ -3765,7 +3971,7 @@ async function writeMemory(record) {
|
|
|
3765
3971
|
tier: record.tier ?? classifyTier(record),
|
|
3766
3972
|
supersedes_id: record.supersedes_id ?? null,
|
|
3767
3973
|
draft: record.draft ? 1 : 0,
|
|
3768
|
-
memory_type:
|
|
3974
|
+
memory_type: memoryType,
|
|
3769
3975
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
3770
3976
|
content_hash: contentHash,
|
|
3771
3977
|
intent: record.intent ?? null,
|
|
@@ -3924,6 +4130,7 @@ async function flushBatch() {
|
|
|
3924
4130
|
const globalClient = getClient();
|
|
3925
4131
|
const globalStmts = batch.map(buildStmt);
|
|
3926
4132
|
await globalClient.batch(globalStmts, "write");
|
|
4133
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
3927
4134
|
_pendingRecords.splice(0, batch.length);
|
|
3928
4135
|
try {
|
|
3929
4136
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -4044,7 +4251,11 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
4044
4251
|
sql += ` AND timestamp >= ?`;
|
|
4045
4252
|
args.push(options.since);
|
|
4046
4253
|
}
|
|
4047
|
-
if (options?.
|
|
4254
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
4255
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
4256
|
+
sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
4257
|
+
args.push(...uniqueTypes);
|
|
4258
|
+
} else if (options?.memoryType) {
|
|
4048
4259
|
sql += ` AND memory_type = ?`;
|
|
4049
4260
|
args.push(options.memoryType);
|
|
4050
4261
|
}
|
|
@@ -4182,6 +4393,7 @@ var init_store = __esm({
|
|
|
4182
4393
|
init_keychain();
|
|
4183
4394
|
init_config();
|
|
4184
4395
|
init_state_bus();
|
|
4396
|
+
init_memory_write_governor();
|
|
4185
4397
|
INIT_MAX_RETRIES = 3;
|
|
4186
4398
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
4187
4399
|
_pendingRecords = [];
|
|
@@ -5335,6 +5547,17 @@ var init_entity_boost = __esm({
|
|
|
5335
5547
|
init_store();
|
|
5336
5548
|
init_database();
|
|
5337
5549
|
var RRF_K = 60;
|
|
5550
|
+
function appendMemoryTypeFilter(sql, args, column, options) {
|
|
5551
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
5552
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
5553
|
+
sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
5554
|
+
args.push(...uniqueTypes);
|
|
5555
|
+
} else if (options?.memoryType) {
|
|
5556
|
+
sql += ` AND ${column} = ?`;
|
|
5557
|
+
args.push(options.memoryType);
|
|
5558
|
+
}
|
|
5559
|
+
return sql;
|
|
5560
|
+
}
|
|
5338
5561
|
async function hybridSearch(queryText, agentId, options) {
|
|
5339
5562
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
5340
5563
|
const config = await loadConfig2();
|
|
@@ -5563,6 +5786,7 @@ async function estimateCardinality(agentId, options) {
|
|
|
5563
5786
|
sql += ` AND timestamp >= ?`;
|
|
5564
5787
|
args.push(options.since);
|
|
5565
5788
|
}
|
|
5789
|
+
sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
|
|
5566
5790
|
try {
|
|
5567
5791
|
const result = await client.execute({ sql, args });
|
|
5568
5792
|
return Number(result.rows[0]?.cnt) || 0;
|
|
@@ -5684,10 +5908,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
|
|
|
5684
5908
|
sql += ` AND m.timestamp >= ?`;
|
|
5685
5909
|
args.push(options.since);
|
|
5686
5910
|
}
|
|
5687
|
-
|
|
5688
|
-
sql += ` AND m.memory_type = ?`;
|
|
5689
|
-
args.push(options.memoryType);
|
|
5690
|
-
}
|
|
5911
|
+
sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
|
|
5691
5912
|
sql += ` ORDER BY rank LIMIT ?`;
|
|
5692
5913
|
args.push(limit);
|
|
5693
5914
|
const result = await client.execute({ sql, args });
|
|
@@ -5744,9 +5965,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
5744
5965
|
AND timestamp >= ? AND timestamp <= ?
|
|
5745
5966
|
AND COALESCE(status, 'active') = 'active'
|
|
5746
5967
|
AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
|
|
5968
|
+
${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
|
|
5747
5969
|
AND COALESCE(confidence, 0.7) >= 0.3
|
|
5748
5970
|
ORDER BY timestamp DESC LIMIT ?`,
|
|
5749
|
-
args: [
|
|
5971
|
+
args: [
|
|
5972
|
+
agentId,
|
|
5973
|
+
windowStart,
|
|
5974
|
+
killedAt,
|
|
5975
|
+
...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
|
|
5976
|
+
boundarySlots
|
|
5977
|
+
]
|
|
5750
5978
|
});
|
|
5751
5979
|
for (const row of boundaryResult.rows) {
|
|
5752
5980
|
sessionBoundaryMemories.push(rowToMemoryRecord(row));
|
|
@@ -5792,10 +6020,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
5792
6020
|
sql += ` AND timestamp >= ?`;
|
|
5793
6021
|
args.push(options.since);
|
|
5794
6022
|
}
|
|
5795
|
-
|
|
5796
|
-
sql += ` AND memory_type = ?`;
|
|
5797
|
-
args.push(options.memoryType);
|
|
5798
|
-
}
|
|
6023
|
+
sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
|
|
5799
6024
|
if (textFilter) {
|
|
5800
6025
|
sql += ` AND raw_text LIKE '%' || ? || '%'`;
|
|
5801
6026
|
args.push(textFilter);
|
package/dist/lib/schedules.js
CHANGED
|
@@ -2072,6 +2072,14 @@ async function ensureSchema() {
|
|
|
2072
2072
|
);
|
|
2073
2073
|
} catch {
|
|
2074
2074
|
}
|
|
2075
|
+
try {
|
|
2076
|
+
await client.execute(
|
|
2077
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2078
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2079
|
+
WHERE content_hash IS NOT NULL`
|
|
2080
|
+
);
|
|
2081
|
+
} catch {
|
|
2082
|
+
}
|
|
2075
2083
|
await client.executeMultiple(`
|
|
2076
2084
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2077
2085
|
id TEXT PRIMARY KEY,
|
|
@@ -2741,7 +2749,8 @@ async function ensureShardSchema(client) {
|
|
|
2741
2749
|
}
|
|
2742
2750
|
for (const idx of [
|
|
2743
2751
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
2744
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
2752
|
+
"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_scoped_content_hash ON memories(content_hash, agent_id, project_name, memory_type) WHERE content_hash IS NOT NULL"
|
|
2745
2754
|
]) {
|
|
2746
2755
|
try {
|
|
2747
2756
|
await client.execute(idx);
|
|
@@ -2935,7 +2944,7 @@ var init_platform_procedures = __esm({
|
|
|
2935
2944
|
title: "Chain of command \u2014 who talks to whom",
|
|
2936
2945
|
domain: "workflow",
|
|
2937
2946
|
priority: "p0",
|
|
2938
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
2947
|
+
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
2939
2948
|
},
|
|
2940
2949
|
{
|
|
2941
2950
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -3156,7 +3165,6 @@ import { execSync as execSync3 } from "child_process";
|
|
|
3156
3165
|
// src/lib/store.ts
|
|
3157
3166
|
init_memory();
|
|
3158
3167
|
init_database();
|
|
3159
|
-
import { createHash } from "crypto";
|
|
3160
3168
|
|
|
3161
3169
|
// src/lib/keychain.ts
|
|
3162
3170
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
@@ -3389,6 +3397,9 @@ var StateBus = class {
|
|
|
3389
3397
|
};
|
|
3390
3398
|
var orgBus = new StateBus();
|
|
3391
3399
|
|
|
3400
|
+
// src/lib/memory-write-governor.ts
|
|
3401
|
+
import { createHash } from "crypto";
|
|
3402
|
+
|
|
3392
3403
|
// src/lib/store.ts
|
|
3393
3404
|
var INIT_MAX_RETRIES = 3;
|
|
3394
3405
|
var INIT_RETRY_DELAY_MS = 1e3;
|