@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.2a88920
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyzer-template/.build-info.json +8 -8
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +5 -5
- package/analyzer-template/packages/ai/index.ts +15 -2
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +87 -51
- package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +98 -9
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +139 -23
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +6 -126
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +555 -28
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +88 -7
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +198 -34
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +772 -243
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +205 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +10 -2
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +43 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +122 -15
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +160 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +319 -88
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +156 -0
- package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
- package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +642 -7
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +383 -6
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1299 -51
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
- package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +23 -6
- package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
- package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
- package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
- package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
- package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
- package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +30 -19
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +14 -4
- package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
- package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +189 -76
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +29 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +77 -9
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +276 -17
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
- package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
- package/analyzer-template/packages/aws/package.json +2 -2
- package/analyzer-template/packages/database/src/lib/kysely/db.ts +8 -1
- package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
- package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
- package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
- package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
- package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
- package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
- package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
- package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +8 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/github/package.json +1 -1
- package/analyzer-template/packages/types/index.ts +1 -0
- package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
- package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
- package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
- package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
- package/analyzer-template/playwright/capture.ts +20 -8
- package/analyzer-template/playwright/captureStatic.ts +1 -1
- package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
- package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
- package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
- package/analyzer-template/project/constructMockCode.ts +367 -37
- package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
- package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
- package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
- package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
- package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
- package/analyzer-template/project/orchestrateCapture.ts +71 -6
- package/analyzer-template/project/reconcileMockDataKeys.ts +152 -9
- package/analyzer-template/project/runAnalysis.ts +4 -0
- package/analyzer-template/project/start.ts +35 -11
- package/analyzer-template/project/writeMockDataTsx.ts +127 -4
- package/analyzer-template/project/writeScenarioComponents.ts +101 -8
- package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
- package/background/src/lib/virtualized/project/constructMockCode.js +300 -7
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js +58 -6
- package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +126 -9
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
- package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
- package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
- package/background/src/lib/virtualized/project/start.js +32 -11
- package/background/src/lib/virtualized/project/start.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +101 -4
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +57 -8
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/codeyam-cli/src/cli.js +2 -0
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/commands/debug.js +7 -5
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/memory.js +273 -0
- package/codeyam-cli/src/commands/memory.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +4 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/analysisRunner.js +21 -2
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/install-skills.js +42 -6
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +1 -0
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/queue/manager.js +6 -0
- package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
- package/codeyam-cli/src/utils/rules/index.js +5 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -0
- package/codeyam-cli/src/utils/rules/parser.js +106 -0
- package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js +18 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +132 -0
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +2 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/database.js +7 -3
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +40 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-DsN1wKrm.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-DLqD3qNt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-Ba2JVPzP.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CEleMv_j.js → InlineSpinner-C8lyxW9k.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-aht4aafF.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-CVtiBnY5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-B0GLXMsr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-xgeCVgSM.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-OApQuNyq.js +16 -0
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-DuDvi0jm.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-DzccYyI8.js} +3 -13
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-DyFZkK0l.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-BwqWJOgH.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BwavGCpm.js +32 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-Cx24_aWc.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-EPOLDU6W-CXRTFQ3F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-BOARzkeR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-BdhJEx6B.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BBnGWYga.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-BJUiQqZF.js} +12 -12
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js → entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-wDWZZO1W.js → entity._sha_.create-scenario-D1T4TGjf.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-CTBG2mmz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-CS2cb_eZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-DMJ7zii9.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-CJ6lTdTA.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-CPTZZ-JZ.js} +8 -8
- package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-B1h680n5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-lzqtyFU8.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-B7B9V-bu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-a78b90a2.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory--GCbFsBE.js +92 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-CxXUmBSd.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-B2eDuBj8.js → settings-CS5f3WzT.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-DwFIBT09.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-B6LgvRJg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-C1v1PQzo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BUm0UVJm.js → useLastLogLine-aSv48UbS.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-DYxHZQuP.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-mBRpZPiu.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-BM6TDT1Y.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-dYC34MHw.js +257 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/templates/codeyam-memory-hook.sh +200 -0
- package/codeyam-cli/templates/codeyam:debug.md +47 -3
- package/codeyam-cli/templates/codeyam:diagnose.md +203 -25
- package/codeyam-cli/templates/codeyam:memory.md +341 -0
- package/codeyam-cli/templates/codeyam:new-rule.md +13 -0
- package/codeyam-cli/templates/rule-reflection-hook.py +160 -0
- package/codeyam-cli/templates/rules-instructions.md +93 -0
- package/package.json +8 -5
- package/packages/ai/index.js +7 -3
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +70 -29
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +78 -8
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +440 -27
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/completionCall.js +161 -30
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +589 -166
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +41 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +104 -11
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +159 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +265 -79
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructureChunking.js +111 -0
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
- package/packages/ai/src/lib/e2eDataTracking.js +241 -0
- package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
- package/packages/ai/src/lib/generateEntityScenarioData.js +525 -8
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +281 -4
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +946 -42
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
- package/packages/ai/src/lib/mergeStatements.js +70 -51
- package/packages/ai/src/lib/mergeStatements.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +15 -7
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
- package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
- package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
- package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
- package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
- package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/analysisContext.js +30 -5
- package/packages/analyze/src/lib/analysisContext.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +21 -9
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +14 -4
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
- package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +160 -68
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +25 -8
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +71 -9
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +233 -9
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
- package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
- package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
- package/packages/database/src/lib/kysely/db.js +8 -1
- package/packages/database/src/lib/kysely/db.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/packages/database/src/lib/loadAnalyses.js +45 -2
- package/packages/database/src/lib/loadAnalyses.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +8 -0
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/packages/database/src/lib/loadBranch.js +11 -1
- package/packages/database/src/lib/loadBranch.js.map +1 -1
- package/packages/database/src/lib/loadCommit.js +7 -0
- package/packages/database/src/lib/loadCommit.js.map +1 -1
- package/packages/database/src/lib/loadCommits.js +22 -1
- package/packages/database/src/lib/loadCommits.js.map +1 -1
- package/packages/database/src/lib/loadEntities.js +23 -4
- package/packages/database/src/lib/loadEntities.js.map +1 -1
- package/packages/database/src/lib/loadEntityBranches.js +9 -0
- package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
- package/packages/database/src/lib/updateCommitMetadata.js +5 -4
- package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/packages/types/index.js.map +1 -1
- package/packages/utils/src/lib/safeFileName.js +29 -3
- package/packages/utils/src/lib/safeFileName.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
- package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { ExecutionFlow, ScenariosDataStructure } from '~codeyam/types';
|
|
2
|
+
|
|
3
|
+
// Type for a single required value from ExecutionFlow
|
|
4
|
+
type RequiredValue = NonNullable<ExecutionFlow['requiredValues']>[number];
|
|
5
|
+
|
|
6
|
+
const DEFAULT_MAX_KEYS_PER_CHUNK = 8;
|
|
7
|
+
|
|
8
|
+
export interface ChunkOptions {
|
|
9
|
+
maxKeysPerChunk?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Chunk a large data structure into smaller pieces for focused LLM processing.
|
|
14
|
+
*
|
|
15
|
+
* Large schemas overwhelm LLMs, causing them to make mistakes on some keys.
|
|
16
|
+
* By processing smaller chunks, each key gets more focused attention.
|
|
17
|
+
*
|
|
18
|
+
* @param dataForMocks - The full data structure schema
|
|
19
|
+
* @param options - Chunking options (maxKeysPerChunk defaults to 8)
|
|
20
|
+
* @returns Array of smaller data structure chunks
|
|
21
|
+
*/
|
|
22
|
+
export function chunkDataStructure(
|
|
23
|
+
dataForMocks: ScenariosDataStructure['dataForMocks'],
|
|
24
|
+
options: ChunkOptions = {},
|
|
25
|
+
): Array<ScenariosDataStructure['dataForMocks']> {
|
|
26
|
+
if (!dataForMocks || typeof dataForMocks !== 'object') {
|
|
27
|
+
return [dataForMocks];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const { maxKeysPerChunk = DEFAULT_MAX_KEYS_PER_CHUNK } = options;
|
|
31
|
+
const keys = Object.keys(dataForMocks);
|
|
32
|
+
|
|
33
|
+
// Don't chunk if already small enough
|
|
34
|
+
if (keys.length <= maxKeysPerChunk) {
|
|
35
|
+
return [dataForMocks];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const chunks: Array<ScenariosDataStructure['dataForMocks']> = [];
|
|
39
|
+
|
|
40
|
+
for (let i = 0; i < keys.length; i += maxKeysPerChunk) {
|
|
41
|
+
const chunkKeys = keys.slice(i, i + maxKeysPerChunk);
|
|
42
|
+
const chunk: ScenariosDataStructure['dataForMocks'] = {};
|
|
43
|
+
|
|
44
|
+
for (const key of chunkKeys) {
|
|
45
|
+
(chunk as Record<string, unknown>)[key] = (
|
|
46
|
+
dataForMocks as Record<string, unknown>
|
|
47
|
+
)[key];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
chunks.push(chunk);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return chunks;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the requiredValues that are relevant to a specific chunk.
|
|
58
|
+
*
|
|
59
|
+
* When processing a chunk, we should include any requiredValues from the covered
|
|
60
|
+
* flows that reference keys in that chunk. This helps the LLM understand what
|
|
61
|
+
* values are expected for those keys.
|
|
62
|
+
*
|
|
63
|
+
* @param chunk - A chunk of the data structure
|
|
64
|
+
* @param executionFlows - All execution flows for the entity
|
|
65
|
+
* @param coveredFlowIds - The flow IDs covered by the current scenario
|
|
66
|
+
* @returns Array of requiredValues that reference keys in this chunk
|
|
67
|
+
*/
|
|
68
|
+
export function getRequiredValuesForChunk(
|
|
69
|
+
chunk: ScenariosDataStructure['dataForMocks'],
|
|
70
|
+
executionFlows: ExecutionFlow[],
|
|
71
|
+
coveredFlowIds: string[],
|
|
72
|
+
): RequiredValue[] {
|
|
73
|
+
if (!chunk || typeof chunk !== 'object') {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const chunkKeys = Object.keys(chunk);
|
|
78
|
+
const relevantValues: RequiredValue[] = [];
|
|
79
|
+
|
|
80
|
+
// Get the covered flows
|
|
81
|
+
const coveredFlows = executionFlows.filter((flow) =>
|
|
82
|
+
coveredFlowIds.includes(flow.id),
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
for (const flow of coveredFlows) {
|
|
86
|
+
if (!flow.requiredValues) continue;
|
|
87
|
+
|
|
88
|
+
for (const rv of flow.requiredValues) {
|
|
89
|
+
if (!rv.attributePath) continue;
|
|
90
|
+
|
|
91
|
+
// Check if this requiredValue references a key in this chunk
|
|
92
|
+
for (const chunkKey of chunkKeys) {
|
|
93
|
+
if (pathMatchesKey(rv.attributePath, chunkKey)) {
|
|
94
|
+
relevantValues.push(rv);
|
|
95
|
+
break; // Don't add the same rv multiple times
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return relevantValues;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if an attributePath references a given dataForMocks key.
|
|
106
|
+
* (Same logic as in extractCriticalDataKeys)
|
|
107
|
+
*/
|
|
108
|
+
function pathMatchesKey(attributePath: string, dataKey: string): boolean {
|
|
109
|
+
const normalizedPath = attributePath.replace('.functionCallReturnValue', '');
|
|
110
|
+
|
|
111
|
+
if (normalizedPath.startsWith(dataKey)) {
|
|
112
|
+
const afterKey = normalizedPath.slice(dataKey.length);
|
|
113
|
+
if (
|
|
114
|
+
afterKey === '' ||
|
|
115
|
+
afterKey.startsWith('.') ||
|
|
116
|
+
afterKey.startsWith('[')
|
|
117
|
+
) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Try matching without type parameters
|
|
123
|
+
const keyWithoutTypes = removeTypeParameters(dataKey);
|
|
124
|
+
const pathWithoutTypes = removeTypeParameters(normalizedPath);
|
|
125
|
+
|
|
126
|
+
if (pathWithoutTypes.startsWith(keyWithoutTypes)) {
|
|
127
|
+
const afterKey = pathWithoutTypes.slice(keyWithoutTypes.length);
|
|
128
|
+
if (
|
|
129
|
+
afterKey === '' ||
|
|
130
|
+
afterKey.startsWith('.') ||
|
|
131
|
+
afterKey.startsWith('[')
|
|
132
|
+
) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Remove type parameters from a function call string.
|
|
142
|
+
*/
|
|
143
|
+
function removeTypeParameters(str: string): string {
|
|
144
|
+
let result = str;
|
|
145
|
+
let prevLength = 0;
|
|
146
|
+
|
|
147
|
+
while (result.length !== prevLength) {
|
|
148
|
+
prevLength = result.length;
|
|
149
|
+
result = result.replace(/<[^<>]*>/g, '');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Re-export extractCriticalDataKeys for backwards compatibility
|
|
156
|
+
export { extractCriticalDataKeys } from './extractCriticalDataKeys';
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as crypto from 'crypto';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* E2E Data Tracking Utility
|
|
7
|
+
*
|
|
8
|
+
* This module helps debug discrepancies between first and second E2E test runs.
|
|
9
|
+
* The first run makes real LLM calls and saves the results.
|
|
10
|
+
* The second run uses cached LLM responses but sometimes produces different data.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* Set CODEYAM_E2E_TRACK_DATA=true to enable tracking
|
|
14
|
+
* Data is saved to /tmp/codeyam-e2e-tracking/
|
|
15
|
+
*
|
|
16
|
+
* First run (no fixtures): Saves snapshots of key data points
|
|
17
|
+
* Second run (with fixtures): Compares current data against saved snapshots
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const TRACKING_DIR = '/tmp/codeyam-e2e-tracking';
|
|
21
|
+
|
|
22
|
+
interface DataSnapshot {
|
|
23
|
+
timestamp: number;
|
|
24
|
+
checkpoint: string;
|
|
25
|
+
entityName?: string;
|
|
26
|
+
scenarioName?: string;
|
|
27
|
+
dataHash: string;
|
|
28
|
+
data: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface ComparisonResult {
|
|
32
|
+
checkpoint: string;
|
|
33
|
+
entityName?: string;
|
|
34
|
+
scenarioName?: string;
|
|
35
|
+
matches: boolean;
|
|
36
|
+
firstRunHash?: string;
|
|
37
|
+
secondRunHash?: string;
|
|
38
|
+
differences?: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let trackingEnabled: boolean | undefined;
|
|
42
|
+
let isFirstRun: boolean | undefined;
|
|
43
|
+
let comparisonResults: ComparisonResult[] = [];
|
|
44
|
+
|
|
45
|
+
function isTrackingEnabled(): boolean {
|
|
46
|
+
if (trackingEnabled === undefined) {
|
|
47
|
+
trackingEnabled = process.env.CODEYAM_E2E_TRACK_DATA === 'true';
|
|
48
|
+
}
|
|
49
|
+
return trackingEnabled;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function determineIfFirstRun(): boolean {
|
|
53
|
+
if (isFirstRun === undefined) {
|
|
54
|
+
// First run = no LLM fixtures directory
|
|
55
|
+
isFirstRun = !process.env.CODEYAM_LLM_FIXTURES_DIR;
|
|
56
|
+
}
|
|
57
|
+
return isFirstRun;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function ensureTrackingDir(): void {
|
|
61
|
+
if (!fs.existsSync(TRACKING_DIR)) {
|
|
62
|
+
fs.mkdirSync(TRACKING_DIR, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function hashData(data: unknown): string {
|
|
67
|
+
const serialized = JSON.stringify(data, null, 0);
|
|
68
|
+
return crypto.createHash('md5').update(serialized).digest('hex');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getSnapshotFilename(
|
|
72
|
+
checkpoint: string,
|
|
73
|
+
entityName?: string,
|
|
74
|
+
scenarioName?: string,
|
|
75
|
+
): string {
|
|
76
|
+
const parts = [checkpoint];
|
|
77
|
+
if (entityName) parts.push(entityName.replace(/[^a-zA-Z0-9]/g, '_'));
|
|
78
|
+
if (scenarioName)
|
|
79
|
+
parts.push(scenarioName.replace(/[^a-zA-Z0-9]/g, '_').substring(0, 30));
|
|
80
|
+
return parts.join('_') + '.json';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Track a data snapshot at a specific checkpoint.
|
|
85
|
+
*
|
|
86
|
+
* On first run: Saves the data to a file for later comparison.
|
|
87
|
+
* On second run: Compares with saved data and logs any differences.
|
|
88
|
+
*
|
|
89
|
+
* @param checkpoint - Unique identifier for this tracking point (e.g., 'completionCall_result', 'parsed_scenarioData')
|
|
90
|
+
* @param data - The data to track
|
|
91
|
+
* @param entityName - Optional entity name for context
|
|
92
|
+
* @param scenarioName - Optional scenario name for context
|
|
93
|
+
*/
|
|
94
|
+
export function trackDataSnapshot(
|
|
95
|
+
checkpoint: string,
|
|
96
|
+
data: unknown,
|
|
97
|
+
entityName?: string,
|
|
98
|
+
scenarioName?: string,
|
|
99
|
+
): void {
|
|
100
|
+
if (!isTrackingEnabled()) return;
|
|
101
|
+
|
|
102
|
+
ensureTrackingDir();
|
|
103
|
+
|
|
104
|
+
const filename = getSnapshotFilename(checkpoint, entityName, scenarioName);
|
|
105
|
+
const filepath = path.join(TRACKING_DIR, filename);
|
|
106
|
+
const currentHash = hashData(data);
|
|
107
|
+
|
|
108
|
+
if (determineIfFirstRun()) {
|
|
109
|
+
// First run: Save the snapshot
|
|
110
|
+
const snapshot: DataSnapshot = {
|
|
111
|
+
timestamp: Date.now(),
|
|
112
|
+
checkpoint,
|
|
113
|
+
entityName,
|
|
114
|
+
scenarioName,
|
|
115
|
+
dataHash: currentHash,
|
|
116
|
+
data,
|
|
117
|
+
};
|
|
118
|
+
fs.writeFileSync(filepath, JSON.stringify(snapshot, null, 2));
|
|
119
|
+
console.log(
|
|
120
|
+
`[E2E Tracking] First run - saved snapshot: ${checkpoint}${entityName ? ` (${entityName})` : ''}${scenarioName ? ` [${scenarioName}]` : ''} hash=${currentHash.substring(0, 8)}`,
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
// Second run: Compare with saved snapshot
|
|
124
|
+
if (fs.existsSync(filepath)) {
|
|
125
|
+
const savedSnapshot: DataSnapshot = JSON.parse(
|
|
126
|
+
fs.readFileSync(filepath, 'utf-8'),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const result: ComparisonResult = {
|
|
130
|
+
checkpoint,
|
|
131
|
+
entityName,
|
|
132
|
+
scenarioName,
|
|
133
|
+
matches: currentHash === savedSnapshot.dataHash,
|
|
134
|
+
firstRunHash: savedSnapshot.dataHash,
|
|
135
|
+
secondRunHash: currentHash,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
if (!result.matches) {
|
|
139
|
+
result.differences = findDifferences(savedSnapshot.data, data);
|
|
140
|
+
console.log(
|
|
141
|
+
`[E2E Tracking] MISMATCH at ${checkpoint}${entityName ? ` (${entityName})` : ''}${scenarioName ? ` [${scenarioName}]` : ''}`,
|
|
142
|
+
);
|
|
143
|
+
console.log(` First run hash: ${savedSnapshot.dataHash}`);
|
|
144
|
+
console.log(` Second run hash: ${currentHash}`);
|
|
145
|
+
|
|
146
|
+
// Save both versions for comparison
|
|
147
|
+
const diffFilepath = filepath.replace('.json', '_DIFF.json');
|
|
148
|
+
fs.writeFileSync(
|
|
149
|
+
diffFilepath,
|
|
150
|
+
JSON.stringify(
|
|
151
|
+
{
|
|
152
|
+
checkpoint,
|
|
153
|
+
entityName,
|
|
154
|
+
scenarioName,
|
|
155
|
+
firstRun: savedSnapshot.data,
|
|
156
|
+
secondRun: data,
|
|
157
|
+
differences: result.differences,
|
|
158
|
+
},
|
|
159
|
+
null,
|
|
160
|
+
2,
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
console.log(` Diff saved to: ${diffFilepath}`);
|
|
164
|
+
} else {
|
|
165
|
+
console.log(
|
|
166
|
+
`[E2E Tracking] Match at ${checkpoint}${entityName ? ` (${entityName})` : ''} hash=${currentHash.substring(0, 8)}`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
comparisonResults.push(result);
|
|
171
|
+
} else {
|
|
172
|
+
console.log(
|
|
173
|
+
`[E2E Tracking] No first-run snapshot found for: ${checkpoint}${entityName ? ` (${entityName})` : ''}`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Find the differences between two data structures.
|
|
181
|
+
* Returns a list of paths where values differ.
|
|
182
|
+
*/
|
|
183
|
+
function findDifferences(
|
|
184
|
+
obj1: unknown,
|
|
185
|
+
obj2: unknown,
|
|
186
|
+
path: string = '',
|
|
187
|
+
): string[] {
|
|
188
|
+
const differences: string[] = [];
|
|
189
|
+
|
|
190
|
+
if (typeof obj1 !== typeof obj2) {
|
|
191
|
+
differences.push(
|
|
192
|
+
`${path || 'root'}: type mismatch (${typeof obj1} vs ${typeof obj2})`,
|
|
193
|
+
);
|
|
194
|
+
return differences;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (obj1 === null || obj2 === null) {
|
|
198
|
+
if (obj1 !== obj2) {
|
|
199
|
+
differences.push(
|
|
200
|
+
`${path || 'root'}: ${JSON.stringify(obj1)} vs ${JSON.stringify(obj2)}`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return differences;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
207
|
+
if (obj1.length !== obj2.length) {
|
|
208
|
+
differences.push(
|
|
209
|
+
`${path || 'root'}: array length ${obj1.length} vs ${obj2.length}`,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
const maxLen = Math.max(obj1.length, obj2.length);
|
|
213
|
+
for (let i = 0; i < maxLen; i++) {
|
|
214
|
+
differences.push(...findDifferences(obj1[i], obj2[i], `${path}[${i}]`));
|
|
215
|
+
}
|
|
216
|
+
return differences;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (typeof obj1 === 'object' && typeof obj2 === 'object') {
|
|
220
|
+
const keys1 = Object.keys(obj1 as Record<string, unknown>);
|
|
221
|
+
const keys2 = Object.keys(obj2 as Record<string, unknown>);
|
|
222
|
+
const allKeys = Array.from(new Set([...keys1, ...keys2]));
|
|
223
|
+
|
|
224
|
+
for (const key of allKeys) {
|
|
225
|
+
const val1 = (obj1 as Record<string, unknown>)[key];
|
|
226
|
+
const val2 = (obj2 as Record<string, unknown>)[key];
|
|
227
|
+
|
|
228
|
+
if (!(key in (obj1 as Record<string, unknown>))) {
|
|
229
|
+
differences.push(
|
|
230
|
+
`${path ? path + '.' : ''}${key}: missing in first run`,
|
|
231
|
+
);
|
|
232
|
+
} else if (!(key in (obj2 as Record<string, unknown>))) {
|
|
233
|
+
differences.push(
|
|
234
|
+
`${path ? path + '.' : ''}${key}: missing in second run`,
|
|
235
|
+
);
|
|
236
|
+
} else {
|
|
237
|
+
differences.push(
|
|
238
|
+
...findDifferences(val1, val2, `${path ? path + '.' : ''}${key}`),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return differences;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Primitive comparison
|
|
246
|
+
if (obj1 !== obj2) {
|
|
247
|
+
const str1 = JSON.stringify(obj1);
|
|
248
|
+
const str2 = JSON.stringify(obj2);
|
|
249
|
+
if (str1.length < 100 && str2.length < 100) {
|
|
250
|
+
differences.push(`${path || 'root'}: ${str1} vs ${str2}`);
|
|
251
|
+
} else {
|
|
252
|
+
differences.push(
|
|
253
|
+
`${path || 'root'}: values differ (${str1.length} chars vs ${str2.length} chars)`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return differences;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get a summary of all comparison results.
|
|
263
|
+
* Call this at the end of the second run to see overall results.
|
|
264
|
+
*/
|
|
265
|
+
export function getTrackingSummary(): {
|
|
266
|
+
total: number;
|
|
267
|
+
matches: number;
|
|
268
|
+
mismatches: number;
|
|
269
|
+
results: ComparisonResult[];
|
|
270
|
+
} {
|
|
271
|
+
const matches = comparisonResults.filter((r) => r.matches).length;
|
|
272
|
+
const mismatches = comparisonResults.filter((r) => !r.matches).length;
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
total: comparisonResults.length,
|
|
276
|
+
matches,
|
|
277
|
+
mismatches,
|
|
278
|
+
results: comparisonResults,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Print a summary of tracking results to console.
|
|
284
|
+
*/
|
|
285
|
+
export function printTrackingSummary(): void {
|
|
286
|
+
if (!isTrackingEnabled()) return;
|
|
287
|
+
|
|
288
|
+
const summary = getTrackingSummary();
|
|
289
|
+
console.log('\n========== E2E Data Tracking Summary ==========');
|
|
290
|
+
console.log(`Total checkpoints: ${summary.total}`);
|
|
291
|
+
console.log(`Matches: ${summary.matches}`);
|
|
292
|
+
console.log(`Mismatches: ${summary.mismatches}`);
|
|
293
|
+
|
|
294
|
+
if (summary.mismatches > 0) {
|
|
295
|
+
console.log('\nMismatched checkpoints:');
|
|
296
|
+
for (const result of summary.results.filter((r) => !r.matches)) {
|
|
297
|
+
console.log(
|
|
298
|
+
` - ${result.checkpoint}${result.entityName ? ` (${result.entityName})` : ''}${result.scenarioName ? ` [${result.scenarioName}]` : ''}`,
|
|
299
|
+
);
|
|
300
|
+
if (result.differences && result.differences.length <= 10) {
|
|
301
|
+
for (const diff of result.differences) {
|
|
302
|
+
console.log(` ${diff}`);
|
|
303
|
+
}
|
|
304
|
+
} else if (result.differences) {
|
|
305
|
+
console.log(
|
|
306
|
+
` (${result.differences.length} differences - see diff file)`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
console.log('================================================\n');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Clear all tracking data. Call this before starting a new test session.
|
|
316
|
+
*/
|
|
317
|
+
export function clearTrackingData(): void {
|
|
318
|
+
if (fs.existsSync(TRACKING_DIR)) {
|
|
319
|
+
const files = fs.readdirSync(TRACKING_DIR);
|
|
320
|
+
for (const file of files) {
|
|
321
|
+
fs.unlinkSync(path.join(TRACKING_DIR, file));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
comparisonResults = [];
|
|
325
|
+
isFirstRun = undefined;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Reset tracking state for a new test run (keeps files, clears in-memory state).
|
|
330
|
+
*/
|
|
331
|
+
export function resetTrackingState(): void {
|
|
332
|
+
comparisonResults = [];
|
|
333
|
+
isFirstRun = undefined;
|
|
334
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { ExecutionFlow, ScenariosDataStructure } from '~codeyam/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract the data structure keys that are critical for satisfying execution flow requirements.
|
|
5
|
+
*
|
|
6
|
+
* When generating scenario mock data, only a subset of the full dataForMocks structure
|
|
7
|
+
* is actually needed to satisfy the scenario's covered flows' requiredValues.
|
|
8
|
+
* This function identifies those critical keys so they can be processed with more focus
|
|
9
|
+
* (e.g., in a separate LLM call or prioritized in the prompt).
|
|
10
|
+
*
|
|
11
|
+
* @param dataForMocks - The full data structure schema
|
|
12
|
+
* @param executionFlows - All execution flows for the entity
|
|
13
|
+
* @param coveredFlowIds - The flow IDs covered by the current scenario
|
|
14
|
+
* @returns Array of top-level keys from dataForMocks that are referenced by the covered flows
|
|
15
|
+
*/
|
|
16
|
+
export function extractCriticalDataKeys(
|
|
17
|
+
dataForMocks: ScenariosDataStructure['dataForMocks'],
|
|
18
|
+
executionFlows: ExecutionFlow[],
|
|
19
|
+
coveredFlowIds: string[],
|
|
20
|
+
): string[] {
|
|
21
|
+
if (!dataForMocks || typeof dataForMocks !== 'object') {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const dataKeys = Object.keys(dataForMocks);
|
|
26
|
+
const criticalKeys = new Set<string>();
|
|
27
|
+
|
|
28
|
+
// Get the covered flows
|
|
29
|
+
const coveredFlows = executionFlows.filter((flow) =>
|
|
30
|
+
coveredFlowIds.includes(flow.id),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// For each covered flow, check if any requiredValue references a dataForMocks key
|
|
34
|
+
for (const flow of coveredFlows) {
|
|
35
|
+
if (!flow.requiredValues) continue;
|
|
36
|
+
|
|
37
|
+
for (const rv of flow.requiredValues) {
|
|
38
|
+
const path = rv.attributePath;
|
|
39
|
+
if (!path) continue;
|
|
40
|
+
|
|
41
|
+
// Try to match the attributePath to a dataForMocks key
|
|
42
|
+
// The path format is: "functionCall().functionCallReturnValue.property"
|
|
43
|
+
// or: "functionCall<Type>().functionCallReturnValue.property"
|
|
44
|
+
// We need to extract the function call part and match it to a key
|
|
45
|
+
|
|
46
|
+
for (const key of dataKeys) {
|
|
47
|
+
if (pathMatchesKey(path, key)) {
|
|
48
|
+
criticalKeys.add(key);
|
|
49
|
+
break; // One match per requiredValue is enough
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return Array.from(criticalKeys);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Check if an attributePath references a given dataForMocks key.
|
|
60
|
+
*
|
|
61
|
+
* Handles various path formats:
|
|
62
|
+
* - "useParams().functionCallReturnValue.*" matches "useParams()"
|
|
63
|
+
* - "useLoaderData<LoaderData>().functionCallReturnValue.data" matches "useLoaderData<LoaderData>()"
|
|
64
|
+
* - "useFetcher().data.success" matches "useFetcher()"
|
|
65
|
+
*/
|
|
66
|
+
function pathMatchesKey(attributePath: string, dataKey: string): boolean {
|
|
67
|
+
// Normalize both for comparison
|
|
68
|
+
// Remove .functionCallReturnValue from the path
|
|
69
|
+
const normalizedPath = attributePath.replace('.functionCallReturnValue', '');
|
|
70
|
+
|
|
71
|
+
// Check if the path starts with the key (exact match for function call keys)
|
|
72
|
+
if (normalizedPath.startsWith(dataKey)) {
|
|
73
|
+
// Ensure it's not a partial match (e.g., "use" shouldn't match "useState")
|
|
74
|
+
const afterKey = normalizedPath.slice(dataKey.length);
|
|
75
|
+
// Valid continuations: end of string, '.', or '['
|
|
76
|
+
if (
|
|
77
|
+
afterKey === '' ||
|
|
78
|
+
afterKey.startsWith('.') ||
|
|
79
|
+
afterKey.startsWith('[')
|
|
80
|
+
) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Try matching without type parameters if needed
|
|
86
|
+
// e.g., "useLoaderData<LoaderData>()" should match attributePaths with same base
|
|
87
|
+
const keyWithoutTypes = removeTypeParameters(dataKey);
|
|
88
|
+
const pathWithoutTypes = removeTypeParameters(normalizedPath);
|
|
89
|
+
|
|
90
|
+
if (pathWithoutTypes.startsWith(keyWithoutTypes)) {
|
|
91
|
+
const afterKey = pathWithoutTypes.slice(keyWithoutTypes.length);
|
|
92
|
+
if (
|
|
93
|
+
afterKey === '' ||
|
|
94
|
+
afterKey.startsWith('.') ||
|
|
95
|
+
afterKey.startsWith('[')
|
|
96
|
+
) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Remove type parameters from a function call string.
|
|
106
|
+
* e.g., "useLoaderData<LoaderData>()" -> "useLoaderData()"
|
|
107
|
+
*/
|
|
108
|
+
function removeTypeParameters(str: string): string {
|
|
109
|
+
// Match and remove <...> including nested angle brackets
|
|
110
|
+
let result = str;
|
|
111
|
+
let prevLength = 0;
|
|
112
|
+
|
|
113
|
+
// Keep removing until no more changes (handles nested generics)
|
|
114
|
+
while (result.length !== prevLength) {
|
|
115
|
+
prevLength = result.length;
|
|
116
|
+
result = result.replace(/<[^<>]*>/g, '');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
}
|