@askexenow/exe-os 0.9.269 → 0.9.271

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 (55) 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 +1 -0
  5. package/deploy/compose/generate-env.ts +5 -0
  6. package/deploy/compose/init-db.sql +236 -56
  7. package/dist/bin/cli.js +2 -2
  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 +10 -3
  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-AQU2CVD4.js +1148 -0
  22. package/dist/chunk-AX6EKVRZ.js +13696 -0
  23. package/dist/chunk-DFI2IZXM.js +1395 -0
  24. package/dist/chunk-EM4EYF3P.js +149 -0
  25. package/dist/chunk-F7RM3Z4R.js +230 -0
  26. package/dist/chunk-IBMTSEZC.js +230 -0
  27. package/dist/chunk-LMYSCMSQ.js +1148 -0
  28. package/dist/chunk-O7YO7E2G.js +1512 -0
  29. package/dist/chunk-RJVFHGFD.js +13696 -0
  30. package/dist/chunk-U2O2UXVQ.js +13696 -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-release-2KSOYDIV.js +712 -0
  48. package/dist/stack-update-MYPMZQEI.js +52 -0
  49. package/dist/stack-update-QQA64STQ.js +52 -0
  50. package/dist/task-enforcement-CJKWU43B.js +364 -0
  51. package/dist/task-enforcement-FYDLTS3R.js +391 -0
  52. package/dist/task-enforcement-YXKZYS5L.js +369 -0
  53. package/package.json +1 -1
  54. package/release-notes.json +14 -14
  55. package/stack.release.json +48 -48
@@ -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-UHKKI5MD.js";
13
+ } from "../chunk-O7YO7E2G.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-AHVGHSWX.js";
23
+ } from "../chunk-IBMTSEZC.js";
24
24
  import "../chunk-MOZ2YQ54.js";
25
25
  import "../chunk-VXIMSRTO.js";
26
26
  import "../chunk-LYH5HE24.js";
@@ -357,6 +357,7 @@ function parseArgs(args) {
357
357
  dryRun: false,
358
358
  check: false,
359
359
  rollback: false,
360
+ resume: false,
360
361
  deploymentPersona: process.env.EXE_STACK_DEPLOYMENT_PERSONA === "askexe-control-plane" ? "askexe-control-plane" : "customer",
361
362
  yes: false,
362
363
  allowedBreakingChangeIds: [],
@@ -371,6 +372,9 @@ function parseArgs(args) {
371
372
  else if (arg === "--target" || arg === "--to") opts.targetVersion = next();
372
373
  else if (arg.startsWith("--target=")) opts.targetVersion = arg.split("=")[1];
373
374
  else if (arg.startsWith("--to=")) opts.targetVersion = arg.split("=")[1];
375
+ else if (arg === "--service") opts.serviceName = next();
376
+ else if (arg.startsWith("--service=")) opts.serviceName = arg.split("=").slice(1).join("=");
377
+ else if (arg === "--resume") opts.resume = true;
374
378
  else if (arg === "--compose-file") opts.composeFile = next();
375
379
  else if (arg.startsWith("--compose-file=")) opts.composeFile = arg.split("=").slice(1).join("=");
376
380
  else if (arg === "--env-file" || arg === "--stack-env-file") opts.envFile = next();
@@ -439,6 +443,8 @@ Options:
439
443
  --manifest <ref> Stack manifest JSON path or URL (default: update.askexe.com)
440
444
  --to, --target <version> Stack version to install (default: stay on installed version;
441
445
  uses manifest.latest only on first install)
446
+ --service <name> Update one manifest/compose service only
447
+ --resume Resume a failed update from lock state; retries only incomplete services
442
448
  --compose-file <path> docker-compose.yml path (default: ./docker-compose.yml or /opt/exe-stack/docker-compose.yml)
443
449
  --stack-env-file <path> .env path (default: ./.env or /opt/exe-stack/.env)
444
450
  --env-file <path> Alias; prefer --stack-env-file because Node 22 reserves --env-file
@@ -641,7 +647,7 @@ async function main(args = process.argv.slice(2)) {
641
647
  const lockFile = opts.lockFile ?? path2.join(path2.dirname(opts.envFile), ".exe-stack-lock.json");
642
648
  const installedVersion = readInstalledVersion(lockFile);
643
649
  const effectiveTarget = opts.targetVersion ?? installedVersion;
644
- const plan = createStackUpdatePlan(manifest, envRaw, effectiveTarget);
650
+ const plan = createStackUpdatePlan(manifest, envRaw, effectiveTarget, opts.serviceName ? [opts.serviceName] : void 0);
645
651
  assertDeploymentScopeAllowed(plan, opts.deploymentPersona);
646
652
  const plannedEnvRaw = patchEnv(envRaw, Object.fromEntries(plan.changes.map((c) => [c.key, c.after])));
647
653
  assertProductionDeployGate(plan, plannedEnvRaw, readFileSync2(opts.composeFile, "utf8"), {
@@ -721,5 +727,6 @@ if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("stack-upd
721
727
  });
722
728
  }
723
729
  export {
730
+ parseArgs as parseStackUpdateArgs,
724
731
  main as runStackUpdateCli
725
732
  };
@@ -8,7 +8,7 @@ import {
8
8
  logResult,
9
9
  main,
10
10
  runHealthGate
11
- } from "../chunk-AHVGHSWX.js";
11
+ } from "../chunk-IBMTSEZC.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
+ };