@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
|
@@ -2621,6 +2621,14 @@ async function ensureSchema() {
|
|
|
2621
2621
|
);
|
|
2622
2622
|
} catch {
|
|
2623
2623
|
}
|
|
2624
|
+
try {
|
|
2625
|
+
await client.execute(
|
|
2626
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2627
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2628
|
+
WHERE content_hash IS NOT NULL`
|
|
2629
|
+
);
|
|
2630
|
+
} catch {
|
|
2631
|
+
}
|
|
2624
2632
|
await client.executeMultiple(`
|
|
2625
2633
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2626
2634
|
id TEXT PRIMARY KEY,
|
|
@@ -3366,6 +3374,197 @@ var init_state_bus = __esm({
|
|
|
3366
3374
|
}
|
|
3367
3375
|
});
|
|
3368
3376
|
|
|
3377
|
+
// src/lib/memory-write-governor.ts
|
|
3378
|
+
import { createHash } from "crypto";
|
|
3379
|
+
function normalizeMemoryText(text) {
|
|
3380
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
3381
|
+
}
|
|
3382
|
+
function classifyMemoryType(input2) {
|
|
3383
|
+
if (input2.memory_type && input2.memory_type.trim()) return input2.memory_type.trim();
|
|
3384
|
+
const tool = input2.tool_name.toLowerCase();
|
|
3385
|
+
const text = input2.raw_text.toLowerCase();
|
|
3386
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
3387
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
3388
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
3389
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
3390
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
3391
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
3392
|
+
return "raw";
|
|
3393
|
+
}
|
|
3394
|
+
function shouldDropMemory(text) {
|
|
3395
|
+
const normalized = normalizeMemoryText(text);
|
|
3396
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
3397
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
3398
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
3399
|
+
}
|
|
3400
|
+
return { drop: false };
|
|
3401
|
+
}
|
|
3402
|
+
function shouldSkipEmbedding(input2) {
|
|
3403
|
+
const type = classifyMemoryType(input2);
|
|
3404
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
3405
|
+
if (type === "raw" && input2.raw_text.length > 2e4) return true;
|
|
3406
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input2.raw_text))) return true;
|
|
3407
|
+
return false;
|
|
3408
|
+
}
|
|
3409
|
+
function hashMemoryContent(text) {
|
|
3410
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
3411
|
+
}
|
|
3412
|
+
function scopedDedupArgs(input2) {
|
|
3413
|
+
return [input2.contentHash, input2.agentId, input2.projectName, input2.memoryType];
|
|
3414
|
+
}
|
|
3415
|
+
function governMemoryRecord(record) {
|
|
3416
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
3417
|
+
const memoryType = classifyMemoryType({
|
|
3418
|
+
raw_text: normalized,
|
|
3419
|
+
agent_id: record.agent_id,
|
|
3420
|
+
project_name: record.project_name,
|
|
3421
|
+
tool_name: record.tool_name,
|
|
3422
|
+
memory_type: record.memory_type
|
|
3423
|
+
});
|
|
3424
|
+
const drop = shouldDropMemory(normalized);
|
|
3425
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
3426
|
+
raw_text: normalized,
|
|
3427
|
+
agent_id: record.agent_id,
|
|
3428
|
+
project_name: record.project_name,
|
|
3429
|
+
tool_name: record.tool_name,
|
|
3430
|
+
memory_type: memoryType
|
|
3431
|
+
});
|
|
3432
|
+
return {
|
|
3433
|
+
record: {
|
|
3434
|
+
...record,
|
|
3435
|
+
raw_text: normalized,
|
|
3436
|
+
memory_type: memoryType,
|
|
3437
|
+
vector: skipEmbedding ? null : record.vector
|
|
3438
|
+
},
|
|
3439
|
+
contentHash: hashMemoryContent(normalized),
|
|
3440
|
+
shouldDrop: drop.drop,
|
|
3441
|
+
dropReason: drop.reason,
|
|
3442
|
+
skipEmbedding,
|
|
3443
|
+
hygiene: {
|
|
3444
|
+
dedup: true,
|
|
3445
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
3446
|
+
}
|
|
3447
|
+
};
|
|
3448
|
+
}
|
|
3449
|
+
async function findScopedDuplicate(input2) {
|
|
3450
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3451
|
+
const client = getClient2();
|
|
3452
|
+
const args = scopedDedupArgs(input2);
|
|
3453
|
+
let sql = `SELECT id FROM memories
|
|
3454
|
+
WHERE content_hash = ?
|
|
3455
|
+
AND agent_id = ?
|
|
3456
|
+
AND project_name = ?
|
|
3457
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3458
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
3459
|
+
if (input2.excludeId) {
|
|
3460
|
+
sql += " AND id != ?";
|
|
3461
|
+
args.push(input2.excludeId);
|
|
3462
|
+
}
|
|
3463
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
3464
|
+
const result = await client.execute({ sql, args });
|
|
3465
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
3466
|
+
}
|
|
3467
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3468
|
+
try {
|
|
3469
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3470
|
+
const client = getClient2();
|
|
3471
|
+
const current = await client.execute({
|
|
3472
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
3473
|
+
importance, timestamp
|
|
3474
|
+
FROM memories
|
|
3475
|
+
WHERE id = ?
|
|
3476
|
+
LIMIT 1`,
|
|
3477
|
+
args: [memoryId]
|
|
3478
|
+
});
|
|
3479
|
+
const row = current.rows[0];
|
|
3480
|
+
if (!row) return;
|
|
3481
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
3482
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
3483
|
+
const agentId = String(row.agent_id);
|
|
3484
|
+
const projectName = String(row.project_name);
|
|
3485
|
+
if (contentHash) {
|
|
3486
|
+
await client.execute({
|
|
3487
|
+
sql: `UPDATE memories
|
|
3488
|
+
SET status = 'deleted',
|
|
3489
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3490
|
+
WHERE id != ?
|
|
3491
|
+
AND content_hash = ?
|
|
3492
|
+
AND agent_id = ?
|
|
3493
|
+
AND project_name = ?
|
|
3494
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3495
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
3496
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
3497
|
+
});
|
|
3498
|
+
}
|
|
3499
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
3500
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
3501
|
+
const old = await client.execute({
|
|
3502
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
3503
|
+
args: [supersedesId]
|
|
3504
|
+
});
|
|
3505
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
3506
|
+
const newImportance = Number(row.importance ?? 0);
|
|
3507
|
+
await client.batch([
|
|
3508
|
+
{
|
|
3509
|
+
sql: `UPDATE memories
|
|
3510
|
+
SET status = 'archived',
|
|
3511
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3512
|
+
WHERE id = ?`,
|
|
3513
|
+
args: [supersedesId]
|
|
3514
|
+
},
|
|
3515
|
+
{
|
|
3516
|
+
sql: `UPDATE memories
|
|
3517
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
3518
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
3519
|
+
WHERE id = ?`,
|
|
3520
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
3521
|
+
}
|
|
3522
|
+
], "write");
|
|
3523
|
+
}
|
|
3524
|
+
} catch (err) {
|
|
3525
|
+
process.stderr.write(
|
|
3526
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
3527
|
+
`
|
|
3528
|
+
);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
3532
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
3533
|
+
if (memoryIds.length === 0) return;
|
|
3534
|
+
const run = () => {
|
|
3535
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
3536
|
+
};
|
|
3537
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
3538
|
+
else setTimeout(run, 0);
|
|
3539
|
+
}
|
|
3540
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
3541
|
+
var init_memory_write_governor = __esm({
|
|
3542
|
+
"src/lib/memory-write-governor.ts"() {
|
|
3543
|
+
"use strict";
|
|
3544
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
3545
|
+
"decision",
|
|
3546
|
+
"adr",
|
|
3547
|
+
"behavior",
|
|
3548
|
+
"procedure"
|
|
3549
|
+
]);
|
|
3550
|
+
NOISE_DROP_PATTERNS = [
|
|
3551
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
3552
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
3553
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
3554
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
3555
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
3556
|
+
];
|
|
3557
|
+
SKIP_EMBED_PATTERNS = [
|
|
3558
|
+
/tmux capture-pane\b/i,
|
|
3559
|
+
/docker ps\b/i,
|
|
3560
|
+
/docker images\b/i,
|
|
3561
|
+
/git status\b/i,
|
|
3562
|
+
/grep .*node_modules/i,
|
|
3563
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
3564
|
+
];
|
|
3565
|
+
}
|
|
3566
|
+
});
|
|
3567
|
+
|
|
3369
3568
|
// src/lib/shard-manager.ts
|
|
3370
3569
|
var shard_manager_exports = {};
|
|
3371
3570
|
__export(shard_manager_exports, {
|
|
@@ -3530,7 +3729,8 @@ async function ensureShardSchema(client) {
|
|
|
3530
3729
|
}
|
|
3531
3730
|
for (const idx of [
|
|
3532
3731
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
3533
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
3732
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
3733
|
+
"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"
|
|
3534
3734
|
]) {
|
|
3535
3735
|
try {
|
|
3536
3736
|
await client.execute(idx);
|
|
@@ -3724,7 +3924,7 @@ var init_platform_procedures = __esm({
|
|
|
3724
3924
|
title: "Chain of command \u2014 who talks to whom",
|
|
3725
3925
|
domain: "workflow",
|
|
3726
3926
|
priority: "p0",
|
|
3727
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
3927
|
+
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."
|
|
3728
3928
|
},
|
|
3729
3929
|
{
|
|
3730
3930
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -3955,7 +4155,6 @@ __export(store_exports, {
|
|
|
3955
4155
|
vectorToBlob: () => vectorToBlob,
|
|
3956
4156
|
writeMemory: () => writeMemory
|
|
3957
4157
|
});
|
|
3958
|
-
import { createHash } from "crypto";
|
|
3959
4158
|
function isBusyError2(err) {
|
|
3960
4159
|
if (err instanceof Error) {
|
|
3961
4160
|
const msg = err.message.toLowerCase();
|
|
@@ -4069,17 +4268,24 @@ async function writeMemory(record) {
|
|
|
4069
4268
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
4070
4269
|
);
|
|
4071
4270
|
}
|
|
4072
|
-
const
|
|
4073
|
-
if (
|
|
4271
|
+
const governed = governMemoryRecord(record);
|
|
4272
|
+
if (governed.shouldDrop) return;
|
|
4273
|
+
record = governed.record;
|
|
4274
|
+
const contentHash = governed.contentHash;
|
|
4275
|
+
const memoryType = record.memory_type ?? "raw";
|
|
4276
|
+
if (_pendingRecords.some(
|
|
4277
|
+
(r) => r.content_hash === contentHash && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
4278
|
+
)) {
|
|
4074
4279
|
return;
|
|
4075
4280
|
}
|
|
4076
4281
|
try {
|
|
4077
|
-
const
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4282
|
+
const existing = await findScopedDuplicate({
|
|
4283
|
+
contentHash,
|
|
4284
|
+
agentId: record.agent_id,
|
|
4285
|
+
projectName: record.project_name,
|
|
4286
|
+
memoryType
|
|
4081
4287
|
});
|
|
4082
|
-
if (existing
|
|
4288
|
+
if (existing) return;
|
|
4083
4289
|
} catch {
|
|
4084
4290
|
}
|
|
4085
4291
|
const dbRow = {
|
|
@@ -4110,7 +4316,7 @@ async function writeMemory(record) {
|
|
|
4110
4316
|
tier: record.tier ?? classifyTier(record),
|
|
4111
4317
|
supersedes_id: record.supersedes_id ?? null,
|
|
4112
4318
|
draft: record.draft ? 1 : 0,
|
|
4113
|
-
memory_type:
|
|
4319
|
+
memory_type: memoryType,
|
|
4114
4320
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
4115
4321
|
content_hash: contentHash,
|
|
4116
4322
|
intent: record.intent ?? null,
|
|
@@ -4269,6 +4475,7 @@ async function flushBatch() {
|
|
|
4269
4475
|
const globalClient = getClient();
|
|
4270
4476
|
const globalStmts = batch.map(buildStmt);
|
|
4271
4477
|
await globalClient.batch(globalStmts, "write");
|
|
4478
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4272
4479
|
_pendingRecords.splice(0, batch.length);
|
|
4273
4480
|
try {
|
|
4274
4481
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -4389,7 +4596,11 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
4389
4596
|
sql += ` AND timestamp >= ?`;
|
|
4390
4597
|
args.push(options.since);
|
|
4391
4598
|
}
|
|
4392
|
-
if (options?.
|
|
4599
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
4600
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
4601
|
+
sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
4602
|
+
args.push(...uniqueTypes);
|
|
4603
|
+
} else if (options?.memoryType) {
|
|
4393
4604
|
sql += ` AND memory_type = ?`;
|
|
4394
4605
|
args.push(options.memoryType);
|
|
4395
4606
|
}
|
|
@@ -4527,6 +4738,7 @@ var init_store = __esm({
|
|
|
4527
4738
|
init_keychain();
|
|
4528
4739
|
init_config();
|
|
4529
4740
|
init_state_bus();
|
|
4741
|
+
init_memory_write_governor();
|
|
4530
4742
|
INIT_MAX_RETRIES = 3;
|
|
4531
4743
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
4532
4744
|
_pendingRecords = [];
|
|
@@ -7516,6 +7728,13 @@ var init_tasks_notify = __esm({
|
|
|
7516
7728
|
});
|
|
7517
7729
|
|
|
7518
7730
|
// src/lib/behaviors.ts
|
|
7731
|
+
var behaviors_exports = {};
|
|
7732
|
+
__export(behaviors_exports, {
|
|
7733
|
+
deactivateBehavior: () => deactivateBehavior,
|
|
7734
|
+
listBehaviors: () => listBehaviors,
|
|
7735
|
+
listBehaviorsByDomain: () => listBehaviorsByDomain,
|
|
7736
|
+
storeBehavior: () => storeBehavior
|
|
7737
|
+
});
|
|
7519
7738
|
import crypto6 from "crypto";
|
|
7520
7739
|
async function storeBehavior(opts) {
|
|
7521
7740
|
const client = getClient();
|
|
@@ -7535,6 +7754,63 @@ async function storeBehavior(opts) {
|
|
|
7535
7754
|
});
|
|
7536
7755
|
return id;
|
|
7537
7756
|
}
|
|
7757
|
+
async function listBehaviors(agentId, projectName, limit = 30) {
|
|
7758
|
+
const client = getClient();
|
|
7759
|
+
const result = await client.execute({
|
|
7760
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
|
|
7761
|
+
FROM behaviors
|
|
7762
|
+
WHERE agent_id = ? AND active = 1
|
|
7763
|
+
AND (project_name IS NULL OR project_name = ?)
|
|
7764
|
+
ORDER BY
|
|
7765
|
+
CASE WHEN priority = 'p0' THEN 0
|
|
7766
|
+
WHEN priority = 'p1' THEN 1
|
|
7767
|
+
ELSE 2 END,
|
|
7768
|
+
updated_at DESC
|
|
7769
|
+
LIMIT ?`,
|
|
7770
|
+
args: [agentId, projectName ?? "", limit]
|
|
7771
|
+
});
|
|
7772
|
+
return result.rows.map((r) => ({
|
|
7773
|
+
id: String(r.id),
|
|
7774
|
+
agent_id: String(r.agent_id),
|
|
7775
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
7776
|
+
domain: r.domain ? String(r.domain) : null,
|
|
7777
|
+
priority: String(r.priority || "p1"),
|
|
7778
|
+
content: String(r.content),
|
|
7779
|
+
active: Number(r.active),
|
|
7780
|
+
created_at: String(r.created_at),
|
|
7781
|
+
updated_at: String(r.updated_at),
|
|
7782
|
+
vector: r.vector ? Array.from(new Float32Array(r.vector)) : null
|
|
7783
|
+
}));
|
|
7784
|
+
}
|
|
7785
|
+
async function listBehaviorsByDomain(agentId, domain) {
|
|
7786
|
+
const client = getClient();
|
|
7787
|
+
const result = await client.execute({
|
|
7788
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
|
|
7789
|
+
FROM behaviors
|
|
7790
|
+
WHERE agent_id = ? AND domain = ? AND active = 1`,
|
|
7791
|
+
args: [agentId, domain]
|
|
7792
|
+
});
|
|
7793
|
+
return result.rows.map((r) => ({
|
|
7794
|
+
id: String(r.id),
|
|
7795
|
+
agent_id: String(r.agent_id),
|
|
7796
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
7797
|
+
domain: r.domain ? String(r.domain) : null,
|
|
7798
|
+
priority: String(r.priority || "p1"),
|
|
7799
|
+
content: String(r.content),
|
|
7800
|
+
active: Number(r.active),
|
|
7801
|
+
created_at: String(r.created_at),
|
|
7802
|
+
updated_at: String(r.updated_at),
|
|
7803
|
+
vector: r.vector ? Array.from(new Float32Array(r.vector)) : null
|
|
7804
|
+
}));
|
|
7805
|
+
}
|
|
7806
|
+
async function deactivateBehavior(id) {
|
|
7807
|
+
const client = getClient();
|
|
7808
|
+
const result = await client.execute({
|
|
7809
|
+
sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
|
|
7810
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), id]
|
|
7811
|
+
});
|
|
7812
|
+
return (result.rowsAffected ?? 0) > 0;
|
|
7813
|
+
}
|
|
7538
7814
|
var init_behaviors = __esm({
|
|
7539
7815
|
"src/lib/behaviors.ts"() {
|
|
7540
7816
|
"use strict";
|
|
@@ -9001,7 +9277,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9001
9277
|
}
|
|
9002
9278
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
9003
9279
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
9004
|
-
|
|
9280
|
+
let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
9281
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
9282
|
+
ccModel += "[1m]";
|
|
9283
|
+
}
|
|
9284
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
9005
9285
|
}
|
|
9006
9286
|
}
|
|
9007
9287
|
let spawnCommand;
|
|
@@ -9486,6 +9766,17 @@ import path25 from "path";
|
|
|
9486
9766
|
init_store();
|
|
9487
9767
|
init_database();
|
|
9488
9768
|
var RRF_K = 60;
|
|
9769
|
+
function appendMemoryTypeFilter(sql, args, column, options) {
|
|
9770
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
9771
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
9772
|
+
sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
9773
|
+
args.push(...uniqueTypes);
|
|
9774
|
+
} else if (options?.memoryType) {
|
|
9775
|
+
sql += ` AND ${column} = ?`;
|
|
9776
|
+
args.push(options.memoryType);
|
|
9777
|
+
}
|
|
9778
|
+
return sql;
|
|
9779
|
+
}
|
|
9489
9780
|
async function hybridSearch(queryText, agentId, options) {
|
|
9490
9781
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
9491
9782
|
const config = await loadConfig2();
|
|
@@ -9714,6 +10005,7 @@ async function estimateCardinality(agentId, options) {
|
|
|
9714
10005
|
sql += ` AND timestamp >= ?`;
|
|
9715
10006
|
args.push(options.since);
|
|
9716
10007
|
}
|
|
10008
|
+
sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
|
|
9717
10009
|
try {
|
|
9718
10010
|
const result = await client.execute({ sql, args });
|
|
9719
10011
|
return Number(result.rows[0]?.cnt) || 0;
|
|
@@ -9832,10 +10124,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
|
|
|
9832
10124
|
sql += ` AND m.timestamp >= ?`;
|
|
9833
10125
|
args.push(options.since);
|
|
9834
10126
|
}
|
|
9835
|
-
|
|
9836
|
-
sql += ` AND m.memory_type = ?`;
|
|
9837
|
-
args.push(options.memoryType);
|
|
9838
|
-
}
|
|
10127
|
+
sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
|
|
9839
10128
|
sql += ` ORDER BY rank LIMIT ?`;
|
|
9840
10129
|
args.push(limit);
|
|
9841
10130
|
const result = await client.execute({ sql, args });
|
|
@@ -9892,9 +10181,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
9892
10181
|
AND timestamp >= ? AND timestamp <= ?
|
|
9893
10182
|
AND COALESCE(status, 'active') = 'active'
|
|
9894
10183
|
AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
|
|
10184
|
+
${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
|
|
9895
10185
|
AND COALESCE(confidence, 0.7) >= 0.3
|
|
9896
10186
|
ORDER BY timestamp DESC LIMIT ?`,
|
|
9897
|
-
args: [
|
|
10187
|
+
args: [
|
|
10188
|
+
agentId,
|
|
10189
|
+
windowStart,
|
|
10190
|
+
killedAt,
|
|
10191
|
+
...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
|
|
10192
|
+
boundarySlots
|
|
10193
|
+
]
|
|
9898
10194
|
});
|
|
9899
10195
|
for (const row of boundaryResult.rows) {
|
|
9900
10196
|
sessionBoundaryMemories.push(rowToMemoryRecord(row));
|
|
@@ -9940,10 +10236,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
9940
10236
|
sql += ` AND timestamp >= ?`;
|
|
9941
10237
|
args.push(options.since);
|
|
9942
10238
|
}
|
|
9943
|
-
|
|
9944
|
-
sql += ` AND memory_type = ?`;
|
|
9945
|
-
args.push(options.memoryType);
|
|
9946
|
-
}
|
|
10239
|
+
sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
|
|
9947
10240
|
if (textFilter) {
|
|
9948
10241
|
sql += ` AND raw_text LIKE '%' || ? || '%'`;
|
|
9949
10242
|
args.push(textFilter);
|
|
@@ -10389,6 +10682,36 @@ ${fresh.map(
|
|
|
10389
10682
|
}
|
|
10390
10683
|
}
|
|
10391
10684
|
}
|
|
10685
|
+
let behaviorContext = "";
|
|
10686
|
+
if (!IS_CODEX_RUNTIME && agent.agentId !== "default") {
|
|
10687
|
+
try {
|
|
10688
|
+
const counterPath = path25.join(CACHE_DIR3, `prompt-count-${getSessionKey()}`);
|
|
10689
|
+
let count = 1;
|
|
10690
|
+
try {
|
|
10691
|
+
count = parseInt(readFileSync17(counterPath, "utf8").trim(), 10) + 1;
|
|
10692
|
+
} catch {
|
|
10693
|
+
}
|
|
10694
|
+
writeFileSync11(counterPath, String(count), "utf8");
|
|
10695
|
+
const BEHAVIOR_REINJECT_INTERVAL = 50;
|
|
10696
|
+
if (count === 1 || count % BEHAVIOR_REINJECT_INTERVAL === 0) {
|
|
10697
|
+
const { listBehaviors: listBehaviors2 } = await Promise.resolve().then(() => (init_behaviors(), behaviors_exports));
|
|
10698
|
+
const behaviors = await listBehaviors2(agent.agentId);
|
|
10699
|
+
const active = behaviors.filter((b) => b.active !== 0).sort((a, b) => (a.priority === "p0" ? -1 : 1) - (b.priority === "p0" ? -1 : 1)).slice(0, 15);
|
|
10700
|
+
if (active.length > 0) {
|
|
10701
|
+
const lines = active.map(
|
|
10702
|
+
(b) => `- [${b.domain ?? "workflow"}] ${b.content.slice(0, 200)}`
|
|
10703
|
+
);
|
|
10704
|
+
behaviorContext = `
|
|
10705
|
+
## Your Behavioral Memory
|
|
10706
|
+
Validated patterns and corrections for this session. Follow them.
|
|
10707
|
+
Sourced from exe-os Layer 2 (Expertise). Changes apply on next spawn.
|
|
10708
|
+
|
|
10709
|
+
${lines.join("\n")}`;
|
|
10710
|
+
}
|
|
10711
|
+
}
|
|
10712
|
+
} catch {
|
|
10713
|
+
}
|
|
10714
|
+
}
|
|
10392
10715
|
let reviewContext = "";
|
|
10393
10716
|
if (canCoordinate(agent.agentId, agent.agentRole)) {
|
|
10394
10717
|
try {
|
|
@@ -10444,7 +10767,7 @@ IMPORTANT: After completing your current task, you MUST address the pending revi
|
|
|
10444
10767
|
} catch {
|
|
10445
10768
|
}
|
|
10446
10769
|
}
|
|
10447
|
-
const combined = [cacheContext, memoryContext, reviewContext].filter(Boolean).join("\n\n");
|
|
10770
|
+
const combined = [cacheContext, memoryContext, behaviorContext, reviewContext].filter(Boolean).join("\n\n");
|
|
10448
10771
|
if (combined.length > 0) {
|
|
10449
10772
|
const output = JSON.stringify({
|
|
10450
10773
|
hookSpecificOutput: {
|