@askexenow/exe-os 0.9.268 → 0.9.270

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 (54) hide show
  1. package/deploy/compose/.env.customer.example +2 -0
  2. package/deploy/compose/.env.default +1 -0
  3. package/deploy/compose/.env.example +2 -0
  4. package/deploy/compose/docker-compose.yml +14 -6
  5. package/deploy/compose/generate-env.ts +5 -0
  6. package/deploy/compose/init-db.sql +236 -56
  7. package/dist/bin/cli.js +1 -1
  8. package/dist/bin/exe-forget.js +1 -1
  9. package/dist/bin/exe-new-employee.js +1 -1
  10. package/dist/bin/exe-search.js +1 -1
  11. package/dist/bin/exe-start.sh +28 -1
  12. package/dist/bin/install.js +1 -1
  13. package/dist/bin/setup.js +1 -1
  14. package/dist/bin/stack-update.js +2 -2
  15. package/dist/bin/vps-health-gate.js +1 -1
  16. package/dist/catchup-brief-7G3HIQT3.js +151 -0
  17. package/dist/catchup-brief-IA2K5RYM.js +151 -0
  18. package/dist/catchup-brief-KABFKY7U.js +151 -0
  19. package/dist/chunk-4GJHWD4H.js +1148 -0
  20. package/dist/chunk-6H7PZOYD.js +58 -0
  21. package/dist/chunk-AHVGHSWX.js +230 -0
  22. package/dist/chunk-AQU2CVD4.js +1148 -0
  23. package/dist/chunk-AX6EKVRZ.js +13696 -0
  24. package/dist/chunk-DFI2IZXM.js +1395 -0
  25. package/dist/chunk-EM4EYF3P.js +149 -0
  26. package/dist/chunk-F7RM3Z4R.js +230 -0
  27. package/dist/chunk-LMYSCMSQ.js +1148 -0
  28. package/dist/chunk-RJVFHGFD.js +13696 -0
  29. package/dist/chunk-U2O2UXVQ.js +13696 -0
  30. package/dist/chunk-UHKKI5MD.js +1391 -0
  31. package/dist/chunk-X56OLWQS.js +58 -0
  32. package/dist/chunk-YYO5RQRT.js +1021 -0
  33. package/dist/chunk-ZFHXFDWX.js +58 -0
  34. package/dist/hooks/error-recall.js +1 -1
  35. package/dist/hooks/manifest.json +4 -4
  36. package/dist/hooks/prompt-submit.js +1 -1
  37. package/dist/hooks/session-start.js +1 -1
  38. package/dist/lib/exe-daemon.js +49 -3
  39. package/dist/lib/hybrid-search.js +1 -1
  40. package/dist/lib/session-wrappers.js +1 -1
  41. package/dist/mcp/register-tools.js +3 -3
  42. package/dist/mcp/server.js +3 -3
  43. package/dist/reranker-7GCUQ6LC.js +19 -0
  44. package/dist/reranker-NLH3VBTN.js +19 -0
  45. package/dist/reranker-RUOD4YHZ.js +19 -0
  46. package/dist/setup-wizard-M7A7MXH4.js +12 -0
  47. package/dist/stack-update-MYPMZQEI.js +52 -0
  48. package/dist/stack-update-YJ433OLM.js +52 -0
  49. package/dist/task-enforcement-CJKWU43B.js +364 -0
  50. package/dist/task-enforcement-FYDLTS3R.js +391 -0
  51. package/dist/task-enforcement-YXKZYS5L.js +369 -0
  52. package/package.json +1 -1
  53. package/release-notes.json +57 -21
  54. package/stack.release.json +48 -48
package/dist/bin/cli.js CHANGED
@@ -344,7 +344,7 @@ ID: ${result.id}`);
344
344
  process.exit(1);
345
345
  }
346
346
  } else if (args[0] === "setup" || args[0] === "-setup" || args[0] === "--setup") {
347
- const { runSetupWizard } = await import("../setup-wizard-IZSKLVWW.js");
347
+ const { runSetupWizard } = await import("../setup-wizard-M7A7MXH4.js");
348
348
  await runSetupWizard({ skipModel: args.includes("--skip-model") });
349
349
  } else if (args[0] === "update") {
350
350
  const { runUpdate } = await import("./update.js");
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-M7GR2WO4.js";
5
5
  import {
6
6
  lightweightSearch
7
- } from "../chunk-HYI4PN4J.js";
7
+ } from "../chunk-LMYSCMSQ.js";
8
8
  import "../chunk-5MOYMGS5.js";
9
9
  import "../chunk-CHCA3ZM2.js";
10
10
  import "../chunk-RSIDQBIG.js";
@@ -13,7 +13,7 @@ import {
13
13
  } from "../chunk-7SLLNRR3.js";
14
14
  import {
15
15
  generateSessionWrappers
16
- } from "../chunk-GBCZXOWU.js";
16
+ } from "../chunk-EM4EYF3P.js";
17
17
  import {
18
18
  hireEmployee,
19
19
  registerBinSymlinks,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  hybridSearch,
4
4
  lightweightSearch
5
- } from "../chunk-HYI4PN4J.js";
5
+ } from "../chunk-LMYSCMSQ.js";
6
6
  import {
7
7
  initStore
8
8
  } from "../chunk-5MOYMGS5.js";
@@ -15,6 +15,29 @@ command -v tmux >/dev/null 2>&1 || { echo "exe-os requires tmux. Install: brew i
15
15
  command -v node >/dev/null 2>&1 || { echo "exe-os requires Node.js. Install: https://nodejs.org/"; exit 1; }
16
16
 
17
17
  ROSTER_PATH="${HOME}/.exe-os/exe-employees.json"
18
+ EXE_START_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
19
+
20
+ resolve_exe_os_bin() {
21
+ local found=""
22
+ found="$(command -v exe-os 2>/dev/null || true)"
23
+ if [ -n "$found" ]; then
24
+ printf '%s\n' "$found"
25
+ return 0
26
+ fi
27
+
28
+ local generated_bin_dir="__EXE_OS_BIN_DIR__"
29
+ if [ "$generated_bin_dir" != "__EXE_OS_BIN_DIR__" ] && [ -x "$generated_bin_dir/exe-os" ]; then
30
+ printf '%s\n' "$generated_bin_dir/exe-os"
31
+ return 0
32
+ fi
33
+
34
+ if [ -x "$EXE_START_DIR/exe-os" ]; then
35
+ printf '%s\n' "$EXE_START_DIR/exe-os"
36
+ return 0
37
+ fi
38
+
39
+ return 1
40
+ }
18
41
 
19
42
  # --- Parse wrapper name ---
20
43
  # Wrappers call: exec ~/.exe-os/bin/exe-start "$0" "$@"
@@ -109,7 +132,11 @@ fi
109
132
  # Fixes bug c79a0335: "exe-os update" intercepted by attach-only logic.
110
133
  case "${1:-}" in
111
134
  update|healthcheck|doctor|setup|support|key|stack-update|install|cloud|settings|version|backup)
112
- exec exe-os "$@"
135
+ EXE_OS_BIN="$(resolve_exe_os_bin)" || {
136
+ echo "exe-os binary not found. Add the npm global bin directory to PATH or reinstall exe-os."
137
+ exit 127
138
+ }
139
+ exec "$EXE_OS_BIN" "$@"
113
140
  ;;
114
141
  esac
115
142
 
@@ -10,7 +10,7 @@ import {
10
10
  import "../chunk-GNHN5HRQ.js";
11
11
  import {
12
12
  generateSessionWrappers
13
- } from "../chunk-GBCZXOWU.js";
13
+ } from "../chunk-EM4EYF3P.js";
14
14
  import "../chunk-L3TB7CC3.js";
15
15
  import "../chunk-HILKCYA4.js";
16
16
  import {
package/dist/bin/setup.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runSetupWizard
4
- } from "../chunk-6WKV4F6L.js";
4
+ } from "../chunk-YYO5RQRT.js";
5
5
  import "../chunk-K333WOW4.js";
6
6
  import "../chunk-VXIMSRTO.js";
7
7
  import "../chunk-LYH5HE24.js";
@@ -10,7 +10,7 @@ import {
10
10
  loadStackManifest,
11
11
  patchEnv,
12
12
  runStackUpdate
13
- } from "../chunk-2NIJORQE.js";
13
+ } from "../chunk-DFI2IZXM.js";
14
14
  import {
15
15
  runVerifyStack
16
16
  } from "../chunk-IRHNV4GY.js";
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  logResult,
22
22
  runHealthGate
23
- } from "../chunk-HGTXRRBK.js";
23
+ } from "../chunk-F7RM3Z4R.js";
24
24
  import "../chunk-MOZ2YQ54.js";
25
25
  import "../chunk-VXIMSRTO.js";
26
26
  import "../chunk-LYH5HE24.js";
@@ -8,7 +8,7 @@ import {
8
8
  logResult,
9
9
  main,
10
10
  runHealthGate
11
- } from "../chunk-HGTXRRBK.js";
11
+ } from "../chunk-F7RM3Z4R.js";
12
12
  import "../chunk-MLKGABMK.js";
13
13
  export {
14
14
  checkCRM,
@@ -0,0 +1,151 @@
1
+ import {
2
+ lightweightSearch
3
+ } from "./chunk-LMYSCMSQ.js";
4
+ import "./chunk-5MOYMGS5.js";
5
+ import "./chunk-CHCA3ZM2.js";
6
+ import "./chunk-RSIDQBIG.js";
7
+ import "./chunk-Y25OJWOQ.js";
8
+ import {
9
+ sessionScopeFilter,
10
+ strictSessionScopeFilter
11
+ } from "./chunk-BXY5Y3RI.js";
12
+ import "./chunk-SD6UFZRH.js";
13
+ import "./chunk-5CHYEKMH.js";
14
+ import "./chunk-4JERP7NT.js";
15
+ import "./chunk-GQ2XYRG3.js";
16
+ import "./chunk-MVW62NIZ.js";
17
+ import "./chunk-OYNKIAVW.js";
18
+ import "./chunk-CX6GL3ZJ.js";
19
+ import "./chunk-JP45GCVR.js";
20
+ import "./chunk-XJUUWHVN.js";
21
+ import "./chunk-NGP6LSV2.js";
22
+ import "./chunk-7SLLNRR3.js";
23
+ import "./chunk-CVYC6DUW.js";
24
+ import "./chunk-OPU3NYOO.js";
25
+ import "./chunk-GJV3WDWM.js";
26
+ import "./chunk-MP2AFCGL.js";
27
+ import "./chunk-TN45CTOI.js";
28
+ import "./chunk-HYZV25LY.js";
29
+ import {
30
+ getClient
31
+ } from "./chunk-UNCGZXPU.js";
32
+ import "./chunk-2I23RPSI.js";
33
+ import "./chunk-VGYL7CN2.js";
34
+ import "./chunk-FXU7JOXK.js";
35
+ import "./chunk-K333WOW4.js";
36
+ import "./chunk-MOZ2YQ54.js";
37
+ import "./chunk-VXIMSRTO.js";
38
+ import "./chunk-LYH5HE24.js";
39
+ import "./chunk-MLKGABMK.js";
40
+
41
+ // src/lib/catchup-brief.ts
42
+ import { execSync } from "child_process";
43
+ var HEADER = "## Catchup Brief\nHere's what happened while you were offline:";
44
+ var DEFAULT_LOOKBACK_MS = 60 * 60 * 1e3;
45
+ var MAX_BRIEF_CHARS = 2e3;
46
+ var MAX_CHECKPOINT_CHARS = 500;
47
+ var MAX_MESSAGE_CHARS = 100;
48
+ function clipText(text, maxChars) {
49
+ if (text.length <= maxChars) return text;
50
+ if (maxChars <= 1) return "\u2026";
51
+ return `${text.slice(0, maxChars - 1).trimEnd()}\u2026`;
52
+ }
53
+ function clampSections(header, sections, maxChars) {
54
+ const bounded = [];
55
+ let remaining = Math.max(0, maxChars - header.length);
56
+ for (const section of sections) {
57
+ const separatorChars = 2;
58
+ if (remaining <= separatorChars) break;
59
+ remaining -= separatorChars;
60
+ if (section.length <= remaining) {
61
+ bounded.push(section);
62
+ remaining -= section.length;
63
+ continue;
64
+ }
65
+ const clipped = clipText(section, remaining);
66
+ if (clipped.trim().length > 0) bounded.push(clipped);
67
+ break;
68
+ }
69
+ return bounded;
70
+ }
71
+ async function buildCatchupBrief(agentId, projectName, cwd, sessionScope) {
72
+ const sections = [];
73
+ let lastTimestamp = new Date(Date.now() - DEFAULT_LOOKBACK_MS).toISOString();
74
+ try {
75
+ const checkpointMemories = await lightweightSearch(
76
+ "CONTEXT CHECKPOINT",
77
+ agentId,
78
+ { projectName, limit: 1 }
79
+ );
80
+ const checkpoint = checkpointMemories[0];
81
+ if (checkpoint?.timestamp) {
82
+ lastTimestamp = checkpoint.timestamp;
83
+ }
84
+ if (checkpoint?.raw_text) {
85
+ sections.push(
86
+ `### Last Checkpoint
87
+ ${clipText(checkpoint.raw_text, MAX_CHECKPOINT_CHARS)}`
88
+ );
89
+ }
90
+ } catch {
91
+ }
92
+ try {
93
+ const gitLog = execSync(
94
+ `git log --oneline --since=${JSON.stringify(lastTimestamp)} --format="%h %an: %s" | head -10`,
95
+ { cwd, timeout: 3e3, encoding: "utf-8" }
96
+ ).trim();
97
+ if (gitLog) {
98
+ sections.push(`### Git Activity Since You Left
99
+ \`\`\`
100
+ ${gitLog}
101
+ \`\`\``);
102
+ }
103
+ } catch {
104
+ }
105
+ try {
106
+ const client = getClient();
107
+ const taskScope = sessionScopeFilter(sessionScope);
108
+ const taskChanges = await client.execute({
109
+ sql: `SELECT title, status, priority FROM tasks
110
+ WHERE assigned_to = ? AND project_name = ?
111
+ AND updated_at > ? AND status IN ('open', 'in_progress')${taskScope.sql}
112
+ ORDER BY priority ASC, updated_at DESC LIMIT 5`,
113
+ args: [agentId, projectName, lastTimestamp, ...taskScope.args]
114
+ });
115
+ if (taskChanges.rows.length > 0) {
116
+ const taskLines = taskChanges.rows.map((row) => {
117
+ const record = row;
118
+ return `- [${String(record.priority).toUpperCase()}] ${String(record.title)} (${String(record.status)})`;
119
+ }).join("\n");
120
+ sections.push(`### Your Task Queue
121
+ ${taskLines}`);
122
+ }
123
+ } catch {
124
+ }
125
+ try {
126
+ const client = getClient();
127
+ const messageScope = strictSessionScopeFilter(sessionScope);
128
+ const messages = await client.execute({
129
+ sql: `SELECT from_agent, content, created_at FROM messages
130
+ WHERE target_agent = ? AND status = 'pending'${messageScope.sql}
131
+ ORDER BY created_at DESC LIMIT 3`,
132
+ args: [agentId, ...messageScope.args]
133
+ });
134
+ if (messages.rows.length > 0) {
135
+ const msgLines = messages.rows.map((row) => {
136
+ const record = row;
137
+ return `- From ${String(record.from_agent)}: ${clipText(String(record.content ?? ""), MAX_MESSAGE_CHARS)}`;
138
+ }).join("\n");
139
+ sections.push(`### Unread Messages
140
+ ${msgLines}`);
141
+ }
142
+ } catch {
143
+ }
144
+ return {
145
+ header: HEADER,
146
+ sections: clampSections(HEADER, sections, MAX_BRIEF_CHARS)
147
+ };
148
+ }
149
+ export {
150
+ buildCatchupBrief
151
+ };
@@ -0,0 +1,151 @@
1
+ import {
2
+ lightweightSearch
3
+ } from "./chunk-AQU2CVD4.js";
4
+ import "./chunk-5MOYMGS5.js";
5
+ import "./chunk-CHCA3ZM2.js";
6
+ import "./chunk-RSIDQBIG.js";
7
+ import "./chunk-Y25OJWOQ.js";
8
+ import {
9
+ sessionScopeFilter,
10
+ strictSessionScopeFilter
11
+ } from "./chunk-BXY5Y3RI.js";
12
+ import "./chunk-SD6UFZRH.js";
13
+ import "./chunk-5CHYEKMH.js";
14
+ import "./chunk-4JERP7NT.js";
15
+ import "./chunk-GQ2XYRG3.js";
16
+ import "./chunk-MVW62NIZ.js";
17
+ import "./chunk-OYNKIAVW.js";
18
+ import "./chunk-CX6GL3ZJ.js";
19
+ import "./chunk-JP45GCVR.js";
20
+ import "./chunk-XJUUWHVN.js";
21
+ import "./chunk-NGP6LSV2.js";
22
+ import "./chunk-7SLLNRR3.js";
23
+ import "./chunk-CVYC6DUW.js";
24
+ import "./chunk-OPU3NYOO.js";
25
+ import "./chunk-GJV3WDWM.js";
26
+ import "./chunk-MP2AFCGL.js";
27
+ import "./chunk-TN45CTOI.js";
28
+ import "./chunk-HYZV25LY.js";
29
+ import {
30
+ getClient
31
+ } from "./chunk-UNCGZXPU.js";
32
+ import "./chunk-2I23RPSI.js";
33
+ import "./chunk-VGYL7CN2.js";
34
+ import "./chunk-FXU7JOXK.js";
35
+ import "./chunk-K333WOW4.js";
36
+ import "./chunk-MOZ2YQ54.js";
37
+ import "./chunk-VXIMSRTO.js";
38
+ import "./chunk-LYH5HE24.js";
39
+ import "./chunk-MLKGABMK.js";
40
+
41
+ // src/lib/catchup-brief.ts
42
+ import { execSync } from "child_process";
43
+ var HEADER = "## Catchup Brief\nHere's what happened while you were offline:";
44
+ var DEFAULT_LOOKBACK_MS = 60 * 60 * 1e3;
45
+ var MAX_BRIEF_CHARS = 2e3;
46
+ var MAX_CHECKPOINT_CHARS = 500;
47
+ var MAX_MESSAGE_CHARS = 100;
48
+ function clipText(text, maxChars) {
49
+ if (text.length <= maxChars) return text;
50
+ if (maxChars <= 1) return "\u2026";
51
+ return `${text.slice(0, maxChars - 1).trimEnd()}\u2026`;
52
+ }
53
+ function clampSections(header, sections, maxChars) {
54
+ const bounded = [];
55
+ let remaining = Math.max(0, maxChars - header.length);
56
+ for (const section of sections) {
57
+ const separatorChars = 2;
58
+ if (remaining <= separatorChars) break;
59
+ remaining -= separatorChars;
60
+ if (section.length <= remaining) {
61
+ bounded.push(section);
62
+ remaining -= section.length;
63
+ continue;
64
+ }
65
+ const clipped = clipText(section, remaining);
66
+ if (clipped.trim().length > 0) bounded.push(clipped);
67
+ break;
68
+ }
69
+ return bounded;
70
+ }
71
+ async function buildCatchupBrief(agentId, projectName, cwd, sessionScope) {
72
+ const sections = [];
73
+ let lastTimestamp = new Date(Date.now() - DEFAULT_LOOKBACK_MS).toISOString();
74
+ try {
75
+ const checkpointMemories = await lightweightSearch(
76
+ "CONTEXT CHECKPOINT",
77
+ agentId,
78
+ { projectName, limit: 1 }
79
+ );
80
+ const checkpoint = checkpointMemories[0];
81
+ if (checkpoint?.timestamp) {
82
+ lastTimestamp = checkpoint.timestamp;
83
+ }
84
+ if (checkpoint?.raw_text) {
85
+ sections.push(
86
+ `### Last Checkpoint
87
+ ${clipText(checkpoint.raw_text, MAX_CHECKPOINT_CHARS)}`
88
+ );
89
+ }
90
+ } catch {
91
+ }
92
+ try {
93
+ const gitLog = execSync(
94
+ `git log --oneline --since=${JSON.stringify(lastTimestamp)} --format="%h %an: %s" | head -10`,
95
+ { cwd, timeout: 3e3, encoding: "utf-8" }
96
+ ).trim();
97
+ if (gitLog) {
98
+ sections.push(`### Git Activity Since You Left
99
+ \`\`\`
100
+ ${gitLog}
101
+ \`\`\``);
102
+ }
103
+ } catch {
104
+ }
105
+ try {
106
+ const client = getClient();
107
+ const taskScope = sessionScopeFilter(sessionScope);
108
+ const taskChanges = await client.execute({
109
+ sql: `SELECT title, status, priority FROM tasks
110
+ WHERE assigned_to = ? AND project_name = ?
111
+ AND updated_at > ? AND status IN ('open', 'in_progress')${taskScope.sql}
112
+ ORDER BY priority ASC, updated_at DESC LIMIT 5`,
113
+ args: [agentId, projectName, lastTimestamp, ...taskScope.args]
114
+ });
115
+ if (taskChanges.rows.length > 0) {
116
+ const taskLines = taskChanges.rows.map((row) => {
117
+ const record = row;
118
+ return `- [${String(record.priority).toUpperCase()}] ${String(record.title)} (${String(record.status)})`;
119
+ }).join("\n");
120
+ sections.push(`### Your Task Queue
121
+ ${taskLines}`);
122
+ }
123
+ } catch {
124
+ }
125
+ try {
126
+ const client = getClient();
127
+ const messageScope = strictSessionScopeFilter(sessionScope);
128
+ const messages = await client.execute({
129
+ sql: `SELECT from_agent, content, created_at FROM messages
130
+ WHERE target_agent = ? AND status = 'pending'${messageScope.sql}
131
+ ORDER BY created_at DESC LIMIT 3`,
132
+ args: [agentId, ...messageScope.args]
133
+ });
134
+ if (messages.rows.length > 0) {
135
+ const msgLines = messages.rows.map((row) => {
136
+ const record = row;
137
+ return `- From ${String(record.from_agent)}: ${clipText(String(record.content ?? ""), MAX_MESSAGE_CHARS)}`;
138
+ }).join("\n");
139
+ sections.push(`### Unread Messages
140
+ ${msgLines}`);
141
+ }
142
+ } catch {
143
+ }
144
+ return {
145
+ header: HEADER,
146
+ sections: clampSections(HEADER, sections, MAX_BRIEF_CHARS)
147
+ };
148
+ }
149
+ export {
150
+ buildCatchupBrief
151
+ };
@@ -0,0 +1,151 @@
1
+ import {
2
+ lightweightSearch
3
+ } from "./chunk-4GJHWD4H.js";
4
+ import "./chunk-5MOYMGS5.js";
5
+ import "./chunk-CHCA3ZM2.js";
6
+ import "./chunk-RSIDQBIG.js";
7
+ import "./chunk-Y25OJWOQ.js";
8
+ import {
9
+ sessionScopeFilter,
10
+ strictSessionScopeFilter
11
+ } from "./chunk-BXY5Y3RI.js";
12
+ import "./chunk-SD6UFZRH.js";
13
+ import "./chunk-5CHYEKMH.js";
14
+ import "./chunk-4JERP7NT.js";
15
+ import "./chunk-GQ2XYRG3.js";
16
+ import "./chunk-MVW62NIZ.js";
17
+ import "./chunk-OYNKIAVW.js";
18
+ import "./chunk-CX6GL3ZJ.js";
19
+ import "./chunk-JP45GCVR.js";
20
+ import "./chunk-XJUUWHVN.js";
21
+ import "./chunk-NGP6LSV2.js";
22
+ import "./chunk-7SLLNRR3.js";
23
+ import "./chunk-CVYC6DUW.js";
24
+ import "./chunk-OPU3NYOO.js";
25
+ import "./chunk-GJV3WDWM.js";
26
+ import "./chunk-MP2AFCGL.js";
27
+ import "./chunk-TN45CTOI.js";
28
+ import "./chunk-HYZV25LY.js";
29
+ import {
30
+ getClient
31
+ } from "./chunk-UNCGZXPU.js";
32
+ import "./chunk-2I23RPSI.js";
33
+ import "./chunk-VGYL7CN2.js";
34
+ import "./chunk-FXU7JOXK.js";
35
+ import "./chunk-K333WOW4.js";
36
+ import "./chunk-MOZ2YQ54.js";
37
+ import "./chunk-VXIMSRTO.js";
38
+ import "./chunk-LYH5HE24.js";
39
+ import "./chunk-MLKGABMK.js";
40
+
41
+ // src/lib/catchup-brief.ts
42
+ import { execSync } from "child_process";
43
+ var HEADER = "## Catchup Brief\nHere's what happened while you were offline:";
44
+ var DEFAULT_LOOKBACK_MS = 60 * 60 * 1e3;
45
+ var MAX_BRIEF_CHARS = 2e3;
46
+ var MAX_CHECKPOINT_CHARS = 500;
47
+ var MAX_MESSAGE_CHARS = 100;
48
+ function clipText(text, maxChars) {
49
+ if (text.length <= maxChars) return text;
50
+ if (maxChars <= 1) return "\u2026";
51
+ return `${text.slice(0, maxChars - 1).trimEnd()}\u2026`;
52
+ }
53
+ function clampSections(header, sections, maxChars) {
54
+ const bounded = [];
55
+ let remaining = Math.max(0, maxChars - header.length);
56
+ for (const section of sections) {
57
+ const separatorChars = 2;
58
+ if (remaining <= separatorChars) break;
59
+ remaining -= separatorChars;
60
+ if (section.length <= remaining) {
61
+ bounded.push(section);
62
+ remaining -= section.length;
63
+ continue;
64
+ }
65
+ const clipped = clipText(section, remaining);
66
+ if (clipped.trim().length > 0) bounded.push(clipped);
67
+ break;
68
+ }
69
+ return bounded;
70
+ }
71
+ async function buildCatchupBrief(agentId, projectName, cwd, sessionScope) {
72
+ const sections = [];
73
+ let lastTimestamp = new Date(Date.now() - DEFAULT_LOOKBACK_MS).toISOString();
74
+ try {
75
+ const checkpointMemories = await lightweightSearch(
76
+ "CONTEXT CHECKPOINT",
77
+ agentId,
78
+ { projectName, limit: 1 }
79
+ );
80
+ const checkpoint = checkpointMemories[0];
81
+ if (checkpoint?.timestamp) {
82
+ lastTimestamp = checkpoint.timestamp;
83
+ }
84
+ if (checkpoint?.raw_text) {
85
+ sections.push(
86
+ `### Last Checkpoint
87
+ ${clipText(checkpoint.raw_text, MAX_CHECKPOINT_CHARS)}`
88
+ );
89
+ }
90
+ } catch {
91
+ }
92
+ try {
93
+ const gitLog = execSync(
94
+ `git log --oneline --since=${JSON.stringify(lastTimestamp)} --format="%h %an: %s" | head -10`,
95
+ { cwd, timeout: 3e3, encoding: "utf-8" }
96
+ ).trim();
97
+ if (gitLog) {
98
+ sections.push(`### Git Activity Since You Left
99
+ \`\`\`
100
+ ${gitLog}
101
+ \`\`\``);
102
+ }
103
+ } catch {
104
+ }
105
+ try {
106
+ const client = getClient();
107
+ const taskScope = sessionScopeFilter(sessionScope);
108
+ const taskChanges = await client.execute({
109
+ sql: `SELECT title, status, priority FROM tasks
110
+ WHERE assigned_to = ? AND project_name = ?
111
+ AND updated_at > ? AND status IN ('open', 'in_progress')${taskScope.sql}
112
+ ORDER BY priority ASC, updated_at DESC LIMIT 5`,
113
+ args: [agentId, projectName, lastTimestamp, ...taskScope.args]
114
+ });
115
+ if (taskChanges.rows.length > 0) {
116
+ const taskLines = taskChanges.rows.map((row) => {
117
+ const record = row;
118
+ return `- [${String(record.priority).toUpperCase()}] ${String(record.title)} (${String(record.status)})`;
119
+ }).join("\n");
120
+ sections.push(`### Your Task Queue
121
+ ${taskLines}`);
122
+ }
123
+ } catch {
124
+ }
125
+ try {
126
+ const client = getClient();
127
+ const messageScope = strictSessionScopeFilter(sessionScope);
128
+ const messages = await client.execute({
129
+ sql: `SELECT from_agent, content, created_at FROM messages
130
+ WHERE target_agent = ? AND status = 'pending'${messageScope.sql}
131
+ ORDER BY created_at DESC LIMIT 3`,
132
+ args: [agentId, ...messageScope.args]
133
+ });
134
+ if (messages.rows.length > 0) {
135
+ const msgLines = messages.rows.map((row) => {
136
+ const record = row;
137
+ return `- From ${String(record.from_agent)}: ${clipText(String(record.content ?? ""), MAX_MESSAGE_CHARS)}`;
138
+ }).join("\n");
139
+ sections.push(`### Unread Messages
140
+ ${msgLines}`);
141
+ }
142
+ } catch {
143
+ }
144
+ return {
145
+ header: HEADER,
146
+ sections: clampSections(HEADER, sections, MAX_BRIEF_CHARS)
147
+ };
148
+ }
149
+ export {
150
+ buildCatchupBrief
151
+ };