@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.
- 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 +1 -0
- package/deploy/compose/generate-env.ts +5 -0
- package/deploy/compose/init-db.sql +236 -56
- package/dist/bin/cli.js +2 -2
- 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 +10 -3
- 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-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-IBMTSEZC.js +230 -0
- package/dist/chunk-LMYSCMSQ.js +1148 -0
- package/dist/chunk-O7YO7E2G.js +1512 -0
- package/dist/chunk-RJVFHGFD.js +13696 -0
- package/dist/chunk-U2O2UXVQ.js +13696 -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-release-2KSOYDIV.js +712 -0
- package/dist/stack-update-MYPMZQEI.js +52 -0
- package/dist/stack-update-QQA64STQ.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 +14 -14
- package/stack.release.json +48 -48
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-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-
|
|
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
|
};
|
|
@@ -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
|
+
};
|