@askexenow/exe-os 0.9.32 → 0.9.33

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.
@@ -4028,9 +4028,9 @@ async function auditDuplicates(client, flags) {
4028
4028
  const { clause, args } = agentFilter(flags);
4029
4029
  const backfillExclude = clause ? " AND tool_name != 'ConversationBackfill'" : " WHERE tool_name != 'ConversationBackfill'";
4030
4030
  const groups = await client.execute({
4031
- sql: `SELECT raw_text, COUNT(*) as cnt
4031
+ sql: `SELECT SUBSTR(raw_text, 1, 200) as text_head, LENGTH(raw_text) as text_len, COUNT(*) as cnt
4032
4032
  FROM memories${clause}${backfillExclude}
4033
- GROUP BY raw_text
4033
+ GROUP BY text_head, text_len
4034
4034
  HAVING cnt > 1
4035
4035
  ORDER BY cnt DESC
4036
4036
  LIMIT 500`,
@@ -4038,23 +4038,33 @@ async function auditDuplicates(client, flags) {
4038
4038
  });
4039
4039
  const duplicates = [];
4040
4040
  for (const g of groups.rows) {
4041
- const text = g.raw_text;
4042
- const cnt = Number(g.cnt);
4043
- const filterArgs = [text, ...args];
4044
- let filterClause = " WHERE raw_text = ?";
4041
+ const textHead = g.text_head;
4042
+ const textLen = Number(g.text_len);
4043
+ const filterArgs = [textHead, textLen, ...args];
4044
+ let filterClause = " WHERE SUBSTR(raw_text, 1, 200) = ? AND LENGTH(raw_text) = ?";
4045
4045
  if (flags.agent) filterClause += " AND agent_id = ?";
4046
4046
  if (flags.project) filterClause += " AND project_name = ?";
4047
4047
  const ids = await client.execute({
4048
- sql: `SELECT id FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
4048
+ sql: `SELECT id, raw_text FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
4049
4049
  args: filterArgs
4050
4050
  });
4051
- const allIds = ids.rows.map((r) => r.id);
4052
- duplicates.push({
4053
- raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
4054
- count: cnt,
4055
- keep_id: allIds[0],
4056
- delete_ids: allIds.slice(1)
4057
- });
4051
+ const byText = /* @__PURE__ */ new Map();
4052
+ for (const r of ids.rows) {
4053
+ const text = r.raw_text;
4054
+ const id = r.id;
4055
+ const existing = byText.get(text);
4056
+ if (existing) existing.push(id);
4057
+ else byText.set(text, [id]);
4058
+ }
4059
+ for (const [text, allIds] of byText) {
4060
+ if (allIds.length <= 1) continue;
4061
+ duplicates.push({
4062
+ raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
4063
+ count: allIds.length,
4064
+ keep_id: allIds[0],
4065
+ delete_ids: allIds.slice(1)
4066
+ });
4067
+ }
4058
4068
  }
4059
4069
  return duplicates;
4060
4070
  }
@@ -4559,16 +4559,19 @@ MCP tools are available under the exe-os server. Call them directly by name:
4559
4559
  - get_task \u2014 read full task context
4560
4560
  - update_task \u2014 mark tasks in_progress or done
4561
4561
  - store_memory \u2014 persist findings for future sessions
4562
- - recall_my_memory \u2014 search your past work
4562
+ - recall_my_memory \u2014 search your past work (IMPORTANT: call this before starting any task)
4563
4563
  - ask_team_memory \u2014 query a colleague's knowledge
4564
4564
 
4565
+ CRITICAL \u2014 Memory retrieval is NOT automatic in this runtime.
4566
+ You MUST call recall_my_memory proactively:
4567
+ - Before starting any task: recall relevant past work, decisions, and patterns
4568
+ - When encountering an error: recall past solutions
4569
+ - When making architectural decisions: recall past ADRs and constraints
4570
+ Do NOT assume you remember \u2014 always check memory first.
4571
+
4565
4572
  On startup: call list_tasks to check for assigned work.
4566
4573
  When done with a task: call update_task with status "done" and a result summary.
4567
4574
  Always call store_memory to persist important decisions.
4568
-
4569
- \u26A0 FIRST RUN: If hooks haven't been approved yet, run /hooks in Codex and approve
4570
- all exe-os hooks before starting work. Without approved hooks, memory capture
4571
- and session tracking won't function.
4572
4575
  `;
4573
4576
  function resolveAgent(argv) {
4574
4577
  const invokedAs = path15.basename(argv[1] ?? "");
@@ -20074,9 +20074,9 @@ async function auditDuplicates(client, flags) {
20074
20074
  const { clause, args } = agentFilter(flags);
20075
20075
  const backfillExclude = clause ? " AND tool_name != 'ConversationBackfill'" : " WHERE tool_name != 'ConversationBackfill'";
20076
20076
  const groups = await client.execute({
20077
- sql: `SELECT raw_text, COUNT(*) as cnt
20077
+ sql: `SELECT SUBSTR(raw_text, 1, 200) as text_head, LENGTH(raw_text) as text_len, COUNT(*) as cnt
20078
20078
  FROM memories${clause}${backfillExclude}
20079
- GROUP BY raw_text
20079
+ GROUP BY text_head, text_len
20080
20080
  HAVING cnt > 1
20081
20081
  ORDER BY cnt DESC
20082
20082
  LIMIT 500`,
@@ -20084,23 +20084,33 @@ async function auditDuplicates(client, flags) {
20084
20084
  });
20085
20085
  const duplicates = [];
20086
20086
  for (const g of groups.rows) {
20087
- const text = g.raw_text;
20088
- const cnt = Number(g.cnt);
20089
- const filterArgs = [text, ...args];
20090
- let filterClause = " WHERE raw_text = ?";
20087
+ const textHead = g.text_head;
20088
+ const textLen = Number(g.text_len);
20089
+ const filterArgs = [textHead, textLen, ...args];
20090
+ let filterClause = " WHERE SUBSTR(raw_text, 1, 200) = ? AND LENGTH(raw_text) = ?";
20091
20091
  if (flags.agent) filterClause += " AND agent_id = ?";
20092
20092
  if (flags.project) filterClause += " AND project_name = ?";
20093
20093
  const ids = await client.execute({
20094
- sql: `SELECT id FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
20094
+ sql: `SELECT id, raw_text FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
20095
20095
  args: filterArgs
20096
20096
  });
20097
- const allIds = ids.rows.map((r) => r.id);
20098
- duplicates.push({
20099
- raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
20100
- count: cnt,
20101
- keep_id: allIds[0],
20102
- delete_ids: allIds.slice(1)
20103
- });
20097
+ const byText = /* @__PURE__ */ new Map();
20098
+ for (const r of ids.rows) {
20099
+ const text = r.raw_text;
20100
+ const id = r.id;
20101
+ const existing = byText.get(text);
20102
+ if (existing) existing.push(id);
20103
+ else byText.set(text, [id]);
20104
+ }
20105
+ for (const [text, allIds] of byText) {
20106
+ if (allIds.length <= 1) continue;
20107
+ duplicates.push({
20108
+ raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
20109
+ count: allIds.length,
20110
+ keep_id: allIds[0],
20111
+ delete_ids: allIds.slice(1)
20112
+ });
20113
+ }
20104
20114
  }
20105
20115
  return duplicates;
20106
20116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.32",
3
+ "version": "0.9.33",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",