feat(canvas): Add NX model introspection API endpoints

Phase 4 of Canvas Professional Upgrade:
- Add /studies/{id}/nx/introspect endpoint for full model introspection
- Add /studies/{id}/nx/expressions endpoint for expression list
- Add caching to avoid re-running NX journal on each request
- Add frontend API client methods: introspectNxModel, getNxExpressions
- Use existing introspect_part.py extractor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-15 22:39:38 -05:00
parent 2d4303bf22
commit 0eb5028d8f
2 changed files with 213 additions and 0 deletions

View File

@@ -348,6 +348,55 @@ class ApiClient {
if (!response.ok) throw new Error(`Failed to export ${format}`);
return response.json();
}
// NX Model introspection
async introspectNxModel(studyId: string, force: boolean = false): Promise<{
study_id: string;
cached: boolean;
introspection: {
success: boolean;
part_file: string;
expressions: {
user: Array<{
name: string;
value: number;
units?: string;
formula?: string;
}>;
internal: any[];
user_count: number;
total_count: number;
};
mass_properties: {
mass_kg: number;
mass_g: number;
volume_mm3: number;
surface_area_mm2: number;
center_of_gravity_mm: [number, number, number];
};
};
}> {
const url = force
? `${API_BASE}/optimization/studies/${studyId}/nx/introspect?force=true`
: `${API_BASE}/optimization/studies/${studyId}/nx/introspect`;
const response = await fetch(url);
if (!response.ok) throw new Error('Failed to introspect NX model');
return response.json();
}
async getNxExpressions(studyId: string): Promise<{
study_id: string;
expressions: Array<{
name: string;
value: number;
units?: string;
formula?: string;
}>;
count: number;
}> {
const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/nx/expressions`);
if (!response.ok) throw new Error('Failed to get NX expressions');
return response.json();
}
}
export const apiClient = new ApiClient();