Rl-Auto / apps /api /src /judge /trajectory.ts
Lazywords's picture
Deploy RL Auto Docker Space
c4ae742
Raw
History Blame Contribute Delete
10.7 kB
type AnyObj = Record<string, any>;
const NOISE_TOOLS =
/^(default_config|auth_get_current_user|get_config|whoami|current_user|login|logout|session|authenticate)$/i;
const NOISE_ENDPOINTS = [
/\/default[_-]?config/i,
/\/api\/auth\/login$/i,
/\/api\/auth\/logout$/i,
/\/api\/auth\/me$/i,
/\/api\/session$/i,
/\/auth\/get[_-]?current[_-]?user/i,
/\/whoami/i,
/\/api\/users\/unread-counts$/i,
/\/api\/users\/starred$/i,
/\/api\/conversations\/dm/i,
/\/api\/conversations\/read-position$/i,
/\/api\/messages\/read$/i,
/\/api\/messages\/[^/]+\/reactions$/i,
];
const ENTITY_KEYS = ["channelId", "guildId", "messageId", "userId", "roleId", "webhookId"];
type EntityMap = Record<string, string[]>;
type EntityAnchors = Record<string, string>;
type WantedMcpCall = { tool: string; conds: Array<{ path: string; value: string }> };
function argsKey(value: unknown): string {
if (!value || typeof value !== "object") return "";
try {
return JSON.stringify(value);
} catch (_) {
return "";
}
}
function isTypeaheadPair(prev: unknown, curr: unknown): boolean {
const pa = argsKey(prev);
const ca = argsKey(curr);
if (!pa || !ca || pa === ca) return false;
return ca.startsWith(pa.slice(0, -1)) || pa.startsWith(ca.slice(0, -1));
}
function denoiseMcpCalls(calls: AnyObj[]): AnyObj[] {
const seen: Record<string, number> = {};
const out: AnyObj[] = [];
let prev: AnyObj | null = null;
(calls || []).forEach((call) => {
if (NOISE_TOOLS.test(call.tool || "")) return;
if (prev && prev.tool === call.tool && isTypeaheadPair(prev.args, call.args)) {
out.pop();
}
const key = (call.tool || "") + "::" + argsKey(call.args);
seen[key] = (seen[key] || 0) + 1;
if (seen[key] <= 3) out.push(call);
prev = call;
});
return out;
}
function taskMentionsReadState(text: unknown): boolean {
return /(?:mark(?:ed)?\s+.*read|read\s+(?:state|status|marker|receipt|position)|unread|read-position)/i.test(
String(text || ""),
);
}
function isReadMarkerTool(tool: unknown): boolean {
return /^mark_.*read$/i.test(String(tool || "")) || /read[_-]position/i.test(String(tool || ""));
}
function getNestedValue(obj: unknown, dotPath: string): unknown {
return dotPath.split(".").reduce(function (acc: any, key) {
return acc != null && typeof acc === "object" ? acc[key] : undefined;
}, obj as AnyObj);
}
function parseWantedMcpCall(wanted: unknown): WantedMcpCall {
const raw = String(wanted || "").trim();
const callMatch = raw.match(/^CALL\s+(\S+)(.*)$/i);
if (!callMatch) return { tool: raw, conds: [] };
const conds = callMatch[2]
.split("|")
.map((part) => part.trim())
.filter(Boolean)
.map((part) => {
const match = part.match(/^([\w.]+)\s*=\s*(.+)$/);
return match ? { path: match[1].trim(), value: match[2].trim() } : null;
})
.filter(Boolean) as Array<{ path: string; value: string }>;
return { tool: callMatch[1], conds };
}
function matchWantedCond(call: AnyObj, cond: { path: string; value: string }): boolean {
let actual: unknown;
if (cond.path.startsWith("args.")) {
actual = getNestedValue(call.args || {}, cond.path.slice(5));
} else if (cond.path.startsWith("input.")) {
actual = getNestedValue(call.args || call.input || {}, cond.path.slice(6));
} else if (cond.path.startsWith("result.")) {
actual = getNestedValue(call.result || call.output || {}, cond.path.slice(7));
} else {
actual = getNestedValue(call, cond.path);
if (actual == null) actual = getNestedValue(call.args || call.input || {}, cond.path);
}
if (actual == null) return false;
if (cond.value === "*") return true;
return String(actual) === String(cond.value);
}
function addEntityValue(out: EntityMap, key: string, value: unknown): void {
if (value == null || value === "") return;
if (typeof value === "object") return;
const str = String(value);
if (!out[key]) out[key] = [];
if (out[key].indexOf(str) < 0) out[key].push(str);
}
function collectEntityIds(value: unknown, out: EntityMap = {}, depth = 0): EntityMap {
if (!value || typeof value !== "object" || depth > 5) return out;
if (Array.isArray(value)) {
value.forEach((item) => collectEntityIds(item, out, depth + 1));
return out;
}
Object.keys(value as AnyObj).forEach((key) => {
const child = (value as AnyObj)[key];
if (ENTITY_KEYS.indexOf(key) >= 0) addEntityValue(out, key, child);
if (child && typeof child === "object") collectEntityIds(child, out, depth + 1);
});
return out;
}
function getCallEntities(call: AnyObj): EntityMap {
return collectEntityIds(call && (call.args || call.input || {}));
}
function entitiesCompatible(entities: EntityMap, anchors: EntityAnchors): boolean {
return ENTITY_KEYS.every((key) => {
const anchor = anchors[key];
const values = entities[key] || [];
return !anchor || !values.length || values.indexOf(anchor) >= 0;
});
}
function updateEntityAnchors(anchors: EntityAnchors, entities: EntityMap): void {
ENTITY_KEYS.forEach((key) => {
if (anchors[key]) return;
const values = entities[key] || [];
if (values.length === 1) anchors[key] = values[0];
});
}
function denoiseRequests(requests: AnyObj[]): AnyObj[] {
const seen: Record<string, number> = {};
const out: AnyObj[] = [];
let prev: AnyObj | null = null;
(requests || []).forEach((request) => {
const endpoint = request.urlPattern || request.url || "";
if (NOISE_ENDPOINTS.some((re) => re.test(endpoint))) return;
const qp = request.input && request.input.queryParams;
if (
prev &&
prev.method === request.method &&
prev.urlPattern === request.urlPattern &&
isTypeaheadPair(prev.input && prev.input.queryParams, qp)
) {
out.pop();
}
const key =
request.method +
" " +
(request.urlPattern || "") +
"::" +
argsKey(qp) +
"::" +
argsKey(request.input && request.input.bodyParams);
seen[key] = (seen[key] || 0) + 1;
if (seen[key] <= (request.method === "GET" ? 1 : 3)) out.push(request);
prev = request;
});
return out;
}
function isSuccessfulStatus(item: AnyObj): boolean {
const status = item && item.output && item.output.statusCode;
return Number(status) >= 200 && Number(status) < 300;
}
function toMcpCall(call: AnyObj): AnyObj {
const input: AnyObj = {};
if (call.args && typeof call.args === "object" && Object.keys(call.args).length) {
if (call.args.pathParams || call.args.queryParams || call.args.bodyParams) {
Object.assign(input, call.args);
} else {
input.bodyParams = call.args;
}
}
return { tool: call.tool, input };
}
function findMcpCall(
calls: AnyObj[],
wanted: unknown,
cursor: number,
used: Record<string, boolean>,
anchors: EntityAnchors,
): AnyObj | null {
const parsed = parseWantedMcpCall(wanted);
const target = parsed.tool;
let bestAny: AnyObj | null = null;
for (let i = 0; i < calls.length; i += 1) {
const call = calls[i];
call.index = call.index == null ? i : call.index;
if (used[call.index] || call.tool !== target) continue;
if (!parsed.conds.every((cond) => matchWantedCond(call, cond))) continue;
if (!entitiesCompatible(getCallEntities(call), anchors)) continue;
if (!bestAny) bestAny = call;
if (call.index > cursor) return call;
}
return bestAny;
}
function findMcpCallById(calls: AnyObj[], wantedId: unknown, used: Record<string, boolean>): AnyObj | null {
const id = String(wantedId || "");
if (!id) return null;
for (let i = 0; i < calls.length; i += 1) {
const call = calls[i];
call.index = call.index == null ? i : call.index;
const callId = String(call.id || "");
if (!callId || callId !== id || used[call.index]) continue;
return call;
}
return null;
}
function buildGroupedMcpTrajectory(calls: AnyObj[], groups: AnyObj[], instructionText = ""): string | null {
let cursor = -1;
const used: Record<string, boolean> = {};
const anchors: EntityAnchors = {};
const keepReadMarkers = taskMentionsReadState(instructionText);
const subtasks: AnyObj[] = [];
groups.forEach((group, groupIndex) => {
const mcpCalls: AnyObj[] = [];
const wantedIds = Array.isArray(group.callIds)
? group.callIds
: Array.isArray(group.mcpCallIds)
? group.mcpCallIds
: [];
wantedIds.forEach((wantedId: unknown) => {
const match = findMcpCallById(calls, wantedId, used);
if (!match) return;
const wantedTool = String(match.tool || "");
if (!keepReadMarkers && isReadMarkerTool(wantedTool)) return;
if (!entitiesCompatible(getCallEntities(match), anchors)) return;
used[match.index] = true;
cursor = Math.max(cursor, match.index);
updateEntityAnchors(anchors, getCallEntities(match));
mcpCalls.push(toMcpCall(match));
});
if (!mcpCalls.length) (Array.isArray(group.calls) ? group.calls : []).forEach((wanted) => {
const wantedTool = parseWantedMcpCall(wanted).tool;
if (!keepReadMarkers && isReadMarkerTool(wantedTool)) return;
const match = findMcpCall(calls, wanted, cursor, used, anchors);
if (!match) return;
used[match.index] = true;
cursor = Math.max(cursor, match.index);
updateEntityAnchors(anchors, getCallEntities(match));
mcpCalls.push(toMcpCall(match));
});
if (mcpCalls.length) {
subtasks.push({
subtask: {
order: groupIndex + 1,
mode: "mcp",
description: String(group.name || group.reason || "Grouped MCP calls"),
mcpCalls,
},
});
}
});
return subtasks.length ? JSON.stringify(subtasks, null, 2) : null;
}
function buildGroupedTrajectory(evidence: AnyObj, groups: AnyObj[]): string | null {
if (!Array.isArray(groups) || !groups.length) return null;
if (evidence && evidence.type === "mcp" && evidence.calls && evidence.calls.length) {
return buildGroupedMcpTrajectory(evidence.calls, groups, evidence.instructionText || "");
}
return null;
}
export function buildGoldenTrajectory(evidence: AnyObj, groups: AnyObj[] = []): string {
if (!evidence) return "[]";
const grouped = buildGroupedTrajectory(evidence, groups);
if (grouped) return grouped;
if (evidence.type === "mcp" && evidence.calls && evidence.calls.length) {
return JSON.stringify(
[
{
subtask: {
order: 1,
mode: "mcp",
description: "Recording trajectory (denoised)",
mcpCalls: denoiseMcpCalls(evidence.calls).map(toMcpCall),
},
},
],
null,
2,
);
}
return "[]";
}