@askexenow/exe-os 0.9.111 → 0.9.113

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 (95) hide show
  1. package/README.md +9 -7
  2. package/dist/bin/agentic-ontology-backfill.js +62 -12
  3. package/dist/bin/agentic-reflection-backfill.js +37 -2
  4. package/dist/bin/agentic-semantic-label.js +37 -2
  5. package/dist/bin/backfill-conversations.js +61 -11
  6. package/dist/bin/backfill-responses.js +62 -12
  7. package/dist/bin/backfill-vectors.js +37 -2
  8. package/dist/bin/bulk-sync-postgres.js +63 -13
  9. package/dist/bin/cleanup-stale-review-tasks.js +83 -16
  10. package/dist/bin/cli.js +312 -80
  11. package/dist/bin/exe-agent-config.js +7 -1
  12. package/dist/bin/exe-agent.js +29 -3
  13. package/dist/bin/exe-assign.js +62 -12
  14. package/dist/bin/exe-boot.js +500 -151
  15. package/dist/bin/exe-call.js +46 -5
  16. package/dist/bin/exe-cloud.js +101 -16
  17. package/dist/bin/exe-dispatch.js +827 -27
  18. package/dist/bin/exe-doctor.js +61 -11
  19. package/dist/bin/exe-export-behaviors.js +67 -14
  20. package/dist/bin/exe-forget.js +62 -12
  21. package/dist/bin/exe-gateway.js +147 -27
  22. package/dist/bin/exe-heartbeat.js +83 -16
  23. package/dist/bin/exe-kill.js +62 -12
  24. package/dist/bin/exe-launch-agent.js +83 -15
  25. package/dist/bin/exe-new-employee.js +176 -8
  26. package/dist/bin/exe-pending-messages.js +83 -16
  27. package/dist/bin/exe-pending-notifications.js +83 -16
  28. package/dist/bin/exe-pending-reviews.js +83 -16
  29. package/dist/bin/exe-rename.js +62 -12
  30. package/dist/bin/exe-review.js +62 -12
  31. package/dist/bin/exe-search.js +62 -12
  32. package/dist/bin/exe-session-cleanup.js +949 -149
  33. package/dist/bin/exe-settings.js +10 -4
  34. package/dist/bin/exe-start-codex.js +537 -248
  35. package/dist/bin/exe-start-opencode.js +547 -168
  36. package/dist/bin/exe-status.js +83 -16
  37. package/dist/bin/exe-support.js +1 -1
  38. package/dist/bin/exe-team.js +62 -12
  39. package/dist/bin/git-sweep.js +827 -27
  40. package/dist/bin/graph-backfill.js +62 -12
  41. package/dist/bin/graph-export.js +62 -12
  42. package/dist/bin/install.js +62 -4
  43. package/dist/bin/intercom-check.js +949 -149
  44. package/dist/bin/pre-publish.js +14 -2
  45. package/dist/bin/scan-tasks.js +827 -27
  46. package/dist/bin/setup.js +99 -14
  47. package/dist/bin/shard-migrate.js +62 -12
  48. package/dist/bin/stack-update.js +1 -1
  49. package/dist/bin/update.js +3 -3
  50. package/dist/gateway/index.js +586 -26
  51. package/dist/hooks/bug-report-worker.js +586 -26
  52. package/dist/hooks/codex-stop-task-finalizer.js +977 -143
  53. package/dist/hooks/commit-complete.js +827 -27
  54. package/dist/hooks/error-recall.js +62 -12
  55. package/dist/hooks/ingest.js +4579 -249
  56. package/dist/hooks/instructions-loaded.js +62 -12
  57. package/dist/hooks/notification.js +62 -12
  58. package/dist/hooks/post-compact.js +83 -16
  59. package/dist/hooks/post-tool-combined.js +83 -16
  60. package/dist/hooks/pre-compact.js +907 -107
  61. package/dist/hooks/pre-tool-use.js +98 -16
  62. package/dist/hooks/prompt-submit.js +596 -30
  63. package/dist/hooks/session-end.js +909 -112
  64. package/dist/hooks/session-start.js +112 -17
  65. package/dist/hooks/stop.js +82 -15
  66. package/dist/hooks/subagent-stop.js +83 -16
  67. package/dist/hooks/summary-worker.js +81 -8
  68. package/dist/index.js +595 -29
  69. package/dist/lib/agent-config.js +16 -1
  70. package/dist/lib/cloud-sync.js +45 -1
  71. package/dist/lib/consolidation.js +16 -1
  72. package/dist/lib/database.js +23 -0
  73. package/dist/lib/db.js +23 -0
  74. package/dist/lib/device-registry.js +23 -0
  75. package/dist/lib/employee-templates.js +30 -4
  76. package/dist/lib/employees.js +16 -1
  77. package/dist/lib/exe-daemon.js +482 -52
  78. package/dist/lib/hybrid-search.js +62 -12
  79. package/dist/lib/license.js +3 -3
  80. package/dist/lib/messaging.js +21 -4
  81. package/dist/lib/schedules.js +37 -2
  82. package/dist/lib/skill-learning.js +910 -41
  83. package/dist/lib/status-brief.js +14 -1
  84. package/dist/lib/store.js +62 -12
  85. package/dist/lib/tasks.js +843 -93
  86. package/dist/lib/tmux-routing.js +766 -16
  87. package/dist/mcp/server.js +238 -41
  88. package/dist/mcp/tools/create-task.js +525 -15
  89. package/dist/mcp/tools/deactivate-behavior.js +33 -24
  90. package/dist/mcp/tools/list-tasks.js +21 -4
  91. package/dist/mcp/tools/send-message.js +21 -4
  92. package/dist/mcp/tools/update-task.js +840 -93
  93. package/dist/runtime/index.js +913 -107
  94. package/dist/tui/App.js +227 -58
  95. package/package.json +1 -1
@@ -2040,6 +2040,13 @@ async function ensureSchema() {
2040
2040
  } catch (e) {
2041
2041
  logCatchDebug("migration", e);
2042
2042
  }
2043
+ for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
2044
+ try {
2045
+ await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
2046
+ } catch (e) {
2047
+ logCatchDebug("migration", e);
2048
+ }
2049
+ }
2043
2050
  try {
2044
2051
  await client.execute({
2045
2052
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -3256,6 +3263,22 @@ async function ensureSchema() {
3256
3263
  } catch (e) {
3257
3264
  logCatchDebug("migration", e);
3258
3265
  }
3266
+ try {
3267
+ await client.execute({
3268
+ sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
3269
+ args: []
3270
+ });
3271
+ } catch (e) {
3272
+ logCatchDebug("migration", e);
3273
+ }
3274
+ try {
3275
+ await client.execute({
3276
+ sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
3277
+ args: []
3278
+ });
3279
+ } catch (e) {
3280
+ logCatchDebug("migration", e);
3281
+ }
3259
3282
  }
3260
3283
  async function disposeDatabase() {
3261
3284
  if (_walCheckpointTimer) {
@@ -4379,11 +4402,17 @@ var init_platform_procedures = __esm({
4379
4402
  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."
4380
4403
  },
4381
4404
  {
4382
- title: "Customer orchestration maturity \u2014 recommend, never trap",
4405
+ title: "Orchestration phase guidance \u2014 recommend, never trap",
4383
4406
  domain: "workflow",
4384
4407
  priority: "p1",
4385
4408
  content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
4386
4409
  },
4410
+ {
4411
+ title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
4412
+ domain: "identity",
4413
+ priority: "p0",
4414
+ content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
4415
+ },
4387
4416
  {
4388
4417
  title: "Single dispatch path \u2014 create_task only",
4389
4418
  domain: "workflow",
@@ -4417,6 +4446,12 @@ var init_platform_procedures = __esm({
4417
4446
  priority: "p0",
4418
4447
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
4419
4448
  },
4449
+ {
4450
+ title: "Destructive operations \u2014 mandatory reviewer gate",
4451
+ domain: "security",
4452
+ priority: "p0",
4453
+ content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
4454
+ },
4420
4455
  {
4421
4456
  title: "Customer patch triage \u2014 upstream bug vs customization",
4422
4457
  domain: "support",
@@ -4568,7 +4603,7 @@ var init_platform_procedures = __esm({
4568
4603
  title: "MCP tool dispatch \u2014 all tools use action parameter",
4569
4604
  domain: "tool-use",
4570
4605
  priority: "p0",
4571
- content: 'exe-os MCP tools come in two surfaces depending on EXE_MCP_TOOL_SURFACE config. Consolidated (19 tools): action-based dispatch \u2014 memory(action="recall"), task(action="create"), etc. Legacy (108 tools): one tool per operation \u2014 recall_my_memory, create_task, etc. Both surfaces have identical functionality. Use whichever tool names are available in your session. If you see domain tools (memory, task, config, etc.), use the action parameter. If you see specific tools (recall_my_memory, create_task, etc.), call them directly.'
4606
+ content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
4572
4607
  },
4573
4608
  {
4574
4609
  title: "MCP tools \u2014 memory, decision, and search",
@@ -4702,10 +4737,24 @@ function stableId(memoryId, type, content) {
4702
4737
  return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
4703
4738
  }
4704
4739
  function cleanText(text) {
4705
- return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4706
- }
4707
- function splitSentences(text) {
4708
- return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
4740
+ let cleaned = text.replace(
4741
+ /```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
4742
+ (_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
4743
+ );
4744
+ cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4745
+ return cleaned;
4746
+ }
4747
+ function splitSegments(text) {
4748
+ const cleaned = cleanText(text);
4749
+ const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
4750
+ if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
4751
+ const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
4752
+ if (lines.length > 0) return lines;
4753
+ if (cleaned.length >= MIN_SEGMENT_CHARS) {
4754
+ return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
4755
+ }
4756
+ }
4757
+ return segments;
4709
4758
  }
4710
4759
  function inferCardType(sentence, toolName) {
4711
4760
  const lower = sentence.toLowerCase();
@@ -4737,12 +4786,12 @@ function predicateFor(type) {
4737
4786
  }
4738
4787
  }
4739
4788
  function extractMemoryCards(row) {
4740
- const sentences = splitSentences(row.raw_text);
4789
+ const segments = splitSegments(row.raw_text);
4741
4790
  const cards = [];
4742
- for (const sentence of sentences) {
4791
+ for (const sentence of segments) {
4743
4792
  const type = inferCardType(sentence, row.tool_name);
4744
4793
  const subject = extractSubject(sentence, row.agent_id);
4745
- const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
4794
+ const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
4746
4795
  cards.push({
4747
4796
  id: stableId(row.id, type, content),
4748
4797
  memory_id: row.id,
@@ -4838,13 +4887,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
4838
4887
  last_accessed: String(row.timestamp)
4839
4888
  }));
4840
4889
  }
4841
- var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
4890
+ var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
4842
4891
  var init_memory_cards = __esm({
4843
4892
  "src/lib/memory-cards.ts"() {
4844
4893
  "use strict";
4845
4894
  init_database();
4846
- MAX_CARDS_PER_MEMORY = 6;
4847
- MAX_SENTENCE_CHARS = 360;
4895
+ MAX_CARDS_PER_MEMORY = 8;
4896
+ MAX_SEGMENT_CHARS = 500;
4897
+ MIN_SEGMENT_CHARS = 20;
4848
4898
  }
4849
4899
  });
4850
4900
 
@@ -2025,6 +2025,13 @@ async function ensureSchema() {
2025
2025
  } catch (e) {
2026
2026
  logCatchDebug("migration", e);
2027
2027
  }
2028
+ for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
2029
+ try {
2030
+ await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
2031
+ } catch (e) {
2032
+ logCatchDebug("migration", e);
2033
+ }
2034
+ }
2028
2035
  try {
2029
2036
  await client.execute({
2030
2037
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -3241,6 +3248,22 @@ async function ensureSchema() {
3241
3248
  } catch (e) {
3242
3249
  logCatchDebug("migration", e);
3243
3250
  }
3251
+ try {
3252
+ await client.execute({
3253
+ sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
3254
+ args: []
3255
+ });
3256
+ } catch (e) {
3257
+ logCatchDebug("migration", e);
3258
+ }
3259
+ try {
3260
+ await client.execute({
3261
+ sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
3262
+ args: []
3263
+ });
3264
+ } catch (e) {
3265
+ logCatchDebug("migration", e);
3266
+ }
3244
3267
  }
3245
3268
  async function disposeDatabase() {
3246
3269
  if (_walCheckpointTimer) {
@@ -4364,11 +4387,17 @@ var init_platform_procedures = __esm({
4364
4387
  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."
4365
4388
  },
4366
4389
  {
4367
- title: "Customer orchestration maturity \u2014 recommend, never trap",
4390
+ title: "Orchestration phase guidance \u2014 recommend, never trap",
4368
4391
  domain: "workflow",
4369
4392
  priority: "p1",
4370
4393
  content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
4371
4394
  },
4395
+ {
4396
+ title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
4397
+ domain: "identity",
4398
+ priority: "p0",
4399
+ content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
4400
+ },
4372
4401
  {
4373
4402
  title: "Single dispatch path \u2014 create_task only",
4374
4403
  domain: "workflow",
@@ -4402,6 +4431,12 @@ var init_platform_procedures = __esm({
4402
4431
  priority: "p0",
4403
4432
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
4404
4433
  },
4434
+ {
4435
+ title: "Destructive operations \u2014 mandatory reviewer gate",
4436
+ domain: "security",
4437
+ priority: "p0",
4438
+ content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
4439
+ },
4405
4440
  {
4406
4441
  title: "Customer patch triage \u2014 upstream bug vs customization",
4407
4442
  domain: "support",
@@ -4553,7 +4588,7 @@ var init_platform_procedures = __esm({
4553
4588
  title: "MCP tool dispatch \u2014 all tools use action parameter",
4554
4589
  domain: "tool-use",
4555
4590
  priority: "p0",
4556
- content: 'exe-os MCP tools come in two surfaces depending on EXE_MCP_TOOL_SURFACE config. Consolidated (19 tools): action-based dispatch \u2014 memory(action="recall"), task(action="create"), etc. Legacy (108 tools): one tool per operation \u2014 recall_my_memory, create_task, etc. Both surfaces have identical functionality. Use whichever tool names are available in your session. If you see domain tools (memory, task, config, etc.), use the action parameter. If you see specific tools (recall_my_memory, create_task, etc.), call them directly.'
4591
+ content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
4557
4592
  },
4558
4593
  {
4559
4594
  title: "MCP tools \u2014 memory, decision, and search",
@@ -4687,10 +4722,24 @@ function stableId(memoryId, type, content) {
4687
4722
  return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
4688
4723
  }
4689
4724
  function cleanText(text) {
4690
- return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4725
+ let cleaned = text.replace(
4726
+ /```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
4727
+ (_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
4728
+ );
4729
+ cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4730
+ return cleaned;
4691
4731
  }
4692
- function splitSentences(text) {
4693
- return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
4732
+ function splitSegments(text) {
4733
+ const cleaned = cleanText(text);
4734
+ const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
4735
+ if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
4736
+ const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
4737
+ if (lines.length > 0) return lines;
4738
+ if (cleaned.length >= MIN_SEGMENT_CHARS) {
4739
+ return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
4740
+ }
4741
+ }
4742
+ return segments;
4694
4743
  }
4695
4744
  function inferCardType(sentence, toolName) {
4696
4745
  const lower = sentence.toLowerCase();
@@ -4722,12 +4771,12 @@ function predicateFor(type) {
4722
4771
  }
4723
4772
  }
4724
4773
  function extractMemoryCards(row) {
4725
- const sentences = splitSentences(row.raw_text);
4774
+ const segments = splitSegments(row.raw_text);
4726
4775
  const cards = [];
4727
- for (const sentence of sentences) {
4776
+ for (const sentence of segments) {
4728
4777
  const type = inferCardType(sentence, row.tool_name);
4729
4778
  const subject = extractSubject(sentence, row.agent_id);
4730
- const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
4779
+ const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
4731
4780
  cards.push({
4732
4781
  id: stableId(row.id, type, content),
4733
4782
  memory_id: row.id,
@@ -4823,13 +4872,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
4823
4872
  last_accessed: String(row.timestamp)
4824
4873
  }));
4825
4874
  }
4826
- var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
4875
+ var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
4827
4876
  var init_memory_cards = __esm({
4828
4877
  "src/lib/memory-cards.ts"() {
4829
4878
  "use strict";
4830
4879
  init_database();
4831
- MAX_CARDS_PER_MEMORY = 6;
4832
- MAX_SENTENCE_CHARS = 360;
4880
+ MAX_CARDS_PER_MEMORY = 8;
4881
+ MAX_SEGMENT_CHARS = 500;
4882
+ MIN_SEGMENT_CHARS = 20;
4833
4883
  }
4834
4884
  });
4835
4885
 
@@ -7138,7 +7188,7 @@ async function hybridSearch(queryText, agentId, options) {
7138
7188
  try {
7139
7189
  const client = getClient();
7140
7190
  void client.execute({
7141
- sql: `UPDATE memories SET last_accessed = ?, retrieval_count = COALESCE(retrieval_count, 0) + 1 WHERE id IN (${placeholders})`,
7191
+ sql: `UPDATE memories SET last_accessed = ?, retrieval_count = COALESCE(retrieval_count, 0) + 1, strength = MIN(1.0, COALESCE(strength, 1.0) + 0.1) WHERE id IN (${placeholders})`,
7142
7192
  args: [now, ...ids]
7143
7193
  }).catch(() => {
7144
7194
  });