@sema-agent/core
Version:
Stateless, task-oriented AI agent core
239 lines (238 loc) • 11.2 kB
JavaScript
import { createHash } from "node:crypto";
import { GIT_SNAPSHOT_CC_PREAMBLE, buildGitSnapshot } from "../../prompts/default.js";
import { inlineUntrusted } from "../untrusted-text.js";
import { openSystemReminder } from "../reminder-mint.js";
import { engineRegionCovers, protectGitFrame } from "../context-guard.js";
import { gitFrameContextVisible } from "../../internal/harness.js";
import { thrownText } from "../thrown-value.js";
export const GIT_STATUS_FRAME_FORMAT_VERSION = 1;
export const GIT_STATUS_FRAME_PREAMBLE = "This is the git status observed while preparing this request. When the visible snapshot changes it will be re-sent in a later message — the most recent git status frame supersedes earlier ones.";
export const GIT_STATUS_UNAVAILABLE_BODY = "Git status is currently unavailable; the most recent git status frame above may be stale.";
export const GIT_STATUS_NON_REPO_BODY = "The working directory is no longer a git repository; earlier git status frames no longer apply.";
export const GIT_STATUS_ECHO_PREVIEW = {
full: "git status updated",
degraded: "git status updated (degraded: branch and dirtiness only)",
unavailable: "git status unavailable",
"non-repo": "git status: no longer a git repository",
};
function toWellFormedText(s) {
const native = s.toWellFormed;
if (typeof native === "function")
return native.call(s);
return s.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "�");
}
export function renderGitStatusFrameBody(outcome) {
switch (outcome.kind) {
case "full": {
const body = outcome.snapshot.startsWith(GIT_SNAPSHOT_CC_PREAMBLE)
? GIT_STATUS_FRAME_PREAMBLE + outcome.snapshot.slice(GIT_SNAPSHOT_CC_PREAMBLE.length)
: `${GIT_STATUS_FRAME_PREAMBLE}\n\n${outcome.snapshot}`;
return toWellFormedText(body);
}
case "degraded": {
const lines = [GIT_STATUS_FRAME_PREAMBLE];
lines.push(`Current branch: ${inlineUntrusted(outcome.branch ?? "HEAD")}`);
if (outcome.dirty !== undefined) {
lines.push(`Git working tree: ${outcome.dirty ? "has uncommitted changes" : "clean"}`);
}
return toWellFormedText(lines.join("\n\n"));
}
case "unavailable":
return GIT_STATUS_UNAVAILABLE_BODY;
case "non-repo":
return GIT_STATUS_NON_REPO_BODY;
}
}
export function hashGitStatusFrame(kind, body, canonicalRoot) {
return `sha256:${createHash("sha256")
.update(`${GIT_STATUS_FRAME_FORMAT_VERSION}\u0000${canonicalRoot}\u0000${kind}\u0000${body}`)
.digest("hex")}`;
}
export function resolveGitStatusFrame(outcome, canonicalRoot, degradedMaterial) {
const body = renderGitStatusFrameBody(outcome);
const resolved = {
kind: outcome.kind,
body,
hash: hashGitStatusFrame(outcome.kind, body, canonicalRoot),
};
if (outcome.kind === "full") {
const shrunkBody = renderGitStatusFrameBody({ kind: "degraded", ...(degradedMaterial ?? {}) });
resolved.shrunk = { body: shrunkBody, hash: hashGitStatusFrame("degraded", shrunkBody, canonicalRoot) };
}
return resolved;
}
export async function probeGitStatusLane(args) {
const { executionEnv, envFacts, handsEnabled, taskRoot, onDegrade } = args;
const ref = {};
if (!handsEnabled)
return ref;
let outcome;
if (envFacts.isGitRepo === true) {
const SEP = "@@SEMA_ENV_GIT_SPLIT@@";
outcome = {
kind: "degraded",
...(envFacts.gitBranch !== undefined ? { branch: envFacts.gitBranch } : {}),
...(envFacts.gitDirty !== undefined ? { dirty: envFacts.gitDirty } : {}),
};
try {
const snap = await executionEnv.exec(`(m=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null); m=\${m#origin/}; for s in "$m" main master; do if [ -n "$s" ] && git show-ref --verify --quiet "refs/remotes/origin/$s"; then echo "$s"; break; fi; done) || true; echo "${SEP}"; (git config user.name 2>/dev/null || true); echo "${SEP}"; gs=$(git --no-optional-locks status --short) || exit 41; printf '%s\\n' "$gs"; echo "${SEP}"; gl=$(git --no-optional-locks log --oneline -n 5) || exit 42; printf '%s\\n' "$gl"`, { cwd: envFacts.cwd, timeout: 10 });
if (snap.ok && snap.value.exitCode === 0) {
const parts = snap.value.stdout.split(`${SEP}\n`);
if (parts.length === 4) {
outcome = {
kind: "full",
snapshot: buildGitSnapshot({
branch: envFacts.gitBranch ?? "HEAD",
mainBranch: parts[0].trim() || "main",
...(parts[1].trim() ? { userName: parts[1].trim() } : {}),
status: parts[2],
log: parts[3],
}),
};
}
else {
onDegrade(`sentinel mis-split (${parts.length} sections, expected 4)`);
}
}
else {
onDegrade(snap.ok
? snap.value.exitCode === 41
? "git status failed (exit 41)"
: snap.value.exitCode === 42
? "git log failed (exit 42)"
: `git exited ${snap.value.exitCode}`
: `exec failed: ${snap.error.message}`);
}
}
catch (err) {
onDegrade(thrownText(err));
}
}
else if (envFacts.isGitRepo === false) {
outcome = { kind: "non-repo" };
}
else {
outcome = { kind: "unavailable" };
}
const rootRaw = envFacts.gitWorktreeRoot ?? envFacts.cwd ?? taskRoot;
let canonicalRoot = rootRaw;
try {
const c = await executionEnv.canonicalPath(rootRaw);
if (c.ok)
canonicalRoot = c.value;
}
catch {
}
ref.canonicalRoot = canonicalRoot;
ref.frame = resolveGitStatusFrame(outcome, canonicalRoot, {
...(envFacts.gitBranch !== undefined ? { branch: envFacts.gitBranch } : {}),
...(envFacts.gitDirty !== undefined ? { dirty: envFacts.gitDirty } : {}),
});
return ref;
}
export function applyGitFrameGuard(args) {
const { before, trimmed, budgetTokens, ref, charsPerToken, onDegrade } = args;
if (ref.protectedText === undefined)
return trimmed;
const guarded = protectGitFrame(before, trimmed, budgetTokens, {
protectedText: ref.protectedText,
...(ref.frame?.kind === "full" && ref.frame.shrunk !== undefined && ref.wrappedShrink !== undefined ? { substitute: ref.wrappedShrink } : {}),
}, charsPerToken);
if (guarded.action === "over_budget") {
ref.terminalCode = "irreducible_core_over_budget";
throw Object.assign(new Error("irreducible core over budget: the compaction summary plus the git status frame alone exceed the request budget — no trim can produce an honest request"), { code: "irreducible_core_over_budget" });
}
if (guarded.action === "shrunk" && !ref.overBudgetShrunk) {
ref.overBudgetShrunk = true;
if (ref.announced !== undefined)
ref.announced = { ...ref.announced, pending: true };
onDegrade("git status frame degraded under budget pressure: the full snapshot no longer fits the request budget — requests carry the branch+dirty residual; the degraded view will be re-announced");
}
return guarded.messages;
}
export function newestEngineGitFrame(branch, mark) {
const heads = [`${openSystemReminder(undefined)}\n${GIT_STATUS_FRAME_PREAMBLE}`, ...(mark !== undefined ? [`${openSystemReminder(mark)}\n${GIT_STATUS_FRAME_PREAMBLE}`] : [])];
const tombUnits = [GIT_STATUS_UNAVAILABLE_BODY, GIT_STATUS_NON_REPO_BODY].flatMap((body) => [
`${openSystemReminder(undefined)}\n${body}\n</system-reminder>`,
...(mark !== undefined ? [`${openSystemReminder(mark)}\n${body}\n</system-reminder>`] : []),
]);
const topLevel = (text, at) => {
if (at === 0)
return true;
const before = text.slice(0, at).replace(/\n+$/, "");
return before === "" || before.endsWith("</system-reminder>");
};
const allTopLevel = (text, needle, m) => {
const out = [];
for (let at = text.indexOf(needle); at !== -1; at = text.indexOf(needle, at + 1)) {
if (topLevel(text, at) && engineRegionCovers(m, at, needle.length))
out.push(at);
}
return out;
};
for (let i = branch.length - 1; i >= 0; i--) {
const entry = branch[i];
if (entry === undefined || entry.type !== "message")
continue;
const m = entry.message;
if (m.role !== "user")
continue;
const c = m.content;
const text = typeof c === "string" ? c : Array.isArray(c) && c.length >= 1 && c[0].type === "text" ? (c[0].text ?? "") : undefined;
if (text === undefined)
continue;
let best;
for (const head of heads) {
for (const at of allTopLevel(text, head, m)) {
if (best === undefined || at > best.at)
best = { at, positive: true };
}
}
for (const unit of tombUnits) {
for (const at of allTopLevel(text, unit, m)) {
if (best === undefined || at > best.at)
best = { at, positive: false };
}
}
if (best !== undefined)
return { entryId: entry.id, positive: best.positive };
}
return undefined;
}
function hasNestedReminderOpenTag(seg) {
const name = "<system-reminder";
for (let i = seg.indexOf(name); i !== -1; i = seg.indexOf(name, i + 1)) {
const c = seg[i + name.length];
if (c === ">" || c === " ")
return true;
}
return false;
}
export function stripGitStatusUnits(text, mark) {
void mark;
const close = "</system-reminder>";
const findHead = (out, from) => {
for (let at = out.indexOf("<system-reminder", from); at !== -1; at = out.indexOf("<system-reminder", at + 1)) {
const gt = out.indexOf(">", at);
if (gt === -1)
return undefined;
if (out.startsWith(`\n${GIT_STATUS_FRAME_PREAMBLE}`, gt + 1))
return { at, bodyAt: gt + 1 };
}
return undefined;
};
let out = text;
for (let hit = findHead(out, 0); hit !== undefined; hit = findHead(out, 0)) {
const end = out.indexOf(close, hit.at);
if (end === -1)
break;
if (hasNestedReminderOpenTag(out.slice(hit.bodyAt, end)))
break;
out = out.slice(0, hit.at) + out.slice(end + close.length);
}
return out;
}
export function branchCarriesVisiblePositiveGitFrame(branch, mark) {
const newest = newestEngineGitFrame(branch, mark);
return newest !== undefined && newest.positive && gitFrameContextVisible(branch, newest.entryId);
}