diff --git a/src/legal-api.ts b/src/legal-api.ts index 11a7fa8..fee4dd8 100644 --- a/src/legal-api.ts +++ b/src/legal-api.ts @@ -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 { + 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[]; +} diff --git a/src/worker.ts b/src/worker.ts index 5bf7e12..9ff5690 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -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) => {