@askexenow/exe-os 0.9.35 → 0.9.37

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 (67) hide show
  1. package/dist/bin/backfill-conversations.js +5 -1
  2. package/dist/bin/backfill-responses.js +5 -1
  3. package/dist/bin/backfill-vectors.js +1 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +10 -2
  5. package/dist/bin/cli.js +48 -14
  6. package/dist/bin/exe-agent.js +1 -1
  7. package/dist/bin/exe-assign.js +10 -2
  8. package/dist/bin/exe-boot.js +1 -1
  9. package/dist/bin/exe-call.js +7 -5
  10. package/dist/bin/exe-dispatch.js +10 -2
  11. package/dist/bin/exe-doctor.js +1 -1
  12. package/dist/bin/exe-export-behaviors.js +87 -4
  13. package/dist/bin/exe-forget.js +31 -11
  14. package/dist/bin/exe-gateway.js +10 -2
  15. package/dist/bin/exe-heartbeat.js +10 -2
  16. package/dist/bin/exe-kill.js +10 -2
  17. package/dist/bin/exe-launch-agent.js +85 -7
  18. package/dist/bin/exe-new-employee.js +26 -2
  19. package/dist/bin/exe-pending-messages.js +10 -2
  20. package/dist/bin/exe-pending-notifications.js +10 -2
  21. package/dist/bin/exe-pending-reviews.js +10 -2
  22. package/dist/bin/exe-rename.js +1 -1
  23. package/dist/bin/exe-review.js +10 -2
  24. package/dist/bin/exe-search.js +38 -19
  25. package/dist/bin/exe-session-cleanup.js +14 -3
  26. package/dist/bin/exe-start-codex.js +69 -3
  27. package/dist/bin/exe-start-opencode.js +80 -3
  28. package/dist/bin/exe-status.js +10 -2
  29. package/dist/bin/exe-team.js +10 -2
  30. package/dist/bin/git-sweep.js +10 -2
  31. package/dist/bin/graph-backfill.js +2 -1
  32. package/dist/bin/graph-export.js +10 -2
  33. package/dist/bin/install.js +25 -1
  34. package/dist/bin/intercom-check.js +10 -2
  35. package/dist/bin/scan-tasks.js +10 -2
  36. package/dist/bin/setup.js +7 -5
  37. package/dist/bin/shard-migrate.js +2 -1
  38. package/dist/gateway/index.js +10 -2
  39. package/dist/hooks/bug-report-worker.js +10 -2
  40. package/dist/hooks/codex-stop-task-finalizer.js +10 -2
  41. package/dist/hooks/commit-complete.js +10 -2
  42. package/dist/hooks/error-recall.js +38 -19
  43. package/dist/hooks/ingest-worker.js +9 -2
  44. package/dist/hooks/ingest.js +10 -2
  45. package/dist/hooks/instructions-loaded.js +10 -2
  46. package/dist/hooks/notification.js +10 -2
  47. package/dist/hooks/post-compact.js +10 -2
  48. package/dist/hooks/post-tool-combined.js +47 -21
  49. package/dist/hooks/pre-compact.js +12 -3
  50. package/dist/hooks/pre-tool-use.js +20 -8
  51. package/dist/hooks/prompt-submit.js +133 -20
  52. package/dist/hooks/session-end.js +138 -5
  53. package/dist/hooks/session-start.js +216 -46
  54. package/dist/hooks/stop.js +14 -4
  55. package/dist/hooks/subagent-stop.js +10 -2
  56. package/dist/hooks/summary-worker.js +121 -19
  57. package/dist/index.js +32 -16
  58. package/dist/lib/employee-templates.js +7 -5
  59. package/dist/lib/exe-daemon.js +124 -34
  60. package/dist/lib/hybrid-search.js +38 -19
  61. package/dist/lib/schedules.js +1 -1
  62. package/dist/lib/store.js +10 -2
  63. package/dist/mcp/server.js +118 -34
  64. package/dist/runtime/index.js +32 -16
  65. package/dist/tui/App.js +10 -2
  66. package/package.json +1 -1
  67. package/src/commands/exe/save.md +52 -0
@@ -3043,6 +3043,9 @@ function classifyMemoryType(input) {
3043
3043
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3044
3044
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3045
3045
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3046
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3047
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3048
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3046
3049
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3047
3050
  if (tool === "store_memory" || tool === "manual") return "observation";
3048
3051
  return "raw";
@@ -3185,6 +3188,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3185
3188
  }
3186
3189
  }
3187
3190
  function schedulePostWriteMemoryHygiene(memoryIds) {
3191
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3188
3192
  if (memoryIds.length === 0) return;
3189
3193
  const run = () => {
3190
3194
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3579,7 +3583,7 @@ var init_platform_procedures = __esm({
3579
3583
  title: "Chain of command \u2014 who talks to whom",
3580
3584
  domain: "workflow",
3581
3585
  priority: "p0",
3582
- 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."
3586
+ 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."
3583
3587
  },
3584
3588
  {
3585
3589
  title: "Single dispatch path \u2014 create_task only",
@@ -4251,7 +4255,11 @@ async function searchMemories(queryVector, agentId, options) {
4251
4255
  sql += ` AND timestamp >= ?`;
4252
4256
  args.push(options.since);
4253
4257
  }
4254
- if (options?.memoryType) {
4258
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4259
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4260
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4261
+ args.push(...uniqueTypes);
4262
+ } else if (options?.memoryType) {
4255
4263
  sql += ` AND memory_type = ?`;
4256
4264
  args.push(options.memoryType);
4257
4265
  }
@@ -5546,6 +5554,17 @@ init_store();
5546
5554
  init_store();
5547
5555
  init_database();
5548
5556
  var RRF_K = 60;
5557
+ function appendMemoryTypeFilter(sql, args, column, options) {
5558
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
5559
+ const uniqueTypes = [...new Set(options.memoryTypes)];
5560
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
5561
+ args.push(...uniqueTypes);
5562
+ } else if (options?.memoryType) {
5563
+ sql += ` AND ${column} = ?`;
5564
+ args.push(options.memoryType);
5565
+ }
5566
+ return sql;
5567
+ }
5549
5568
  async function hybridSearch(queryText, agentId, options) {
5550
5569
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
5551
5570
  const config = await loadConfig2();
@@ -5641,7 +5660,7 @@ async function hybridSearch(queryText, agentId, options) {
5641
5660
  }
5642
5661
  if (lists.length === 0) return [];
5643
5662
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
5644
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
5663
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
5645
5664
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
5646
5665
  let graphContextMap = /* @__PURE__ */ new Map();
5647
5666
  let entityBoostRan = false;
@@ -5662,6 +5681,7 @@ async function hybridSearch(queryText, agentId, options) {
5662
5681
  returnTopK: 5
5663
5682
  };
5664
5683
  let rerankedAndBlended = null;
5684
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
5665
5685
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
5666
5686
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
5667
5687
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -5673,16 +5693,16 @@ async function hybridSearch(queryText, agentId, options) {
5673
5693
  text: m.raw_text,
5674
5694
  context: graphContextMap.get(m.id)
5675
5695
  }));
5676
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
5696
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
5677
5697
  rerankedRecords = scored.map((s) => merged[s.index]);
5678
5698
  } else {
5679
5699
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
5680
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
5700
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
5681
5701
  }
5682
5702
  if (rerankedRecords.length > 0) {
5683
5703
  rerankedAndBlended = rrfMergeMulti(
5684
5704
  [rerankedRecords],
5685
- auto.returnTopK,
5705
+ rerankReturnLimit,
5686
5706
  RRF_K
5687
5707
  );
5688
5708
  }
@@ -5690,10 +5710,7 @@ async function hybridSearch(queryText, agentId, options) {
5690
5710
  }
5691
5711
  }
5692
5712
  }
5693
- const finalResults = (rerankedAndBlended ?? merged).slice(
5694
- 0,
5695
- rerankedAndBlended ? auto.returnTopK : limit
5696
- );
5713
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
5697
5714
  if (options?.includeSource && finalResults.length > 0) {
5698
5715
  await attachDocumentMetadata(finalResults);
5699
5716
  }
@@ -5774,6 +5791,7 @@ async function estimateCardinality(agentId, options) {
5774
5791
  sql += ` AND timestamp >= ?`;
5775
5792
  args.push(options.since);
5776
5793
  }
5794
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
5777
5795
  try {
5778
5796
  const result = await client.execute({ sql, args });
5779
5797
  return Number(result.rows[0]?.cnt) || 0;
@@ -5892,10 +5910,7 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
5892
5910
  sql += ` AND m.timestamp >= ?`;
5893
5911
  args.push(options.since);
5894
5912
  }
5895
- if (options?.memoryType) {
5896
- sql += ` AND m.memory_type = ?`;
5897
- args.push(options.memoryType);
5898
- }
5913
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
5899
5914
  sql += ` ORDER BY rank LIMIT ?`;
5900
5915
  args.push(limit);
5901
5916
  const result = await client.execute({ sql, args });
@@ -5952,9 +5967,16 @@ async function recentRecords(agentId, options, limit, textFilter) {
5952
5967
  AND timestamp >= ? AND timestamp <= ?
5953
5968
  AND COALESCE(status, 'active') = 'active'
5954
5969
  AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
5970
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
5955
5971
  AND COALESCE(confidence, 0.7) >= 0.3
5956
5972
  ORDER BY timestamp DESC LIMIT ?`,
5957
- args: [agentId, windowStart, killedAt, boundarySlots]
5973
+ args: [
5974
+ agentId,
5975
+ windowStart,
5976
+ killedAt,
5977
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
5978
+ boundarySlots
5979
+ ]
5958
5980
  });
5959
5981
  for (const row of boundaryResult.rows) {
5960
5982
  sessionBoundaryMemories.push(rowToMemoryRecord(row));
@@ -6000,10 +6022,7 @@ async function recentRecords(agentId, options, limit, textFilter) {
6000
6022
  sql += ` AND timestamp >= ?`;
6001
6023
  args.push(options.since);
6002
6024
  }
6003
- if (options?.memoryType) {
6004
- sql += ` AND memory_type = ?`;
6005
- args.push(options.memoryType);
6006
- }
6025
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
6007
6026
  if (textFilter) {
6008
6027
  sql += ` AND raw_text LIKE '%' || ? || '%'`;
6009
6028
  args.push(textFilter);
@@ -3087,6 +3087,9 @@ function classifyMemoryType(input) {
3087
3087
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3088
3088
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3089
3089
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3090
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3091
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3092
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3090
3093
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3091
3094
  if (tool === "store_memory" || tool === "manual") return "observation";
3092
3095
  return "raw";
@@ -3229,6 +3232,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3229
3232
  }
3230
3233
  }
3231
3234
  function schedulePostWriteMemoryHygiene(memoryIds) {
3235
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3232
3236
  if (memoryIds.length === 0) return;
3233
3237
  const run = () => {
3234
3238
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3623,7 +3627,7 @@ var init_platform_procedures = __esm({
3623
3627
  title: "Chain of command \u2014 who talks to whom",
3624
3628
  domain: "workflow",
3625
3629
  priority: "p0",
3626
- 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."
3630
+ 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."
3627
3631
  },
3628
3632
  {
3629
3633
  title: "Single dispatch path \u2014 create_task only",
@@ -4295,7 +4299,11 @@ async function searchMemories(queryVector, agentId, options) {
4295
4299
  sql += ` AND timestamp >= ?`;
4296
4300
  args.push(options.since);
4297
4301
  }
4298
- if (options?.memoryType) {
4302
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4303
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4304
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4305
+ args.push(...uniqueTypes);
4306
+ } else if (options?.memoryType) {
4299
4307
  sql += ` AND memory_type = ?`;
4300
4308
  args.push(options.memoryType);
4301
4309
  }
@@ -8520,6 +8528,7 @@ try {
8520
8528
  }
8521
8529
  const toolBreakdown = [...tools.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([t, c]) => `${t}(${c})`).join(", ");
8522
8530
  const summaryParts = [
8531
+ `CONTEXT CHECKPOINT [auto:session-cleanup]`,
8523
8532
  `Session: ${agentName} | ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]} | ${[...projects].join(", ")}`,
8524
8533
  `Tool calls: ${memories.rows.length} recent \u2014 ${toolBreakdown}`
8525
8534
  ];
@@ -8543,7 +8552,9 @@ try {
8543
8552
  project_name: getProjectName(),
8544
8553
  has_error: errors.length > 0,
8545
8554
  raw_text: summaryText,
8546
- vector
8555
+ vector,
8556
+ importance: 8,
8557
+ memory_type: "checkpoint"
8547
8558
  });
8548
8559
  await flushBatch();
8549
8560
  }
@@ -129,6 +129,21 @@ var init_secure_files = __esm({
129
129
  });
130
130
 
131
131
  // src/lib/config.ts
132
+ var config_exports = {};
133
+ __export(config_exports, {
134
+ CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
135
+ CONFIG_PATH: () => CONFIG_PATH,
136
+ CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
137
+ DB_PATH: () => DB_PATH,
138
+ EXE_AI_DIR: () => EXE_AI_DIR,
139
+ LEGACY_LANCE_PATH: () => LEGACY_LANCE_PATH,
140
+ MODELS_DIR: () => MODELS_DIR,
141
+ loadConfig: () => loadConfig,
142
+ loadConfigFrom: () => loadConfigFrom,
143
+ loadConfigSync: () => loadConfigSync,
144
+ migrateConfig: () => migrateConfig,
145
+ saveConfig: () => saveConfig
146
+ });
132
147
  import { readFile, writeFile } from "fs/promises";
133
148
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
134
149
  import path from "path";
@@ -232,6 +247,46 @@ async function loadConfig() {
232
247
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
233
248
  }
234
249
  }
250
+ function loadConfigSync() {
251
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
252
+ const configPath = path.join(dir, "config.json");
253
+ if (!existsSync2(configPath)) {
254
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
255
+ }
256
+ try {
257
+ const raw = readFileSync(configPath, "utf-8");
258
+ let parsed = JSON.parse(raw);
259
+ parsed = migrateLegacyConfig(parsed);
260
+ const { config: migratedCfg } = migrateConfig(parsed);
261
+ normalizeScalingRoadmap(migratedCfg);
262
+ normalizeSessionLifecycle(migratedCfg);
263
+ normalizeAutoUpdate(migratedCfg);
264
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
265
+ } catch {
266
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
267
+ }
268
+ }
269
+ async function saveConfig(config) {
270
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
271
+ await ensurePrivateDir(dir);
272
+ const configPath = path.join(dir, "config.json");
273
+ await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
274
+ await enforcePrivateFile(configPath);
275
+ }
276
+ async function loadConfigFrom(configPath) {
277
+ const raw = await readFile(configPath, "utf-8");
278
+ try {
279
+ let parsed = JSON.parse(raw);
280
+ parsed = migrateLegacyConfig(parsed);
281
+ const { config: migratedCfg } = migrateConfig(parsed);
282
+ normalizeScalingRoadmap(migratedCfg);
283
+ normalizeSessionLifecycle(migratedCfg);
284
+ normalizeAutoUpdate(migratedCfg);
285
+ return { ...DEFAULT_CONFIG, ...migratedCfg };
286
+ } catch {
287
+ return { ...DEFAULT_CONFIG };
288
+ }
289
+ }
235
290
  var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
236
291
  var init_config = __esm({
237
292
  "src/lib/config.ts"() {
@@ -2967,7 +3022,7 @@ var init_platform_procedures = __esm({
2967
3022
  title: "Chain of command \u2014 who talks to whom",
2968
3023
  domain: "workflow",
2969
3024
  priority: "p0",
2970
- 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."
3025
+ 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."
2971
3026
  },
2972
3027
  {
2973
3028
  title: "Single dispatch path \u2014 create_task only",
@@ -3521,6 +3576,7 @@ var init_preferences = __esm({
3521
3576
  // src/adapters/claude/installer.ts
3522
3577
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
3523
3578
  import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
3579
+ import { createHash as createHash2 } from "crypto";
3524
3580
  import path12 from "path";
3525
3581
  import os9 from "os";
3526
3582
  import { execSync as execSync5 } from "child_process";
@@ -4287,6 +4343,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4287
4343
  }
4288
4344
  }
4289
4345
  function schedulePostWriteMemoryHygiene(memoryIds) {
4346
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4290
4347
  if (memoryIds.length === 0) return;
4291
4348
  const run = () => {
4292
4349
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4606,7 +4663,16 @@ var BEHAVIORS_EXPORT_DIR = path8.join(
4606
4663
  "behaviors-export"
4607
4664
  );
4608
4665
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
4609
- var EXPORT_BEHAVIOR_LIMIT = 30;
4666
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
4667
+ function getBehaviorLimit() {
4668
+ try {
4669
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
4670
+ const cfg = loadConfigSync2();
4671
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
4672
+ } catch {
4673
+ return DEFAULT_BEHAVIOR_LIMIT;
4674
+ }
4675
+ }
4610
4676
  function sweepStaleBehaviorExports(now = Date.now()) {
4611
4677
  if (!existsSync8(BEHAVIORS_EXPORT_DIR)) return;
4612
4678
  let entries;
@@ -4660,7 +4726,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
4660
4726
  async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
4661
4727
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
4662
4728
  sweepStaleBehaviorExports();
4663
- const behaviors = await listBehaviors(agentId, projectName, EXPORT_BEHAVIOR_LIMIT);
4729
+ const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
4664
4730
  if (behaviors.length === 0) return null;
4665
4731
  const body = renderBehaviorExport(behaviors);
4666
4732
  const target = exportFilePath(agentId, projectName, sessionKey);
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
6
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
7
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
8
  }) : x)(function(x) {
@@ -14,6 +16,15 @@ var __export = (target, all) => {
14
16
  for (var name in all)
15
17
  __defProp(target, name, { get: all[name], enumerable: true });
16
18
  };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
17
28
 
18
29
  // src/types/memory.ts
19
30
  var EMBEDDING_DIM;
@@ -118,6 +129,21 @@ var init_secure_files = __esm({
118
129
  });
119
130
 
120
131
  // src/lib/config.ts
132
+ var config_exports = {};
133
+ __export(config_exports, {
134
+ CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
135
+ CONFIG_PATH: () => CONFIG_PATH,
136
+ CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
137
+ DB_PATH: () => DB_PATH,
138
+ EXE_AI_DIR: () => EXE_AI_DIR,
139
+ LEGACY_LANCE_PATH: () => LEGACY_LANCE_PATH,
140
+ MODELS_DIR: () => MODELS_DIR,
141
+ loadConfig: () => loadConfig,
142
+ loadConfigFrom: () => loadConfigFrom,
143
+ loadConfigSync: () => loadConfigSync,
144
+ migrateConfig: () => migrateConfig,
145
+ saveConfig: () => saveConfig
146
+ });
121
147
  import { readFile, writeFile } from "fs/promises";
122
148
  import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
123
149
  import path from "path";
@@ -221,6 +247,46 @@ async function loadConfig() {
221
247
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
222
248
  }
223
249
  }
250
+ function loadConfigSync() {
251
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
252
+ const configPath = path.join(dir, "config.json");
253
+ if (!existsSync2(configPath)) {
254
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
255
+ }
256
+ try {
257
+ const raw = readFileSync(configPath, "utf-8");
258
+ let parsed = JSON.parse(raw);
259
+ parsed = migrateLegacyConfig(parsed);
260
+ const { config: migratedCfg } = migrateConfig(parsed);
261
+ normalizeScalingRoadmap(migratedCfg);
262
+ normalizeSessionLifecycle(migratedCfg);
263
+ normalizeAutoUpdate(migratedCfg);
264
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
265
+ } catch {
266
+ return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
267
+ }
268
+ }
269
+ async function saveConfig(config) {
270
+ const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
271
+ await ensurePrivateDir(dir);
272
+ const configPath = path.join(dir, "config.json");
273
+ await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
274
+ await enforcePrivateFile(configPath);
275
+ }
276
+ async function loadConfigFrom(configPath) {
277
+ const raw = await readFile(configPath, "utf-8");
278
+ try {
279
+ let parsed = JSON.parse(raw);
280
+ parsed = migrateLegacyConfig(parsed);
281
+ const { config: migratedCfg } = migrateConfig(parsed);
282
+ normalizeScalingRoadmap(migratedCfg);
283
+ normalizeSessionLifecycle(migratedCfg);
284
+ normalizeAutoUpdate(migratedCfg);
285
+ return { ...DEFAULT_CONFIG, ...migratedCfg };
286
+ } catch {
287
+ return { ...DEFAULT_CONFIG };
288
+ }
289
+ }
224
290
  var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
225
291
  var init_config = __esm({
226
292
  "src/lib/config.ts"() {
@@ -2956,7 +3022,7 @@ var init_platform_procedures = __esm({
2956
3022
  title: "Chain of command \u2014 who talks to whom",
2957
3023
  domain: "workflow",
2958
3024
  priority: "p0",
2959
- 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."
3025
+ 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."
2960
3026
  },
2961
3027
  {
2962
3028
  title: "Single dispatch path \u2014 create_task only",
@@ -3499,6 +3565,7 @@ var init_preferences = __esm({
3499
3565
  // src/adapters/claude/installer.ts
3500
3566
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
3501
3567
  import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
3568
+ import { createHash as createHash2 } from "crypto";
3502
3569
  import path12 from "path";
3503
3570
  import os9 from "os";
3504
3571
  import { execSync as execSync5 } from "child_process";
@@ -4141,6 +4208,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
4141
4208
  }
4142
4209
  }
4143
4210
  function schedulePostWriteMemoryHygiene(memoryIds) {
4211
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
4144
4212
  if (memoryIds.length === 0) return;
4145
4213
  const run = () => {
4146
4214
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -4460,7 +4528,16 @@ var BEHAVIORS_EXPORT_DIR = path8.join(
4460
4528
  "behaviors-export"
4461
4529
  );
4462
4530
  var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
4463
- var EXPORT_BEHAVIOR_LIMIT = 30;
4531
+ var DEFAULT_BEHAVIOR_LIMIT = 30;
4532
+ function getBehaviorLimit() {
4533
+ try {
4534
+ const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
4535
+ const cfg = loadConfigSync2();
4536
+ return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
4537
+ } catch {
4538
+ return DEFAULT_BEHAVIOR_LIMIT;
4539
+ }
4540
+ }
4464
4541
  function sweepStaleBehaviorExports(now = Date.now()) {
4465
4542
  if (!existsSync8(BEHAVIORS_EXPORT_DIR)) return;
4466
4543
  let entries;
@@ -4514,7 +4591,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
4514
4591
  async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
4515
4592
  mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
4516
4593
  sweepStaleBehaviorExports();
4517
- const behaviors = await listBehaviors(agentId, projectName, EXPORT_BEHAVIOR_LIMIT);
4594
+ const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
4518
4595
  if (behaviors.length === 0) return null;
4519
4596
  const body = renderBehaviorExport(behaviors);
4520
4597
  const target = exportFilePath(agentId, projectName, sessionKey);
@@ -3076,6 +3076,9 @@ function classifyMemoryType(input) {
3076
3076
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3077
3077
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3078
3078
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3079
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3080
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3081
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3079
3082
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3080
3083
  if (tool === "store_memory" || tool === "manual") return "observation";
3081
3084
  return "raw";
@@ -3218,6 +3221,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3218
3221
  }
3219
3222
  }
3220
3223
  function schedulePostWriteMemoryHygiene(memoryIds) {
3224
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3221
3225
  if (memoryIds.length === 0) return;
3222
3226
  const run = () => {
3223
3227
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3612,7 +3616,7 @@ var init_platform_procedures = __esm({
3612
3616
  title: "Chain of command \u2014 who talks to whom",
3613
3617
  domain: "workflow",
3614
3618
  priority: "p0",
3615
- 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."
3619
+ 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."
3616
3620
  },
3617
3621
  {
3618
3622
  title: "Single dispatch path \u2014 create_task only",
@@ -4284,7 +4288,11 @@ async function searchMemories(queryVector, agentId, options) {
4284
4288
  sql += ` AND timestamp >= ?`;
4285
4289
  args.push(options.since);
4286
4290
  }
4287
- if (options?.memoryType) {
4291
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4292
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4293
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4294
+ args.push(...uniqueTypes);
4295
+ } else if (options?.memoryType) {
4288
4296
  sql += ` AND memory_type = ?`;
4289
4297
  args.push(options.memoryType);
4290
4298
  }
@@ -3065,6 +3065,9 @@ function classifyMemoryType(input) {
3065
3065
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3066
3066
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3067
3067
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3068
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3069
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3070
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3068
3071
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3069
3072
  if (tool === "store_memory" || tool === "manual") return "observation";
3070
3073
  return "raw";
@@ -3207,6 +3210,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3207
3210
  }
3208
3211
  }
3209
3212
  function schedulePostWriteMemoryHygiene(memoryIds) {
3213
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3210
3214
  if (memoryIds.length === 0) return;
3211
3215
  const run = () => {
3212
3216
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3601,7 +3605,7 @@ var init_platform_procedures = __esm({
3601
3605
  title: "Chain of command \u2014 who talks to whom",
3602
3606
  domain: "workflow",
3603
3607
  priority: "p0",
3604
- 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."
3608
+ 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."
3605
3609
  },
3606
3610
  {
3607
3611
  title: "Single dispatch path \u2014 create_task only",
@@ -4273,7 +4277,11 @@ async function searchMemories(queryVector, agentId, options) {
4273
4277
  sql += ` AND timestamp >= ?`;
4274
4278
  args.push(options.since);
4275
4279
  }
4276
- if (options?.memoryType) {
4280
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4281
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4282
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4283
+ args.push(...uniqueTypes);
4284
+ } else if (options?.memoryType) {
4277
4285
  sql += ` AND memory_type = ?`;
4278
4286
  args.push(options.memoryType);
4279
4287
  }
@@ -6688,6 +6688,9 @@ function classifyMemoryType(input) {
6688
6688
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
6689
6689
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
6690
6690
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
6691
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
6692
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
6693
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
6691
6694
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
6692
6695
  if (tool === "store_memory" || tool === "manual") return "observation";
6693
6696
  return "raw";
@@ -6830,6 +6833,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
6830
6833
  }
6831
6834
  }
6832
6835
  function schedulePostWriteMemoryHygiene(memoryIds) {
6836
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
6833
6837
  if (memoryIds.length === 0) return;
6834
6838
  const run = () => {
6835
6839
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -7224,7 +7228,7 @@ var init_platform_procedures = __esm({
7224
7228
  title: "Chain of command \u2014 who talks to whom",
7225
7229
  domain: "workflow",
7226
7230
  priority: "p0",
7227
- 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."
7231
+ 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."
7228
7232
  },
7229
7233
  {
7230
7234
  title: "Single dispatch path \u2014 create_task only",
@@ -7896,7 +7900,11 @@ async function searchMemories(queryVector, agentId, options) {
7896
7900
  sql += ` AND timestamp >= ?`;
7897
7901
  args2.push(options.since);
7898
7902
  }
7899
- if (options?.memoryType) {
7903
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
7904
+ const uniqueTypes = [...new Set(options.memoryTypes)];
7905
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
7906
+ args2.push(...uniqueTypes);
7907
+ } else if (options?.memoryType) {
7900
7908
  sql += ` AND memory_type = ?`;
7901
7909
  args2.push(options.memoryType);
7902
7910
  }
@@ -2945,7 +2945,7 @@ var init_platform_procedures = __esm({
2945
2945
  title: "Chain of command \u2014 who talks to whom",
2946
2946
  domain: "workflow",
2947
2947
  priority: "p0",
2948
- 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."
2948
+ 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."
2949
2949
  },
2950
2950
  {
2951
2951
  title: "Single dispatch path \u2014 create_task only",
@@ -3466,6 +3466,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3466
3466
  }
3467
3467
  }
3468
3468
  function schedulePostWriteMemoryHygiene(memoryIds) {
3469
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3469
3470
  if (memoryIds.length === 0) return;
3470
3471
  const run = () => {
3471
3472
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3054,6 +3054,9 @@ function classifyMemoryType(input) {
3054
3054
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3055
3055
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3056
3056
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3057
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3058
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3059
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3057
3060
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3058
3061
  if (tool === "store_memory" || tool === "manual") return "observation";
3059
3062
  return "raw";
@@ -3196,6 +3199,7 @@ async function runPostWriteMemoryHygiene(memoryId) {
3196
3199
  }
3197
3200
  }
3198
3201
  function schedulePostWriteMemoryHygiene(memoryIds) {
3202
+ if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
3199
3203
  if (memoryIds.length === 0) return;
3200
3204
  const run = () => {
3201
3205
  void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
@@ -3590,7 +3594,7 @@ var init_platform_procedures = __esm({
3590
3594
  title: "Chain of command \u2014 who talks to whom",
3591
3595
  domain: "workflow",
3592
3596
  priority: "p0",
3593
- 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."
3597
+ 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."
3594
3598
  },
3595
3599
  {
3596
3600
  title: "Single dispatch path \u2014 create_task only",
@@ -4262,7 +4266,11 @@ async function searchMemories(queryVector, agentId, options) {
4262
4266
  sql += ` AND timestamp >= ?`;
4263
4267
  args.push(options.since);
4264
4268
  }
4265
- if (options?.memoryType) {
4269
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
4270
+ const uniqueTypes = [...new Set(options.memoryTypes)];
4271
+ sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
4272
+ args.push(...uniqueTypes);
4273
+ } else if (options?.memoryType) {
4266
4274
  sql += ` AND memory_type = ?`;
4267
4275
  args.push(options.memoryType);
4268
4276
  }