| // apps/api/src/analyzers/detect.ts | |
| // Detect whether an uploaded ZIP is an API-mode recording or an MCP-mode recording. | |
| // Rule (matches the existing importer logic in scripts/mcp/importer.js): | |
| // - has session.json → mcp | |
| // - has mcp_calls.json → mcp | |
| // - otherwise (network.json only, etc.) → api | |
| import JSZip from "jszip"; | |
| import type { DetectedMode } from "../queue/store.js"; | |
| const MCP_MARKERS = [/(^|\/)session\.json$/i, /(^|\/)mcp_calls\.json$/i]; | |
| export async function detectModeFromZip( | |
| buffer: Buffer | |
| ): Promise<{ mode: DetectedMode; entries: string[] }> { | |
| let zip: JSZip; | |
| try { | |
| zip = await JSZip.loadAsync(buffer); | |
| } catch (err) { | |
| const message = | |
| err instanceof Error ? err.message : "ZIP 解析失败(不是有效的 zip 文件)"; | |
| throw Object.assign(new Error(message), { code: 400 }); | |
| } | |
| const entries: string[] = []; | |
| zip.forEach((path, entry) => { | |
| if (!entry.dir) entries.push(path); | |
| }); | |
| const isMcp = entries.some((p) => MCP_MARKERS.some((re) => re.test(p))); | |
| return { mode: isMcp ? "mcp" : "api", entries }; | |
| } | |