@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.
- package/deploy/compose/.env.customer.example +2 -0
- package/deploy/compose/.env.default +1 -0
- package/deploy/compose/.env.example +2 -0
- package/deploy/compose/docker-compose.yml +14 -6
- package/deploy/compose/generate-env.ts +5 -0
- package/deploy/compose/init-db.sql +236 -56
- package/dist/bin/cli.js +1 -1
- package/dist/bin/exe-forget.js +1 -1
- package/dist/bin/exe-new-employee.js +1 -1
- package/dist/bin/exe-search.js +1 -1
- package/dist/bin/exe-start.sh +28 -1
- package/dist/bin/install.js +1 -1
- package/dist/bin/setup.js +1 -1
- package/dist/bin/stack-update.js +2 -2
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/catchup-brief-7G3HIQT3.js +151 -0
- package/dist/catchup-brief-IA2K5RYM.js +151 -0
- package/dist/catchup-brief-KABFKY7U.js +151 -0
- package/dist/chunk-4GJHWD4H.js +1148 -0
- package/dist/chunk-6H7PZOYD.js +58 -0
- package/dist/chunk-AHVGHSWX.js +230 -0
- package/dist/chunk-AQU2CVD4.js +1148 -0
- package/dist/chunk-AX6EKVRZ.js +13696 -0
- package/dist/chunk-DFI2IZXM.js +1395 -0
- package/dist/chunk-EM4EYF3P.js +149 -0
- package/dist/chunk-F7RM3Z4R.js +230 -0
- package/dist/chunk-LMYSCMSQ.js +1148 -0
- package/dist/chunk-RJVFHGFD.js +13696 -0
- package/dist/chunk-U2O2UXVQ.js +13696 -0
- package/dist/chunk-UHKKI5MD.js +1391 -0
- package/dist/chunk-X56OLWQS.js +58 -0
- package/dist/chunk-YYO5RQRT.js +1021 -0
- package/dist/chunk-ZFHXFDWX.js +58 -0
- package/dist/hooks/error-recall.js +1 -1
- package/dist/hooks/manifest.json +4 -4
- package/dist/hooks/prompt-submit.js +1 -1
- package/dist/hooks/session-start.js +1 -1
- package/dist/lib/exe-daemon.js +49 -3
- package/dist/lib/hybrid-search.js +1 -1
- package/dist/lib/session-wrappers.js +1 -1
- package/dist/mcp/register-tools.js +3 -3
- package/dist/mcp/server.js +3 -3
- package/dist/reranker-7GCUQ6LC.js +19 -0
- package/dist/reranker-NLH3VBTN.js +19 -0
- package/dist/reranker-RUOD4YHZ.js +19 -0
- package/dist/setup-wizard-M7A7MXH4.js +12 -0
- package/dist/stack-update-MYPMZQEI.js +52 -0
- package/dist/stack-update-YJ433OLM.js +52 -0
- package/dist/task-enforcement-CJKWU43B.js +364 -0
- package/dist/task-enforcement-FYDLTS3R.js +391 -0
- package/dist/task-enforcement-YXKZYS5L.js +369 -0
- package/package.json +1 -1
- package/release-notes.json +57 -21
- 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-
|
|
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");
|
package/dist/bin/exe-forget.js
CHANGED
package/dist/bin/exe-search.js
CHANGED
package/dist/bin/exe-start.sh
CHANGED
|
@@ -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
|
-
|
|
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
|
|
package/dist/bin/install.js
CHANGED
package/dist/bin/setup.js
CHANGED
package/dist/bin/stack-update.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadStackManifest,
|
|
11
11
|
patchEnv,
|
|
12
12
|
runStackUpdate
|
|
13
|
-
} from "../chunk-
|
|
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-
|
|
23
|
+
} from "../chunk-F7RM3Z4R.js";
|
|
24
24
|
import "../chunk-MOZ2YQ54.js";
|
|
25
25
|
import "../chunk-VXIMSRTO.js";
|
|
26
26
|
import "../chunk-LYH5HE24.js";
|
|
@@ -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
|
+
};
|