Add biome config and update plugin source + dependencies
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
34
biome.json
Normal file
34
biome.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.11/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": true
|
||||
},
|
||||
"files": {
|
||||
"includes": ["**", "!!**/dist"]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab"
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double"
|
||||
}
|
||||
},
|
||||
"assist": {
|
||||
"enabled": true,
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
164
package-lock.json
generated
164
package-lock.json
generated
@@ -11,10 +11,174 @@
|
||||
"@paperclipai/plugin-sdk": "^2026.325.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.4.11",
|
||||
"@types/node": "^25.5.0",
|
||||
"typescript": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/biome": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.11.tgz",
|
||||
"integrity": "sha512-nWxHX8tf3Opb/qRgZpBbsTOqOodkbrkJ7S+JxJAruxOReaDPPmPuLBAGQ8vigyUgo0QBB+oQltNEAvalLcjggA==",
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"bin": {
|
||||
"biome": "bin/biome"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/biome"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@biomejs/cli-darwin-arm64": "2.4.11",
|
||||
"@biomejs/cli-darwin-x64": "2.4.11",
|
||||
"@biomejs/cli-linux-arm64": "2.4.11",
|
||||
"@biomejs/cli-linux-arm64-musl": "2.4.11",
|
||||
"@biomejs/cli-linux-x64": "2.4.11",
|
||||
"@biomejs/cli-linux-x64-musl": "2.4.11",
|
||||
"@biomejs/cli-win32-arm64": "2.4.11",
|
||||
"@biomejs/cli-win32-x64": "2.4.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-darwin-arm64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.11.tgz",
|
||||
"integrity": "sha512-wOt+ed+L2dgZanWyL6i29qlXMc088N11optzpo10peayObBaAshbTcxKUchzEMp9QSY8rh5h6VfAFE3WTS1rqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-darwin-x64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.11.tgz",
|
||||
"integrity": "sha512-gZ6zR8XmZlExfi/Pz/PffmdpWOQ8Qhy7oBztgkR8/ylSRyLwfRPSadmiVCV8WQ8PoJ2MWUy2fgID9zmtgUUJmw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-linux-arm64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.11.tgz",
|
||||
"integrity": "sha512-avdJaEElXrKceK0va9FkJ4P5ci3N01TGkc6ni3P8l3BElqbOz42Wg2IyX3gbh0ZLEd4HVKEIrmuVu/AMuSeFFA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-linux-arm64-musl": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.11.tgz",
|
||||
"integrity": "sha512-+Sbo1OAmlegtdwqFE8iOxFIWLh1B3OEgsuZfBpyyN/kWuqZ8dx9ZEes6zVnDMo+zRHF2wLynRVhoQmV7ohxl2Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-linux-x64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.11.tgz",
|
||||
"integrity": "sha512-TagWV0iomp5LnEnxWFg4nQO+e52Fow349vaX0Q/PIcX6Zhk4GGBgp3qqZ8PVkpC+cuehRctMf3+6+FgQ8jCEFQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-linux-x64-musl": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.11.tgz",
|
||||
"integrity": "sha512-bexd2IklK7ZgPhrz6jXzpIL6dEAH9MlJU1xGTrypx+FICxrXUp4CqtwfiuoDKse+UlgAlWtzML3jrMqeEAHEhA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-win32-arm64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.11.tgz",
|
||||
"integrity": "sha512-RJhaTnY8byzxDt4bDVb7AFPHkPcjOPK3xBip4ZRTrN3TEfyhjLRm3r3mqknqydgVTB74XG8l4jMLwEACEeihVg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@biomejs/cli-win32-x64": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.11.tgz",
|
||||
"integrity": "sha512-A8D3JM/00C2KQgUV3oj8Ba15EHEYwebAGCy5Sf9GAjr5Y3+kJIYOiESoqRDeuRZueuMdCsbLZIUqmPhpYXJE9A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@paperclipai/plugin-sdk": {
|
||||
"version": "2026.325.0",
|
||||
"resolved": "https://registry.npmjs.org/@paperclipai/plugin-sdk/-/plugin-sdk-2026.325.0.tgz",
|
||||
|
||||
11
package.json
11
package.json
@@ -8,13 +8,18 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "paperclip-plugin-dev-server"
|
||||
"dev": "paperclip-plugin-dev-server",
|
||||
"format": "biome format --write src/",
|
||||
"format:check": "biome format src/",
|
||||
"biome": "biome check src/",
|
||||
"biome:fix": "biome check --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@paperclipai/plugin-sdk": "^2026.325.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^6.0.2",
|
||||
"@types/node": "^25.5.0"
|
||||
"@biomejs/biome": "2.4.11",
|
||||
"@types/node": "^25.5.0",
|
||||
"typescript": "^6.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,10 @@ export class LegalApi {
|
||||
});
|
||||
}
|
||||
|
||||
async updateCase(caseNumber: string, data: CaseUpdateInput): Promise<CaseDetails> {
|
||||
async updateCase(
|
||||
caseNumber: string,
|
||||
data: CaseUpdateInput,
|
||||
): Promise<CaseDetails> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(data),
|
||||
@@ -46,19 +49,31 @@ export class LegalApi {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/status`);
|
||||
}
|
||||
|
||||
async search(query: string, limit = 10, sectionType = ""): Promise<SearchResult[]> {
|
||||
async search(
|
||||
query: string,
|
||||
limit = 10,
|
||||
sectionType = "",
|
||||
): Promise<SearchResult[]> {
|
||||
const params = new URLSearchParams({ query, limit: String(limit) });
|
||||
if (sectionType) params.set("section_type", sectionType);
|
||||
return this.request(`/api/search?${params}`);
|
||||
}
|
||||
|
||||
async searchCase(caseNumber: string, query: string, limit = 10): Promise<SearchResult[]> {
|
||||
async searchCase(
|
||||
caseNumber: string,
|
||||
query: string,
|
||||
limit = 10,
|
||||
): Promise<SearchResult[]> {
|
||||
const params = new URLSearchParams({ query, limit: String(limit) });
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/search?${params}`);
|
||||
return this.request(
|
||||
`/api/cases/${encodeURIComponent(caseNumber)}/search?${params}`,
|
||||
);
|
||||
}
|
||||
|
||||
async getTemplate(caseNumber: string): Promise<{ template: string }> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/template`);
|
||||
return this.request(
|
||||
`/api/cases/${encodeURIComponent(caseNumber)}/template`,
|
||||
);
|
||||
}
|
||||
|
||||
async getProcessingStatus(): Promise<ProcessingStatus> {
|
||||
@@ -81,25 +96,40 @@ export class LegalApi {
|
||||
}
|
||||
|
||||
async findSimilarCases(caseNumber: string): Promise<SearchResult[]> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/search?query=similar&limit=5`);
|
||||
return this.request(
|
||||
`/api/cases/${encodeURIComponent(caseNumber)}/search?query=similar&limit=5`,
|
||||
);
|
||||
}
|
||||
|
||||
async setOutcome(caseNumber: string, outcome: string, reasoning?: string): Promise<{ status: string }> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/outcome`, {
|
||||
async setOutcome(
|
||||
caseNumber: string,
|
||||
outcome: string,
|
||||
reasoning?: string,
|
||||
): Promise<{ status: string }> {
|
||||
return this.request(
|
||||
`/api/cases/${encodeURIComponent(caseNumber)}/outcome`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({ outcome, reasoning: reasoning || "" }),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async getClaims(caseNumber: string): Promise<ClaimsResponse> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/claims`);
|
||||
}
|
||||
|
||||
async setDirection(caseNumber: string, directionDoc: Record<string, unknown>): Promise<{ status: string }> {
|
||||
return this.request(`/api/cases/${encodeURIComponent(caseNumber)}/direction`, {
|
||||
async setDirection(
|
||||
caseNumber: string,
|
||||
directionDoc: Record<string, unknown>,
|
||||
): Promise<{ status: string }> {
|
||||
return this.request(
|
||||
`/api/cases/${encodeURIComponent(caseNumber)}/direction`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({ direction_doc: directionDoc }),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async runQA(caseNumber: string): Promise<QAResponse> {
|
||||
@@ -213,7 +243,10 @@ export interface ProcessingStatus {
|
||||
|
||||
export interface ClaimsResponse {
|
||||
case_number: string;
|
||||
claims: Record<string, Array<{ party_role: string; claim_text: string; claim_index: number }>>;
|
||||
claims: Record<
|
||||
string,
|
||||
Array<{ party_role: string; claim_text: string; claim_index: number }>
|
||||
>;
|
||||
total: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,14 @@ export default {
|
||||
properties: {
|
||||
case_number: { type: "string" as const },
|
||||
title: { type: "string" as const },
|
||||
appellants: { type: "array" as const, items: { type: "string" as const } },
|
||||
respondents: { type: "array" as const, items: { type: "string" as const } },
|
||||
appellants: {
|
||||
type: "array" as const,
|
||||
items: { type: "string" as const },
|
||||
},
|
||||
respondents: {
|
||||
type: "array" as const,
|
||||
items: { type: "string" as const },
|
||||
},
|
||||
subject: { type: "string" as const },
|
||||
property_address: { type: "string" as const },
|
||||
expected_outcome: { type: "string" as const },
|
||||
@@ -112,7 +118,10 @@ export default {
|
||||
parametersSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
query: { type: "string" as const, description: "Search query in Hebrew" },
|
||||
query: {
|
||||
type: "string" as const,
|
||||
description: "Search query in Hebrew",
|
||||
},
|
||||
limit: { type: "number" as const },
|
||||
section_type: { type: "string" as const },
|
||||
},
|
||||
|
||||
@@ -3,7 +3,9 @@ import { LegalApi } from "./legal-api.js";
|
||||
|
||||
const plugin = definePlugin({
|
||||
async setup(ctx) {
|
||||
const config = (await ctx.config.get()) as { legalApiBaseUrl?: string } | null;
|
||||
const config = (await ctx.config.get()) as {
|
||||
legalApiBaseUrl?: string;
|
||||
} | null;
|
||||
const baseUrl = config?.legalApiBaseUrl || "http://localhost:8085";
|
||||
const api = new LegalApi(baseUrl);
|
||||
|
||||
@@ -159,13 +161,7 @@ const plugin = definePlugin({
|
||||
},
|
||||
status: {
|
||||
type: "string",
|
||||
enum: [
|
||||
"new",
|
||||
"in_progress",
|
||||
"drafted",
|
||||
"reviewed",
|
||||
"final",
|
||||
],
|
||||
enum: ["new", "in_progress", "drafted", "reviewed", "final"],
|
||||
description: "New case status",
|
||||
},
|
||||
title: { type: "string" },
|
||||
@@ -257,7 +253,11 @@ const plugin = definePlugin({
|
||||
limit?: number;
|
||||
section_type?: string;
|
||||
};
|
||||
const results = await api.search(query, limit || 10, section_type || "");
|
||||
const results = await api.search(
|
||||
query,
|
||||
limit || 10,
|
||||
section_type || "",
|
||||
);
|
||||
return {
|
||||
content: JSON.stringify(results, null, 2),
|
||||
data: results,
|
||||
@@ -318,7 +318,8 @@ const plugin = definePlugin({
|
||||
"legal_document_list",
|
||||
{
|
||||
displayName: "רשימת מסמכים בתיק",
|
||||
description: "List all documents in a case with their extraction status.",
|
||||
description:
|
||||
"List all documents in a case with their extraction status.",
|
||||
parametersSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
@@ -338,7 +339,8 @@ const plugin = definePlugin({
|
||||
"legal_set_outcome",
|
||||
{
|
||||
displayName: "הזנת תוצאת ערר",
|
||||
description: "Set the decision outcome (rejection/full_acceptance/partial_acceptance) and optional reasoning from Dafna.",
|
||||
description:
|
||||
"Set the decision outcome (rejection/full_acceptance/partial_acceptance) and optional reasoning from Dafna.",
|
||||
parametersSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
@@ -348,7 +350,10 @@ const plugin = definePlugin({
|
||||
enum: ["rejection", "full_acceptance", "partial_acceptance"],
|
||||
description: "Decision outcome",
|
||||
},
|
||||
reasoning: { type: "string", description: "Optional reasoning from Dafna" },
|
||||
reasoning: {
|
||||
type: "string",
|
||||
description: "Optional reasoning from Dafna",
|
||||
},
|
||||
},
|
||||
required: ["case_number", "outcome"],
|
||||
},
|
||||
@@ -399,7 +404,10 @@ const plugin = definePlugin({
|
||||
},
|
||||
},
|
||||
async (params) => {
|
||||
const { case_number, query } = params as { case_number: string; query: string };
|
||||
const { case_number, query } = params as {
|
||||
case_number: string;
|
||||
query: string;
|
||||
};
|
||||
const results = await api.searchCase(case_number, query);
|
||||
return { content: JSON.stringify(results, null, 2), data: results };
|
||||
},
|
||||
@@ -429,7 +437,8 @@ const plugin = definePlugin({
|
||||
"legal_run_qa",
|
||||
{
|
||||
displayName: "בדיקת איכות",
|
||||
description: "Run QA validation on a drafted decision. Checks: grounding, claims coverage, neutral background, weights.",
|
||||
description:
|
||||
"Run QA validation on a drafted decision. Checks: grounding, claims coverage, neutral background, weights.",
|
||||
parametersSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
@@ -449,7 +458,8 @@ const plugin = definePlugin({
|
||||
"legal_trigger_learning",
|
||||
{
|
||||
displayName: "הפעלת לולאת למידה",
|
||||
description: "Trigger the learning loop — compare draft to final signed version.",
|
||||
description:
|
||||
"Trigger the learning loop — compare draft to final signed version.",
|
||||
parametersSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
@@ -530,7 +540,8 @@ const plugin = definePlugin({
|
||||
|
||||
if (linkedCase === legalCase.case_number) {
|
||||
// Map 13 legal-ai statuses to Paperclip issue status
|
||||
const statusMap: Record<string, "todo" | "in_progress" | "done"> = {
|
||||
const statusMap: Record<string, "todo" | "in_progress" | "done"> =
|
||||
{
|
||||
new: "todo",
|
||||
uploading: "todo",
|
||||
processing: "in_progress",
|
||||
@@ -566,7 +577,11 @@ const plugin = definePlugin({
|
||||
const label = statusLabels[legalCase.status] || legalCase.status;
|
||||
|
||||
if (targetStatus && issue.status !== targetStatus) {
|
||||
await ctx.issues.update(issue.id, { status: targetStatus }, companyId);
|
||||
await ctx.issues.update(
|
||||
issue.id,
|
||||
{ status: targetStatus },
|
||||
companyId,
|
||||
);
|
||||
await ctx.issues.createComment(
|
||||
issue.id,
|
||||
`📋 ${label}`,
|
||||
|
||||
Reference in New Issue
Block a user