@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.
Files changed (76) hide show
  1. package/dist/bin/backfill-conversations.js +212 -11
  2. package/dist/bin/backfill-responses.js +212 -11
  3. package/dist/bin/backfill-vectors.js +14 -3
  4. package/dist/bin/cleanup-stale-review-tasks.js +224 -12
  5. package/dist/bin/cli.js +265 -23
  6. package/dist/bin/exe-agent.js +1 -1
  7. package/dist/bin/exe-assign.js +217 -12
  8. package/dist/bin/exe-boot.js +25 -4
  9. package/dist/bin/exe-call.js +7 -5
  10. package/dist/bin/exe-dispatch.js +229 -13
  11. package/dist/bin/exe-doctor.js +14 -3
  12. package/dist/bin/exe-export-behaviors.js +301 -14
  13. package/dist/bin/exe-forget.js +245 -21
  14. package/dist/bin/exe-gateway.js +229 -13
  15. package/dist/bin/exe-heartbeat.js +224 -12
  16. package/dist/bin/exe-kill.js +224 -12
  17. package/dist/bin/exe-launch-agent.js +177 -9
  18. package/dist/bin/exe-link.js +8 -0
  19. package/dist/bin/exe-new-employee.js +26 -2
  20. package/dist/bin/exe-pending-messages.js +224 -12
  21. package/dist/bin/exe-pending-notifications.js +224 -12
  22. package/dist/bin/exe-pending-reviews.js +224 -12
  23. package/dist/bin/exe-rename.js +9 -1
  24. package/dist/bin/exe-review.js +224 -12
  25. package/dist/bin/exe-search.js +246 -21
  26. package/dist/bin/exe-session-cleanup.js +229 -13
  27. package/dist/bin/exe-start-codex.js +161 -5
  28. package/dist/bin/exe-start-opencode.js +172 -5
  29. package/dist/bin/exe-status.js +224 -12
  30. package/dist/bin/exe-team.js +224 -12
  31. package/dist/bin/git-sweep.js +229 -13
  32. package/dist/bin/graph-backfill.js +94 -3
  33. package/dist/bin/graph-export.js +224 -12
  34. package/dist/bin/install.js +25 -1
  35. package/dist/bin/intercom-check.js +229 -13
  36. package/dist/bin/scan-tasks.js +229 -13
  37. package/dist/bin/setup.js +15 -5
  38. package/dist/bin/shard-migrate.js +94 -3
  39. package/dist/gateway/index.js +229 -13
  40. package/dist/hooks/bug-report-worker.js +229 -13
  41. package/dist/hooks/codex-stop-task-finalizer.js +224 -12
  42. package/dist/hooks/commit-complete.js +229 -13
  43. package/dist/hooks/error-recall.js +246 -21
  44. package/dist/hooks/ingest.js +224 -12
  45. package/dist/hooks/instructions-loaded.js +224 -12
  46. package/dist/hooks/notification.js +224 -12
  47. package/dist/hooks/post-compact.js +224 -12
  48. package/dist/hooks/post-tool-combined.js +246 -21
  49. package/dist/hooks/pre-compact.js +229 -13
  50. package/dist/hooks/pre-tool-use.js +234 -18
  51. package/dist/hooks/prompt-submit.js +346 -23
  52. package/dist/hooks/session-end.js +229 -13
  53. package/dist/hooks/session-start.js +418 -42
  54. package/dist/hooks/stop.js +224 -12
  55. package/dist/hooks/subagent-stop.js +224 -12
  56. package/dist/hooks/summary-worker.js +15 -2
  57. package/dist/index.js +229 -13
  58. package/dist/lib/cloud-sync.js +8 -0
  59. package/dist/lib/consolidation.js +3 -1
  60. package/dist/lib/database.js +8 -0
  61. package/dist/lib/db.js +8 -0
  62. package/dist/lib/device-registry.js +8 -0
  63. package/dist/lib/employee-templates.js +7 -5
  64. package/dist/lib/exe-daemon.js +1776 -1433
  65. package/dist/lib/hybrid-search.js +246 -21
  66. package/dist/lib/schedules.js +14 -3
  67. package/dist/lib/store.js +217 -12
  68. package/dist/lib/tasks.js +5 -1
  69. package/dist/lib/tmux-routing.js +5 -1
  70. package/dist/mcp/server.js +331 -37
  71. package/dist/mcp/tools/create-task.js +5 -1
  72. package/dist/mcp/tools/update-task.js +5 -1
  73. package/dist/runtime/index.js +229 -13
  74. package/dist/tui/App.js +229 -13
  75. package/package.json +1 -1
  76. 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 COO 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."
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 contentHash = createHash("md5").update(record.raw_text).digest("hex");
4073
- if (_pendingRecords.some((r) => r.content_hash === contentHash && r.agent_id === record.agent_id)) {
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 client = getClient();
4078
- const existing = await client.execute({
4079
- sql: "SELECT id FROM memories WHERE content_hash = ? AND agent_id = ? LIMIT 1",
4080
- args: [contentHash, record.agent_id]
4282
+ const existing = await findScopedDuplicate({
4283
+ contentHash,
4284
+ agentId: record.agent_id,
4285
+ projectName: record.project_name,
4286
+ memoryType
4081
4287
  });
4082
- if (existing.rows.length > 0) return;
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: record.memory_type ?? "raw",
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?.memoryType) {
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
- envPrefix = `${envPrefix} ANTHROPIC_MODEL=${agentRtConfig.model}`;
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
- if (options?.memoryType) {
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: [agentId, windowStart, killedAt, boundarySlots]
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
- if (options?.memoryType) {
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: {