feat(tools): כלי legal_predecessor_context — הקשר מריצות-קודמות לסוכן (#220) #5

Merged
chaim merged 1 commits from feat/predecessor-context into main 2026-07-07 05:12:18 +00:00
2 changed files with 66 additions and 0 deletions

View File

@@ -148,6 +148,20 @@ export class LegalApi {
// Return static style guide reference
return "ראה skill-legal-decision/SKILL.md — מדריך סגנון מלא של דפנה תמיר";
}
/**
* Recent conclusions of prior heartbeat runs across a case's issues (#220,
* "seance"). Lets a resuming agent read what earlier sessions concluded
* instead of re-deriving context from scratch.
*/
async getPredecessorForCase(
caseNumber: string,
limit = 5,
): Promise<PredecessorResponse> {
return this.request(
`/api/operations/cases/${encodeURIComponent(caseNumber)}/predecessor?limit=${limit}`,
);
}
}
// Types
@@ -260,3 +274,21 @@ export interface QAResponse {
}>;
status: string;
}
export interface PredecessorRun {
run_id: string;
status: string;
started_at: string | null;
finished_at: string | null;
summary: string | null;
error_code: string | null;
session_id: string | null;
agent_name: string | null;
identifier: string | null;
}
export interface PredecessorResponse {
ok: boolean;
case_number: string;
runs: PredecessorRun[];
}

View File

@@ -507,6 +507,40 @@ const plugin = definePlugin({
},
);
ctx.tools.register(
"legal_predecessor_context",
{
displayName: "הקשר מריצות קודמות",
description:
"Recent conclusions from prior heartbeat runs on this case (the 'summary' each run left). Call this when RESUMING work on a case to see what earlier sessions already did/decided — instead of re-deriving context from scratch. Provide the case number.",
parametersSchema: {
type: "object",
properties: {
case_number: {
type: "string",
description: "Case number (e.g. 1043-02-26)",
},
},
required: ["case_number"],
},
},
async (params) => {
const { case_number } = params as { case_number: string };
const result = await api.getPredecessorForCase(case_number);
// Readable digest for the agent — each prior run's conclusion,
// newest-first, summaries trimmed to keep the wake context lean.
const lines = result.runs.map((r) => {
const summary = (r.summary ?? "").trim().slice(0, 600);
const when = r.finished_at ?? r.started_at ?? "";
return `${r.agent_name ?? "?"} · ${r.identifier ?? ""} · ${when} · ${r.status}\n${summary}`;
});
const content = lines.length
? lines.join("\n\n")
: "אין ריצות קודמות עם מסקנות לתיק זה.";
return { content, data: result };
},
);
// ── Events ─────────────────────────────────────────────────────
ctx.events.on("issue.created", async (event) => {