diff --git a/Cyrano/package-lock.json b/Cyrano/package-lock.json index b8bbbc46..71c16969 100644 --- a/Cyrano/package-lock.json +++ b/Cyrano/package-lock.json @@ -49,7 +49,7 @@ "react-icons": "^5.5.0", "tesseract.js": "^6.0.1", "uuid": "^13.0.0", - "zod": "^3.25.76" + "zod": "^4.3.4" }, "devDependencies": { "@playwright/test": "^1.48.0", @@ -260,7 +260,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -302,7 +301,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1412,7 +1410,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -2432,7 +2429,6 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2594,7 +2590,6 @@ "integrity": "sha512-MFV6GhTflgBj194+vowTB2iLI5niMZhqiW7/NV7U4AfWbX/IAtsq4zA+gzCLyGzpsQUdJlX26hrQ1vuWShq2BQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "4.0.13", "fflate": "^0.8.2", @@ -3079,6 +3074,15 @@ "devtools-protocol": "*" } }, + "node_modules/chromium-bidi/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3548,8 +3552,7 @@ "version": "0.0.1521046", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz", "integrity": "sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==", - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/dingbat-to-unicode": { "version": "1.0.1", @@ -3924,7 +3927,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -5011,7 +5013,6 @@ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 10.16.0" } @@ -6101,7 +6102,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6236,7 +6236,6 @@ "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", "license": "Unlicense", - "peer": true, "engines": { "node": ">=12" }, @@ -7863,7 +7862,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7948,7 +7946,6 @@ "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -8024,7 +8021,6 @@ "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/expect": "4.0.13", "@vitest/mocker": "4.0.13", @@ -8268,7 +8264,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -8392,11 +8387,10 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.4.tgz", + "integrity": "sha512-Zw/uYiiyF6pUT1qmKbZziChgNPRu+ZRneAsMUDU6IwmXdWt5JwcUfy2bvLOCUtz5UniaN/Zx5aFttZYbYc7O/A==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/Cyrano/package.json b/Cyrano/package.json index d04cc047..ac3f5d6e 100644 --- a/Cyrano/package.json +++ b/Cyrano/package.json @@ -62,7 +62,7 @@ "react-icons": "^5.5.0", "tesseract.js": "^6.0.1", "uuid": "^13.0.0", - "zod": "^3.25.76" + "zod": "^4.3.4" }, "devDependencies": { "@playwright/test": "^1.48.0", diff --git a/Cyrano/src/engines/chronometric/modules/pattern-learning-module.ts b/Cyrano/src/engines/chronometric/modules/pattern-learning-module.ts index c59fb21d..a6d340d5 100644 --- a/Cyrano/src/engines/chronometric/modules/pattern-learning-module.ts +++ b/Cyrano/src/engines/chronometric/modules/pattern-learning-module.ts @@ -27,7 +27,7 @@ const PatternLearningInputSchema = z.object({ userId: z.string().describe('User ID'), minimumHoursPerWeek: z.number().optional().describe('Minimum hours per week'), minimumHoursPerDay: z.number().optional().describe('Minimum hours per day'), - typicalSchedule: z.record(z.number()).optional().describe('Typical schedule by day of week'), + typicalSchedule: z.record(z.string(), z.number()).optional().describe('Typical schedule by day of week'), offDays: z.array(z.string()).optional().describe('Off days (YYYY-MM-DD)'), useBaselineUntilDataAvailable: z.boolean().optional().describe('Use baseline until enough data available'), matterId: z.string().optional().describe('Matter ID for profitability analysis'), diff --git a/Cyrano/src/engines/goodcounsel/tools/ethics-reviewer.ts b/Cyrano/src/engines/goodcounsel/tools/ethics-reviewer.ts index 21f986e8..6a7f1e96 100644 --- a/Cyrano/src/engines/goodcounsel/tools/ethics-reviewer.ts +++ b/Cyrano/src/engines/goodcounsel/tools/ethics-reviewer.ts @@ -30,7 +30,7 @@ import { ethicsRulesService, EthicsReviewResult } from '../services/ethics-rules const EthicsReviewerSchema = z.object({ userId: z.string().optional().describe('User ID for ethics review'), - facts: z.record(z.any()).describe('Facts to evaluate against ethics rules'), + facts: z.record(z.string(), z.any()).describe('Facts to evaluate against ethics rules'), includeWarnings: z.boolean().default(true).describe('Include warnings in results'), }); diff --git a/Cyrano/src/engines/mae/services/ai-orchestrator.ts b/Cyrano/src/engines/mae/services/ai-orchestrator.ts index ab03704d..dec14fbc 100644 --- a/Cyrano/src/engines/mae/services/ai-orchestrator.ts +++ b/Cyrano/src/engines/mae/services/ai-orchestrator.ts @@ -14,7 +14,7 @@ const AIOrchestratorSchema = z.object({ task_description: z.string().describe('Description of the task to orchestrate'), ai_providers: z.array(z.string()).optional().describe('AI providers to use'), orchestration_mode: z.enum(['sequential', 'parallel', 'collaborative']).default('collaborative'), - parameters: z.record(z.any()).optional().describe('Orchestration parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Orchestration parameters'), }); /** diff --git a/Cyrano/src/engines/mae/tools/ai-orchestrator.ts b/Cyrano/src/engines/mae/tools/ai-orchestrator.ts index d30160ca..1f963070 100644 --- a/Cyrano/src/engines/mae/tools/ai-orchestrator.ts +++ b/Cyrano/src/engines/mae/tools/ai-orchestrator.ts @@ -14,7 +14,7 @@ const AIOrchestratorSchema = z.object({ task_description: z.string().describe('Description of the task to orchestrate'), ai_providers: z.array(z.string()).optional().describe('AI providers to use'), orchestration_mode: z.enum(['sequential', 'parallel', 'collaborative']).default('collaborative'), - parameters: z.record(z.any()).optional().describe('Orchestration parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Orchestration parameters'), }); /** diff --git a/Cyrano/src/http-bridge.ts b/Cyrano/src/http-bridge.ts index f9933077..950fe89e 100644 --- a/Cyrano/src/http-bridge.ts +++ b/Cyrano/src/http-bridge.ts @@ -644,7 +644,7 @@ app.post('/mcp/execute', async (req, res) => { if (!validationResult.success) { return res.status(400).json({ error: 'Invalid request body', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -1059,7 +1059,7 @@ app.post('/api/arkiver/upload', upload.single('file'), async (req, res) => { error: { code: 'INVALID_METADATA', message: 'Invalid metadata format', - details: metadataValidation.error.errors, + details: metadataValidation.error.issues, }, }); } @@ -1170,7 +1170,7 @@ app.get('/api/arkiver/files/:fileId', async (req, res) => { error: { code: 'INVALID_FILE_ID', message: 'Invalid file ID format', - details: validationResult.error.errors, + details: validationResult.error.issues, }, }); } diff --git a/Cyrano/src/modules/arkiver/extractors/conversation-extractor.ts b/Cyrano/src/modules/arkiver/extractors/conversation-extractor.ts index 1c82b9b0..65a7bcfd 100644 --- a/Cyrano/src/modules/arkiver/extractors/conversation-extractor.ts +++ b/Cyrano/src/modules/arkiver/extractors/conversation-extractor.ts @@ -20,7 +20,7 @@ const ChatGPTConversationSchema = z.object({ title: z.string().optional(), create_time: z.number().optional(), update_time: z.number().optional(), - mapping: z.record(z.any()).optional(), + mapping: z.record(z.string(), z.any()).optional(), moderation_results: z.array(z.any()).optional(), }); diff --git a/Cyrano/src/routes/auth.ts b/Cyrano/src/routes/auth.ts index d06ae02e..49c352ab 100644 --- a/Cyrano/src/routes/auth.ts +++ b/Cyrano/src/routes/auth.ts @@ -75,7 +75,7 @@ router.post('/refresh', async (req: Request, res: Response) => { if (!validationResult.success && req.body && Object.keys(req.body).length > 0) { return res.status(400).json({ error: 'Invalid request body', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -108,7 +108,7 @@ router.post('/verify', (req: Request, res: Response) => { if (!validationResult.success && req.body && Object.keys(req.body).length > 0) { return res.status(400).json({ error: 'Invalid request body', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } diff --git a/Cyrano/src/routes/library.ts b/Cyrano/src/routes/library.ts index 2a20cc4c..f28266a2 100644 --- a/Cyrano/src/routes/library.ts +++ b/Cyrano/src/routes/library.ts @@ -89,7 +89,7 @@ const LibraryLocationSchema = z.object({ name: z.string().min(1, 'Location name is required'), type: z.enum(['local', 'onedrive', 'gdrive', 's3']), path: z.string().min(1, 'Path is required'), - credentials: z.record(z.any()).optional(), + credentials: z.record(z.string(), z.any()).optional(), enabled: z.boolean().optional(), }); @@ -124,7 +124,7 @@ const BaselineConfigSchema = z.object({ userId: z.string().optional(), minimumHoursPerWeek: z.number().min(0).max(168), minimumHoursPerDay: z.number().min(0).max(24).optional(), - typicalSchedule: z.record(z.number()).optional(), + typicalSchedule: z.record(z.string(), z.number()).optional(), offDays: z.array(z.string()).optional(), useBaselineUntilDataAvailable: z.boolean().optional(), }); @@ -156,7 +156,7 @@ router.post('/onboarding/practice-profile', authenticateJWT, async (req: Request if (!validationResult.success) { return res.status(400).json({ error: 'Invalid practice profile data', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -192,7 +192,7 @@ router.post('/onboarding/baseline-config', async (req: Request, res: Response) = if (!validationResult.success) { return res.status(400).json({ error: 'Invalid baseline config data', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -267,7 +267,7 @@ router.post('/library/locations', authenticateJWT, async (req: Request, res: Res if (!validationResult.success) { return res.status(400).json({ error: 'Invalid library location data', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -313,7 +313,7 @@ router.post('/library/locations/:id/sync', authenticateJWT, async (req: Request, if (!idValidation.success) { return res.status(400).json({ error: 'Invalid location ID format', - details: idValidation.error.errors, + details: idValidation.error.issues, }); } @@ -508,7 +508,7 @@ router.get('/library/items', authenticateJWT, async (req: Request, res: Response if (!validationResult.success) { return res.status(400).json({ error: 'Invalid filter parameters', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -540,7 +540,7 @@ router.get('/library/items/:id', authenticateJWT, async (req: Request, res: Resp if (!validationResult.success) { return res.status(400).json({ error: 'Invalid item ID format', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -599,7 +599,7 @@ router.post('/library/items', authenticateJWT, async (req: Request, res: Respons if (!validationResult.success) { return res.status(400).json({ error: 'Invalid library item data', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -648,7 +648,7 @@ router.delete('/library/items/:id', authenticateJWT, async (req: Request, res: R if (!validationResult.success) { return res.status(400).json({ error: 'Invalid item ID format', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -709,7 +709,7 @@ router.post('/library/items/upload', authenticateJWT, upload.single('file'), asy if (!validationResult.success) { return res.status(400).json({ error: 'Invalid upload request data', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -785,7 +785,7 @@ router.post('/library/items/:id/ingest', authenticateJWT, async (req: Request, r if (!validationResult.success) { return res.status(400).json({ error: 'Invalid ingest request data', - details: validationResult.error.errors + details: validationResult.error.issues }); } @@ -810,7 +810,7 @@ router.post('/library/items/:id/ingest', authenticateJWT, async (req: Request, r if (!idValidation.success) { return res.status(400).json({ error: 'Invalid item ID format', - details: idValidation.error.errors, + details: idValidation.error.issues, }); } diff --git a/Cyrano/src/routes/onboarding.ts b/Cyrano/src/routes/onboarding.ts index e3be17c8..9ea52342 100644 --- a/Cyrano/src/routes/onboarding.ts +++ b/Cyrano/src/routes/onboarding.ts @@ -53,7 +53,7 @@ const BaselineConfigSchema = z.object({ minimumHoursPerWeek: z.number().min(0).max(168), minimumHoursPerDay: z.number().min(0).max(24).optional(), useBaselineUntilEnoughData: z.boolean().default(true), - typicalSchedule: z.record(z.number()).optional(), // day-of-week hours + typicalSchedule: z.record(z.string(), z.number()).optional(), // day-of-week hours offDays: z.array(z.string()).optional(), // ISO date strings }); @@ -232,7 +232,7 @@ router.get('/onboarding/status', async (req: Request, res: Response) => { return res.status(400).json({ success: false, error: 'Invalid query parameters', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } @@ -441,7 +441,7 @@ router.get('/onboarding/load-progress', async (req: Request, res: Response) => { return res.status(400).json({ success: false, error: 'Invalid query parameters', - details: validationResult.error.errors, + details: validationResult.error.issues, }); } diff --git a/Cyrano/src/tools/arkiver-integrity-test.ts b/Cyrano/src/tools/arkiver-integrity-test.ts index afde4656..55b20ced 100644 --- a/Cyrano/src/tools/arkiver-integrity-test.ts +++ b/Cyrano/src/tools/arkiver-integrity-test.ts @@ -25,7 +25,7 @@ const IntegrityTestSchema = z.object({ insightIds: z.array(z.string()).optional().describe('Specific insight IDs to test (if not provided, uses insights from targetLLM)'), fileId: z.string().optional().describe('File ID to test insights from'), llmSource: z.string().describe('Source LLM to test (e.g., "ChatGPT", "Claude", "Gemini")'), - parameters: z.record(z.any()).optional().describe('Additional test-specific parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Additional test-specific parameters'), }); /** diff --git a/Cyrano/src/tools/arkiver-processor-tools.ts b/Cyrano/src/tools/arkiver-processor-tools.ts index e27c974c..eb66e9fb 100644 --- a/Cyrano/src/tools/arkiver-processor-tools.ts +++ b/Cyrano/src/tools/arkiver-processor-tools.ts @@ -74,7 +74,7 @@ export class ArkiverTextProcessorTool extends BaseTool { }, null, 2)); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Text processing failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -129,7 +129,7 @@ export class ArkiverEmailProcessorTool extends BaseTool { return this.createSuccessResult(JSON.stringify(result, null, 2)); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Email processing failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -187,7 +187,7 @@ export class ArkiverEntityProcessorTool extends BaseTool { return this.createSuccessResult(JSON.stringify(result, null, 2)); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Entity extraction failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -277,7 +277,7 @@ export class ArkiverInsightProcessorTool extends BaseTool { return this.createSuccessResult(JSON.stringify(finalResult, null, 2)); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Insight generation failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -339,7 +339,7 @@ export class ArkiverTimelineProcessorTool extends BaseTool { return this.createSuccessResult(JSON.stringify(result, null, 2)); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Timeline extraction failed: ${error instanceof Error ? error.message : String(error)}`); } diff --git a/Cyrano/src/tools/case-manager.ts b/Cyrano/src/tools/case-manager.ts index 49013ecc..6fb37b89 100644 --- a/Cyrano/src/tools/case-manager.ts +++ b/Cyrano/src/tools/case-manager.ts @@ -12,8 +12,8 @@ import { eq, and, or, desc, asc, like, sql } from 'drizzle-orm'; const CaseManagerSchema = z.object({ action: z.enum(['create', 'update', 'get', 'list', 'delete']).describe('Action to perform on case'), case_id: z.string().optional().describe('Case ID for the operation'), - case_data: z.record(z.any()).optional().describe('Case data for create/update operations'), - filters: z.record(z.any()).optional().describe('Filters for list operations'), + case_data: z.record(z.string(), z.any()).optional().describe('Case data for create/update operations'), + filters: z.record(z.string(), z.any()).optional().describe('Filters for list operations'), }); export const caseManager = new (class extends BaseTool { diff --git a/Cyrano/src/tools/clio-integration.ts b/Cyrano/src/tools/clio-integration.ts index 9a5f5b61..bcb662d3 100644 --- a/Cyrano/src/tools/clio-integration.ts +++ b/Cyrano/src/tools/clio-integration.ts @@ -27,10 +27,10 @@ const ClioIntegrationSchema = z.object({ matter_id: z.string().optional().describe('Matter ID'), client_id: z.string().optional().describe('Client ID'), document_id: z.string().optional().describe('Document ID'), - parameters: z.record(z.any()).optional().describe('Additional parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Additional parameters'), }); -export const clioIntegration = new (class extends BaseTool { +export const clioIntegration: BaseTool = new (class extends BaseTool { public clioApiKey: string; public clioBaseUrl: string = 'https://app.clio.com/api/v4'; diff --git a/Cyrano/src/tools/cyrano-pathfinder.ts b/Cyrano/src/tools/cyrano-pathfinder.ts index 2de34de9..e8ea3ccc 100644 --- a/Cyrano/src/tools/cyrano-pathfinder.ts +++ b/Cyrano/src/tools/cyrano-pathfinder.ts @@ -21,7 +21,7 @@ import { const CyranoPathfinderSchema = z.object({ message: z.string().describe('User message to the Cyrano Pathfinder'), - context: z.record(z.any()).optional().describe('Optional context (app, page, matter, document, etc.)'), + context: z.record(z.string(), z.any()).optional().describe('Optional context (app, page, matter, document, etc.)'), model: z.enum(['perplexity', 'anthropic', 'openai', 'google', 'xai', 'deepseek']) .default('perplexity') .describe('AI model to use (default: perplexity)'), diff --git a/Cyrano/src/tools/document-processor.ts b/Cyrano/src/tools/document-processor.ts index 16462bd5..b9b46be4 100644 --- a/Cyrano/src/tools/document-processor.ts +++ b/Cyrano/src/tools/document-processor.ts @@ -12,7 +12,7 @@ const DocumentProcessorSchema = z.object({ document_text: z.string().optional().describe('The document text to process'), processing_type: z.enum(['extract', 'transform', 'validate', 'format']).optional().describe('Type of processing to perform'), action: z.enum(['fill_pdf_forms', 'apply_forecast_branding', 'redact']).optional().describe('Action to perform (for PDF and redaction operations)'), - options: z.record(z.any()).optional().describe('Processing options'), + options: z.record(z.string(), z.any()).optional().describe('Processing options'), // PDF form filling parameters form_type: z.enum(['tax_return', 'child_support', 'qdro']).optional().describe('Type of form to fill'), form_data: z.any().optional().describe('Data to fill into form'), @@ -35,7 +35,7 @@ const DocumentProcessorSchema = z.object({ }).optional().describe('Redaction rules configuration'), }); -export const documentProcessor = new (class extends BaseTool { +export const documentProcessor: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'document_processor', diff --git a/Cyrano/src/tools/email-artifact-collector.ts b/Cyrano/src/tools/email-artifact-collector.ts index 44800d57..3cf5a5ae 100644 --- a/Cyrano/src/tools/email-artifact-collector.ts +++ b/Cyrano/src/tools/email-artifact-collector.ts @@ -17,7 +17,7 @@ const EmailArtifactCollectorSchema = z.object({ keywords: z.array(z.string()).optional().describe('Optional keywords to filter emails'), }); -export const emailArtifactCollector = new (class extends BaseTool { +export const emailArtifactCollector: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'email_artifact_collector', diff --git a/Cyrano/src/tools/ethical-ai-guard.ts b/Cyrano/src/tools/ethical-ai-guard.ts index 19b33d12..1f18ca45 100644 --- a/Cyrano/src/tools/ethical-ai-guard.ts +++ b/Cyrano/src/tools/ethical-ai-guard.ts @@ -38,7 +38,7 @@ const EthicalAIGuardSchema = z.object({ app: z.string().optional().describe('Which app (LexFiat, Arkiver, etc.)'), tool: z.string().optional().describe('Which tool generated this'), }).optional().describe('Metadata about where this was called from'), - facts: z.record(z.any()).optional().describe('Facts for professional ethics rules evaluation'), + facts: z.record(z.string(), z.any()).optional().describe('Facts for professional ethics rules evaluation'), }); export interface GuardResult { @@ -68,7 +68,7 @@ export interface GuardResult { }; } -export const ethicalAIGuard = new (class extends BaseTool { +export const ethicalAIGuard: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'ethical_ai_guard', diff --git a/Cyrano/src/tools/ethics-policy-explainer.ts b/Cyrano/src/tools/ethics-policy-explainer.ts index 17a41940..8bb589c9 100644 --- a/Cyrano/src/tools/ethics-policy-explainer.ts +++ b/Cyrano/src/tools/ethics-policy-explainer.ts @@ -48,7 +48,7 @@ export interface PolicyExplanation { }; } -export const ethicsPolicyExplainer = new (class extends BaseTool { +export const ethicsPolicyExplainer: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'ethics_policy_explainer', diff --git a/Cyrano/src/tools/fact-checker.ts b/Cyrano/src/tools/fact-checker.ts index d2f8ba51..77e20169 100644 --- a/Cyrano/src/tools/fact-checker.ts +++ b/Cyrano/src/tools/fact-checker.ts @@ -31,7 +31,7 @@ const FactCheckerSchema = z.object({ save_preference: z.boolean().optional().default(false).describe('Save current settings as user preference'), }); -export const factChecker = new (class extends BaseTool { +export const factChecker: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'fact_checker', diff --git a/Cyrano/src/tools/legal-email-drafter.ts b/Cyrano/src/tools/legal-email-drafter.ts index 019818cd..8b8a77ff 100644 --- a/Cyrano/src/tools/legal-email-drafter.ts +++ b/Cyrano/src/tools/legal-email-drafter.ts @@ -310,7 +310,7 @@ export const legalEmailDrafter = new (class extends BaseTool { return this.createSuccessResult(JSON.stringify(draft, null, 2), responseMetadata); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Legal email drafting failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -552,7 +552,7 @@ export const refineEmailTone = new (class extends BaseTool { }); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Email tone refinement failed: ${error instanceof Error ? error.message : String(error)}`); } @@ -665,7 +665,7 @@ export const validateLegalLanguage = new (class extends BaseTool { }); } catch (error) { if (error instanceof z.ZodError) { - return this.createErrorResult(`Validation error: ${error.errors.map(e => e.message).join(', ')}`); + return this.createErrorResult(`Validation error: ${error.issues.map(e => e.message).join(', ')}`); } return this.createErrorResult(`Legal language validation failed: ${error instanceof Error ? error.message : String(error)}`); } diff --git a/Cyrano/src/tools/micourt-query.ts b/Cyrano/src/tools/micourt-query.ts index df4e3f31..d794543b 100644 --- a/Cyrano/src/tools/micourt-query.ts +++ b/Cyrano/src/tools/micourt-query.ts @@ -34,7 +34,7 @@ const MiCourtQuerySchema = z.object({ portal: z.enum(['micourt', 'odyssey', 'court-explorer', 'auto']).optional().default('auto').describe('Court portal to use (auto selects based on court)'), }); -export const micourtQuery = new (class extends BaseTool { +export const micourtQuery: BaseTool = new (class extends BaseTool { private micourtService: MiCourtService; constructor() { diff --git a/Cyrano/src/tools/pdf-form-filler.ts b/Cyrano/src/tools/pdf-form-filler.ts index 707b10ca..6b1dff60 100644 --- a/Cyrano/src/tools/pdf-form-filler.ts +++ b/Cyrano/src/tools/pdf-form-filler.ts @@ -22,7 +22,7 @@ const PDFFormFillerSchema = z.object({ * PDF Form Filler Tool * Fills PDF forms with calculated values and applies LexFiat Forecasterâ„¢ branding */ -export const pdfFormFiller = new (class extends BaseTool { +export const pdfFormFiller: BaseTool = new (class extends BaseTool { constructor() { super(); } diff --git a/Cyrano/src/tools/skill-executor.ts b/Cyrano/src/tools/skill-executor.ts index 531b4df5..66a662e9 100644 --- a/Cyrano/src/tools/skill-executor.ts +++ b/Cyrano/src/tools/skill-executor.ts @@ -13,8 +13,8 @@ import { skillDispatcher } from '../skills/skill-dispatcher.js'; const SkillExecutorSchema = z.object({ skill_id: z.string().describe('Skill ID (e.g., "forensic-finance:dro-weatherpro-skill")'), - input: z.record(z.any()).describe('Input data matching the skill\'s input_schema'), - context: z.record(z.any()).optional().describe('Additional context (matter_id, user_id, etc.)'), + input: z.record(z.string(), z.any()).describe('Input data matching the skill\'s input_schema'), + context: z.record(z.string(), z.any()).optional().describe('Additional context (matter_id, user_id, etc.)'), }); export const skillExecutor = new (class extends BaseTool { diff --git a/Cyrano/src/tools/sync-manager.ts b/Cyrano/src/tools/sync-manager.ts index 4a4cf2cf..850aceb8 100644 --- a/Cyrano/src/tools/sync-manager.ts +++ b/Cyrano/src/tools/sync-manager.ts @@ -10,10 +10,10 @@ import { z } from 'zod'; const SyncManagerSchema = z.object({ service: z.enum(['clio', 'gmail', 'calendar', 'westlaw', 'icle', 'all']).describe('Service to sync (MiFile removed - use micourt_query for user-initiated docket queries)'), action: z.enum(['status', 'sync', 'force_sync']).default('status').describe('Sync action to perform'), - parameters: z.record(z.any()).optional().describe('Sync parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Sync parameters'), }); -export const syncManager = new (class extends BaseTool { +export const syncManager: BaseTool = new (class extends BaseTool { public syncStates: Map = new Map(); public syncProgress: Map = new Map(); diff --git a/Cyrano/src/tools/ten-rules-checker.ts b/Cyrano/src/tools/ten-rules-checker.ts index 563fd00d..ebe54d86 100644 --- a/Cyrano/src/tools/ten-rules-checker.ts +++ b/Cyrano/src/tools/ten-rules-checker.ts @@ -75,7 +75,7 @@ export interface TenRulesCheckResult { }; } -export const tenRulesChecker = new (class extends BaseTool { +export const tenRulesChecker: BaseTool = new (class extends BaseTool { getToolDefinition() { return { name: 'ten_rules_checker', diff --git a/Cyrano/src/tools/time-value-billing.ts b/Cyrano/src/tools/time-value-billing.ts index cbbb3eec..bd6e843c 100644 --- a/Cyrano/src/tools/time-value-billing.ts +++ b/Cyrano/src/tools/time-value-billing.ts @@ -31,7 +31,7 @@ const AnalyzeSchema = z.object({ clio: z.object({ api_key: z.string(), base_url: z.string().optional(), - query: z.record(z.any()).optional(), + query: z.record(z.string(), z.any()).optional(), }).optional(), }).default({}), policy: z.object({ diff --git a/Cyrano/src/tools/workflow-archaeology.ts b/Cyrano/src/tools/workflow-archaeology.ts index 2984ceb4..579a3d9a 100644 --- a/Cyrano/src/tools/workflow-archaeology.ts +++ b/Cyrano/src/tools/workflow-archaeology.ts @@ -12,13 +12,13 @@ const WorkflowArchaeologySchema = z.object({ start_time: z.string().describe('Start time (ISO 8601)'), end_time: z.string().describe('End time (ISO 8601)'), granularity: z.enum(['hour', 'day', 'week']).optional().describe('Time granularity (auto-detected if not provided)'), - context: z.record(z.any()).optional().describe('Additional context (matter_id, user_id, etc.)'), + context: z.record(z.string(), z.any()).optional().describe('Additional context (matter_id, user_id, etc.)'), artifacts: z.array(z.object({ type: z.enum(['email', 'calendar', 'document', 'call', 'other']), id: z.string(), timestamp: z.string(), content: z.string().optional(), - metadata: z.record(z.any()).optional(), + metadata: z.record(z.string(), z.any()).optional(), })).describe('Array of artifact sources'), }); diff --git a/Cyrano/src/tools/workflow-manager.ts b/Cyrano/src/tools/workflow-manager.ts index 20be039a..f4ddb2c9 100644 --- a/Cyrano/src/tools/workflow-manager.ts +++ b/Cyrano/src/tools/workflow-manager.ts @@ -12,7 +12,7 @@ const WorkflowManagerSchema = z.object({ workflow_type: z.enum(['compare', 'critique', 'collaborate', 'custom']).optional().describe('Type of workflow to manage'), case_id: z.string().optional().describe('Case ID for the workflow'), documents: z.array(z.string()).optional().describe('Document IDs to process'), - parameters: z.record(z.any()).optional().describe('Workflow parameters'), + parameters: z.record(z.string(), z.any()).optional().describe('Workflow parameters'), custom_stages: z.array(z.object({ id: z.string(), name: z.string(), diff --git a/apps/arkiver/package-lock.json b/apps/arkiver/package-lock.json index e3463fdd..63aeb7d8 100644 --- a/apps/arkiver/package-lock.json +++ b/apps/arkiver/package-lock.json @@ -863,7 +863,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -1677,7 +1676,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.4.tgz", "integrity": "sha512-Zw/uYiiyF6pUT1qmKbZziChgNPRu+ZRneAsMUDU6IwmXdWt5JwcUfy2bvLOCUtz5UniaN/Zx5aFttZYbYc7O/A==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/apps/arkiver/package.json b/apps/arkiver/package.json index 42c157fa..c8e56ec8 100644 --- a/apps/arkiver/package.json +++ b/apps/arkiver/package.json @@ -1,17 +1,16 @@ { "name": "@cyrano/arkiver", "version": "1.0.0", - "description": "Standalone document processing and insight extraction application", + "description": "Thin-client MCP application for document processing and insight extraction (backend hosted in Cyrano)", "type": "module", - "main": "backend/index.js", "scripts": { - "build": "tsc", - "dev": "tsx watch backend/index.ts", - "start": "node backend/index.js" + "dev": "cd frontend && npm run dev", + "build": "cd frontend && npm run build", + "preview": "cd frontend && npm run preview" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.25.1", - "zod": "3.25.76" + "zod": "^4.3.4" }, "devDependencies": { "@types/node": "^25.0.3",