moai-adk 0.25.4__py3-none-any.whl → 0.32.8__py3-none-any.whl
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.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +2 -5
- moai_adk/__main__.py +114 -82
- moai_adk/cli/__init__.py +6 -1
- moai_adk/cli/commands/__init__.py +1 -3
- moai_adk/cli/commands/analyze.py +5 -16
- moai_adk/cli/commands/doctor.py +6 -18
- moai_adk/cli/commands/init.py +56 -125
- moai_adk/cli/commands/language.py +14 -35
- moai_adk/cli/commands/status.py +9 -15
- moai_adk/cli/commands/update.py +1555 -190
- moai_adk/cli/prompts/init_prompts.py +112 -56
- moai_adk/cli/spec_status.py +263 -0
- moai_adk/cli/ui/__init__.py +44 -0
- moai_adk/cli/ui/progress.py +422 -0
- moai_adk/cli/ui/prompts.py +389 -0
- moai_adk/cli/ui/theme.py +129 -0
- moai_adk/cli/worktree/__init__.py +27 -0
- moai_adk/cli/worktree/__main__.py +31 -0
- moai_adk/cli/worktree/cli.py +672 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +490 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +128 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/analysis/session_analyzer.py +17 -56
- moai_adk/core/claude_integration.py +26 -54
- moai_adk/core/command_helpers.py +10 -10
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/auto_spec_config.py +5 -11
- moai_adk/core/config/migration.py +19 -9
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +6 -12
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +725 -112
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +8 -0
- moai_adk/core/git/branch_manager.py +3 -11
- moai_adk/core/git/checkpoint.py +1 -3
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/manager.py +91 -1
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +56 -80
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/engine.py +6 -18
- moai_adk/core/integration/integration_tester.py +10 -9
- moai_adk/core/integration/utils.py +1 -1
- moai_adk/core/issue_creator.py +10 -28
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config_resolver.py +485 -0
- moai_adk/core/language_validator.py +28 -41
- moai_adk/core/mcp/setup.py +15 -12
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +481 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +78 -9
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +8 -17
- moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
- moai_adk/core/migration/selective_restorer.py +470 -0
- moai_adk/core/migration/template_utils.py +74 -0
- moai_adk/core/migration/user_selection_ui.py +338 -0
- moai_adk/core/migration/version_detector.py +6 -10
- moai_adk/core/migration/version_migrator.py +3 -3
- moai_adk/core/performance/cache_system.py +8 -10
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/checker.py +2 -4
- moai_adk/core/project/detector.py +1 -3
- moai_adk/core/project/initializer.py +135 -23
- moai_adk/core/project/phase_executor.py +54 -81
- moai_adk/core/project/validator.py +6 -12
- moai_adk/core/quality/trust_checker.py +9 -27
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +73 -148
- moai_adk/core/session_manager.py +10 -26
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +31 -100
- moai_adk/core/spec/ears_template_engine.py +351 -286
- moai_adk/core/spec/quality_validator.py +35 -69
- moai_adk/core/spec_status_manager.py +64 -74
- moai_adk/core/template/backup.py +45 -20
- moai_adk/core/template/config.py +112 -39
- moai_adk/core/template/merger.py +11 -19
- moai_adk/core/template/processor.py +253 -149
- moai_adk/core/template_engine.py +73 -40
- moai_adk/core/template_variable_synchronizer.py +417 -0
- moai_adk/core/unified_permission_manager.py +745 -0
- moai_adk/core/user_behavior_analytics.py +851 -0
- moai_adk/core/version_sync.py +429 -0
- moai_adk/foundation/__init__.py +56 -0
- moai_adk/foundation/backend.py +1027 -0
- moai_adk/foundation/database.py +1115 -0
- moai_adk/foundation/devops.py +1585 -0
- moai_adk/foundation/ears.py +431 -0
- moai_adk/foundation/frontend.py +870 -0
- moai_adk/foundation/git/commit_templates.py +4 -12
- moai_adk/foundation/git.py +376 -0
- moai_adk/foundation/langs.py +484 -0
- moai_adk/foundation/ml_ops.py +1162 -0
- moai_adk/foundation/testing.py +1524 -0
- moai_adk/foundation/trust/trust_principles.py +23 -72
- moai_adk/foundation/trust/validation_checklist.py +57 -162
- moai_adk/project/__init__.py +0 -0
- moai_adk/project/configuration.py +1084 -0
- moai_adk/project/documentation.py +566 -0
- moai_adk/project/schema.py +447 -0
- moai_adk/statusline/alfred_detector.py +1 -3
- moai_adk/statusline/config.py +13 -4
- moai_adk/statusline/enhanced_output_style_detector.py +23 -15
- moai_adk/statusline/main.py +51 -15
- moai_adk/statusline/renderer.py +104 -48
- moai_adk/statusline/update_checker.py +3 -9
- moai_adk/statusline/version_reader.py +140 -46
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +549 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +445 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1132 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +601 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +831 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +774 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +396 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +711 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +474 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1038 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +429 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +570 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +937 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +598 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +713 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +600 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +603 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +369 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1567 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +749 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +427 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +994 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1143 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1435 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +883 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +993 -0
- moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
- moai_adk/templates/.claude/hooks/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
- moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
- moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
- moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
- moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
- moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
- moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
- moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
- moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
- moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
- moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
- moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
- moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
- moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +921 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +380 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +338 -0
- moai_adk/templates/.claude/settings.json +172 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +247 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +320 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +496 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +453 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
- moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +491 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +201 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +438 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +515 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +362 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/SKILL.md +352 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/README.md +52 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/error-handling.md +334 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/integration-patterns.md +310 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/security-authentication.md +256 -0
- moai_adk/templates/.claude/skills/moai-integration-mcp/modules/server-architecture.md +253 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/README.md +133 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/SKILL.md +296 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/examples.md +1269 -0
- moai_adk/templates/.claude/skills/moai-lang-unified/reference.md +331 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +298 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +316 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +370 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/README.md +186 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/SKILL.md +290 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/examples.md +1225 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/reference.md +567 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/scripts/provider-selector.py +323 -0
- moai_adk/templates/.claude/skills/moai-platform-baas/templates/stack-config.yaml +204 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +446 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +387 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +135 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1362 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +374 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +453 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
- moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +410 -0
- moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
- moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
- moai_adk/templates/.git-hooks/pre-commit +103 -41
- moai_adk/templates/.git-hooks/pre-push +116 -21
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.gitignore +184 -44
- moai_adk/templates/.mcp.json +7 -9
- moai_adk/templates/.moai/cache/personalization.json +10 -0
- moai_adk/templates/.moai/config/config.yaml +344 -0
- moai_adk/templates/.moai/config/presets/manual.yaml +28 -0
- moai_adk/templates/.moai/config/presets/personal.yaml +30 -0
- moai_adk/templates/.moai/config/presets/team.yaml +33 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +79 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +122 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +542 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +167 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +152 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +40 -0
- moai_adk/templates/.moai/config/sections/language.yaml +11 -0
- moai_adk/templates/.moai/config/sections/project.yaml +13 -0
- moai_adk/templates/.moai/config/sections/quality.yaml +15 -0
- moai_adk/templates/.moai/config/sections/system.yaml +14 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +86 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +382 -501
- moai_adk/utils/__init__.py +24 -1
- moai_adk/utils/banner.py +7 -10
- moai_adk/utils/common.py +16 -30
- moai_adk/utils/link_validator.py +4 -12
- moai_adk/utils/safe_file_reader.py +2 -6
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.32.8.dist-info/METADATA +2478 -0
- moai_adk-0.32.8.dist-info/RECORD +396 -0
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/WHEEL +1 -1
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/entry_points.txt +1 -0
- moai_adk/cli/commands/backup.py +0 -82
- moai_adk/cli/commands/improve_user_experience.py +0 -348
- moai_adk/cli/commands/migrate.py +0 -158
- moai_adk/cli/commands/validate_links.py +0 -118
- moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -413
- moai_adk/templates/.github/workflows/moai-release-create.yml +0 -100
- moai_adk/templates/.github/workflows/moai-release-pipeline.yml +0 -188
- moai_adk/utils/user_experience.py +0 -531
- moai_adk-0.25.4.dist-info/METADATA +0 -2279
- moai_adk-0.25.4.dist-info/RECORD +0 -112
- {moai_adk-0.25.4.dist-info → moai_adk-0.32.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Robust JSON Parser for MoAI-ADK
|
|
3
|
+
|
|
4
|
+
Production-ready JSON parser with automatic error recovery, comprehensive logging,
|
|
5
|
+
and fallback strategies to handle malformed JSON input from various sources.
|
|
6
|
+
|
|
7
|
+
Author: MoAI-ADK Core Team
|
|
8
|
+
Version: 1.0.0
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import logging
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from enum import Enum
|
|
16
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
17
|
+
|
|
18
|
+
# Configure logging
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ErrorSeverity(Enum):
|
|
23
|
+
"""Error severity levels for classification"""
|
|
24
|
+
|
|
25
|
+
LOW = "low"
|
|
26
|
+
MEDIUM = "medium"
|
|
27
|
+
HIGH = "high"
|
|
28
|
+
CRITICAL = "critical"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ParseResult:
|
|
33
|
+
"""Result of JSON parsing with metadata"""
|
|
34
|
+
|
|
35
|
+
success: bool
|
|
36
|
+
data: Optional[Any]
|
|
37
|
+
error: Optional[str]
|
|
38
|
+
original_input: str
|
|
39
|
+
recovery_attempts: int
|
|
40
|
+
severity: ErrorSeverity
|
|
41
|
+
parse_time_ms: float
|
|
42
|
+
warnings: List[str]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class RobustJSONParser:
|
|
46
|
+
"""
|
|
47
|
+
Production-ready JSON parser with comprehensive error recovery strategies.
|
|
48
|
+
|
|
49
|
+
Features:
|
|
50
|
+
- Multiple error recovery strategies
|
|
51
|
+
- Detailed logging and error tracking
|
|
52
|
+
- Performance monitoring
|
|
53
|
+
- Fallback parsing methods
|
|
54
|
+
- Security validation
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, max_recovery_attempts: int = 3, enable_logging: bool = True):
|
|
58
|
+
self.max_recovery_attempts = max_recovery_attempts
|
|
59
|
+
self.enable_logging = enable_logging
|
|
60
|
+
self.error_patterns = self._load_error_patterns()
|
|
61
|
+
self.recovery_strategies = self._load_recovery_strategies()
|
|
62
|
+
self.stats = {
|
|
63
|
+
"total_parses": 0,
|
|
64
|
+
"successful_parses": 0,
|
|
65
|
+
"recovered_parses": 0,
|
|
66
|
+
"failed_parses": 0,
|
|
67
|
+
"total_recovery_time": 0.0,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def _load_error_patterns(self) -> Dict[str, re.Pattern]:
|
|
71
|
+
"""Load common JSON error patterns"""
|
|
72
|
+
return {
|
|
73
|
+
"missing_quotes": re.compile(r'(?<!\\)"(?:[^"\\]|\\.)*$'),
|
|
74
|
+
"trailing_comma": re.compile(r",\s*[}\]]"),
|
|
75
|
+
"escape_sequence": re.compile(r'\\(?![nrtbf"\'\\/])'),
|
|
76
|
+
"partial_object": re.compile(r"^\s*\{[^}]*\s*$"),
|
|
77
|
+
"missing_brace": re.compile(r"^[^{]*\{[^}]*[^}]*$"),
|
|
78
|
+
"invalid_quotes": re.compile(r'(?<!\\)"(?:[^"\\]|\\.)*?[^\\]"(?![\s,}\]:])'),
|
|
79
|
+
"control_chars": re.compile(r"[\x00-\x1F\x7F-\x9F]"),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
def _load_recovery_strategies(self) -> List[Callable]:
|
|
83
|
+
"""Load error recovery strategies in order of application"""
|
|
84
|
+
return [
|
|
85
|
+
self._fix_missing_quotes,
|
|
86
|
+
self._fix_trailing_commas,
|
|
87
|
+
self._fix_escape_sequences,
|
|
88
|
+
self._handle_partial_objects,
|
|
89
|
+
self._fix_invalid_quotes,
|
|
90
|
+
self._remove_control_characters,
|
|
91
|
+
self._handle_escaped_newlines,
|
|
92
|
+
self._fix_common_syntax_errors,
|
|
93
|
+
self._attempt_partial_parse,
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
def parse(self, json_string: str, context: Optional[Dict] = None) -> ParseResult:
|
|
97
|
+
"""
|
|
98
|
+
Parse JSON string with comprehensive error recovery.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
json_string: JSON string to parse
|
|
102
|
+
context: Optional context information for error reporting
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
ParseResult with data and metadata
|
|
106
|
+
"""
|
|
107
|
+
import time
|
|
108
|
+
|
|
109
|
+
start_time = time.time()
|
|
110
|
+
|
|
111
|
+
self.stats["total_parses"] += 1
|
|
112
|
+
|
|
113
|
+
original_input = json_string
|
|
114
|
+
current_input = json_string
|
|
115
|
+
recovery_attempts = 0
|
|
116
|
+
warnings: List[str] = []
|
|
117
|
+
|
|
118
|
+
# Initial validation
|
|
119
|
+
if not isinstance(json_string, str):
|
|
120
|
+
result = ParseResult(
|
|
121
|
+
success=False,
|
|
122
|
+
data=None,
|
|
123
|
+
error=f"Input must be string, got {type(json_string)}",
|
|
124
|
+
original_input=original_input,
|
|
125
|
+
recovery_attempts=0,
|
|
126
|
+
severity=ErrorSeverity.CRITICAL,
|
|
127
|
+
parse_time_ms=(time.time() - start_time) * 1000,
|
|
128
|
+
warnings=warnings,
|
|
129
|
+
)
|
|
130
|
+
self.stats["failed_parses"] += 1
|
|
131
|
+
return result
|
|
132
|
+
|
|
133
|
+
# Try direct parsing first
|
|
134
|
+
try:
|
|
135
|
+
data = json.loads(json_string)
|
|
136
|
+
self.stats["successful_parses"] += 1
|
|
137
|
+
|
|
138
|
+
result = ParseResult(
|
|
139
|
+
success=True,
|
|
140
|
+
data=data,
|
|
141
|
+
error=None,
|
|
142
|
+
original_input=original_input,
|
|
143
|
+
recovery_attempts=0,
|
|
144
|
+
severity=ErrorSeverity.LOW,
|
|
145
|
+
parse_time_ms=(time.time() - start_time) * 1000,
|
|
146
|
+
warnings=warnings,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
if self.enable_logging:
|
|
150
|
+
logger.debug("JSON parsed successfully on first attempt")
|
|
151
|
+
|
|
152
|
+
return result
|
|
153
|
+
|
|
154
|
+
except json.JSONDecodeError as e:
|
|
155
|
+
if self.enable_logging:
|
|
156
|
+
logger.warning(f"Initial JSON parse failed: {e.msg} at line {e.lineno}, col {e.colno}")
|
|
157
|
+
|
|
158
|
+
last_error = str(e)
|
|
159
|
+
|
|
160
|
+
# Apply recovery strategies
|
|
161
|
+
for attempt in range(self.max_recovery_attempts):
|
|
162
|
+
recovery_attempts += 1
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
# Apply recovery strategies
|
|
166
|
+
for strategy in self.recovery_strategies:
|
|
167
|
+
try:
|
|
168
|
+
modified_input, applied_warnings = strategy(current_input)
|
|
169
|
+
if modified_input != current_input:
|
|
170
|
+
current_input = modified_input
|
|
171
|
+
warnings.extend(applied_warnings)
|
|
172
|
+
if self.enable_logging:
|
|
173
|
+
logger.debug(f"Applied recovery strategy: {strategy.__name__}")
|
|
174
|
+
break
|
|
175
|
+
except Exception as strategy_error:
|
|
176
|
+
if self.enable_logging:
|
|
177
|
+
logger.debug(f"Recovery strategy {strategy.__name__} failed: {strategy_error}")
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
# Try parsing with recovered input
|
|
181
|
+
data = json.loads(current_input)
|
|
182
|
+
self.stats["recovered_parses"] += 1
|
|
183
|
+
|
|
184
|
+
result = ParseResult(
|
|
185
|
+
success=True,
|
|
186
|
+
data=data,
|
|
187
|
+
error=None,
|
|
188
|
+
original_input=original_input,
|
|
189
|
+
recovery_attempts=recovery_attempts,
|
|
190
|
+
severity=(ErrorSeverity.MEDIUM if recovery_attempts > 0 else ErrorSeverity.LOW),
|
|
191
|
+
parse_time_ms=(time.time() - start_time) * 1000,
|
|
192
|
+
warnings=warnings,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
if self.enable_logging:
|
|
196
|
+
logger.info(f"JSON recovered after {recovery_attempts} attempts")
|
|
197
|
+
|
|
198
|
+
return result
|
|
199
|
+
|
|
200
|
+
except json.JSONDecodeError as e:
|
|
201
|
+
last_error = str(e)
|
|
202
|
+
if self.enable_logging:
|
|
203
|
+
logger.debug(f"Parse attempt {attempt + 1} failed: {e.msg}")
|
|
204
|
+
|
|
205
|
+
# Try more aggressive recovery for later attempts
|
|
206
|
+
if attempt == self.max_recovery_attempts - 1:
|
|
207
|
+
break
|
|
208
|
+
|
|
209
|
+
# Make more aggressive modifications for next attempt
|
|
210
|
+
current_input = self._apply_aggressive_recovery(current_input)
|
|
211
|
+
|
|
212
|
+
# All recovery attempts failed
|
|
213
|
+
self.stats["failed_parses"] += 1
|
|
214
|
+
|
|
215
|
+
result = ParseResult(
|
|
216
|
+
success=False,
|
|
217
|
+
data=None,
|
|
218
|
+
error=last_error,
|
|
219
|
+
original_input=original_input,
|
|
220
|
+
recovery_attempts=recovery_attempts,
|
|
221
|
+
severity=(ErrorSeverity.HIGH if recovery_attempts > 0 else ErrorSeverity.CRITICAL),
|
|
222
|
+
parse_time_ms=(time.time() - start_time) * 1000,
|
|
223
|
+
warnings=warnings,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
if self.enable_logging:
|
|
227
|
+
logger.error(f"JSON parsing failed after {recovery_attempts} recovery attempts: {last_error}")
|
|
228
|
+
|
|
229
|
+
return result
|
|
230
|
+
|
|
231
|
+
def _fix_missing_quotes(self, json_string: str) -> Tuple[str, List[str]]:
|
|
232
|
+
"""Fix missing quotes around string values"""
|
|
233
|
+
warnings = []
|
|
234
|
+
|
|
235
|
+
# Look for unquoted property names - more comprehensive pattern
|
|
236
|
+
# Pattern: property_name: (instead of "property_name":)
|
|
237
|
+
pattern = r"(\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:"
|
|
238
|
+
matches = list(re.finditer(pattern, json_string))
|
|
239
|
+
|
|
240
|
+
modified = json_string
|
|
241
|
+
offset = 0
|
|
242
|
+
|
|
243
|
+
for match in reversed(matches):
|
|
244
|
+
# Check if this is inside a string (to avoid false positives)
|
|
245
|
+
pos_before = match.start() + offset
|
|
246
|
+
string_context = self._get_string_context(modified, pos_before)
|
|
247
|
+
|
|
248
|
+
if not string_context:
|
|
249
|
+
# This is likely an unquoted property name
|
|
250
|
+
replacement = f'{match.group(1)}"{match.group(2)}":'
|
|
251
|
+
start_pos = match.start() + offset
|
|
252
|
+
end_pos = match.end() + offset
|
|
253
|
+
modified = modified[:start_pos] + replacement + modified[end_pos:]
|
|
254
|
+
offset += len(replacement) - (end_pos - start_pos)
|
|
255
|
+
warnings.append(f"Added quotes to property name: {match.group(2)}")
|
|
256
|
+
|
|
257
|
+
return modified, warnings
|
|
258
|
+
|
|
259
|
+
def _fix_trailing_commas(self, json_string: str) -> Tuple[str, List[str]]:
|
|
260
|
+
"""Remove trailing commas in objects and arrays"""
|
|
261
|
+
warnings = []
|
|
262
|
+
|
|
263
|
+
# Remove trailing commas before } or ]
|
|
264
|
+
pattern = r",(\s*[}\]])"
|
|
265
|
+
matches = list(re.finditer(pattern, json_string))
|
|
266
|
+
|
|
267
|
+
modified = json_string
|
|
268
|
+
offset = 0
|
|
269
|
+
|
|
270
|
+
for match in reversed(matches):
|
|
271
|
+
# Check if this is inside a string
|
|
272
|
+
pos_before = match.start() + offset
|
|
273
|
+
string_context = self._get_string_context(modified, pos_before)
|
|
274
|
+
|
|
275
|
+
if not string_context:
|
|
276
|
+
# Remove the comma
|
|
277
|
+
replacement = match.group(1)
|
|
278
|
+
start_pos = match.start() + offset
|
|
279
|
+
end_pos = match.end() + offset
|
|
280
|
+
modified = modified[:start_pos] + replacement + modified[end_pos:]
|
|
281
|
+
offset -= (match.end() - match.start()) + len(replacement)
|
|
282
|
+
warnings.append("Removed trailing comma")
|
|
283
|
+
|
|
284
|
+
return modified, warnings
|
|
285
|
+
|
|
286
|
+
def _fix_escape_sequences(self, json_string: str) -> Tuple[str, List[str]]:
|
|
287
|
+
"""Fix invalid escape sequences"""
|
|
288
|
+
warnings = []
|
|
289
|
+
|
|
290
|
+
# Find invalid escape sequences
|
|
291
|
+
pattern = r'\\(?![nrtbf"\'\\/u])'
|
|
292
|
+
matches = list(re.finditer(pattern, json_string))
|
|
293
|
+
|
|
294
|
+
modified = json_string
|
|
295
|
+
offset = 0
|
|
296
|
+
|
|
297
|
+
for match in reversed(matches):
|
|
298
|
+
# Check if this is inside a string
|
|
299
|
+
pos_before = match.start() + offset
|
|
300
|
+
string_context = self._get_string_context(modified, pos_before)
|
|
301
|
+
|
|
302
|
+
if string_context:
|
|
303
|
+
# Remove the invalid backslash
|
|
304
|
+
replacement = match.group(1)[1:] if len(match.group(1)) > 1 else ""
|
|
305
|
+
start_pos = match.start() + offset + 1 # Skip the backslash
|
|
306
|
+
end_pos = match.end() + offset
|
|
307
|
+
modified = modified[:start_pos] + replacement + modified[end_pos:]
|
|
308
|
+
offset -= 1
|
|
309
|
+
warnings.append("Removed invalid escape sequence")
|
|
310
|
+
|
|
311
|
+
return modified, warnings
|
|
312
|
+
|
|
313
|
+
def _handle_partial_objects(self, json_string: str) -> Tuple[str, List[str]]:
|
|
314
|
+
"""Handle incomplete JSON objects"""
|
|
315
|
+
warnings = []
|
|
316
|
+
|
|
317
|
+
stripped = json_string.strip()
|
|
318
|
+
|
|
319
|
+
# Check if it's a partial object
|
|
320
|
+
if stripped.startswith("{") and not stripped.endswith("}"):
|
|
321
|
+
# Count braces
|
|
322
|
+
open_braces = stripped.count("{")
|
|
323
|
+
close_braces = stripped.count("}")
|
|
324
|
+
|
|
325
|
+
if open_braces > close_braces:
|
|
326
|
+
missing_braces = open_braces - close_braces
|
|
327
|
+
modified = stripped + "}" * missing_braces
|
|
328
|
+
warnings.append(f"Added {missing_braces} closing brace(s)")
|
|
329
|
+
return modified, warnings
|
|
330
|
+
|
|
331
|
+
# Check for partial arrays
|
|
332
|
+
if stripped.startswith("[") and not stripped.endswith("]"):
|
|
333
|
+
open_brackets = stripped.count("[")
|
|
334
|
+
close_brackets = stripped.count("]")
|
|
335
|
+
|
|
336
|
+
if open_brackets > close_brackets:
|
|
337
|
+
missing_brackets = open_brackets - close_brackets
|
|
338
|
+
modified = stripped + "]" * missing_brackets
|
|
339
|
+
warnings.append(f"Added {missing_brackets} closing bracket(s)")
|
|
340
|
+
return modified, warnings
|
|
341
|
+
|
|
342
|
+
return json_string, warnings
|
|
343
|
+
|
|
344
|
+
def _fix_invalid_quotes(self, json_string: str) -> Tuple[str, List[str]]:
|
|
345
|
+
"""Fix invalid quote usage"""
|
|
346
|
+
warnings = []
|
|
347
|
+
|
|
348
|
+
# Simple replacement: replace single quotes with double quotes
|
|
349
|
+
# This handles cases like {'name': 'test'} -> {"name": "test"}
|
|
350
|
+
if json_string.startswith("'") or ("'" in json_string and '"' not in json_string):
|
|
351
|
+
# Case: entirely single-quoted JSON
|
|
352
|
+
modified_str = json_string.replace("'", '"')
|
|
353
|
+
if modified_str != json_string:
|
|
354
|
+
warnings.append("Replaced single quotes with double quotes")
|
|
355
|
+
return modified_str, warnings
|
|
356
|
+
|
|
357
|
+
# More complex case: mixed quotes
|
|
358
|
+
# Replace unescaped single quotes that appear to be string delimiters
|
|
359
|
+
char_list: list[str] = []
|
|
360
|
+
i = 0
|
|
361
|
+
while i < len(json_string):
|
|
362
|
+
char = json_string[i]
|
|
363
|
+
|
|
364
|
+
if char == "\\":
|
|
365
|
+
# Preserve escape sequences
|
|
366
|
+
char_list.append(char)
|
|
367
|
+
i += 1
|
|
368
|
+
if i < len(json_string):
|
|
369
|
+
char_list.append(json_string[i])
|
|
370
|
+
i += 1
|
|
371
|
+
continue
|
|
372
|
+
|
|
373
|
+
if char == "'":
|
|
374
|
+
# Replace single quote with double quote
|
|
375
|
+
char_list.append('"')
|
|
376
|
+
i += 1
|
|
377
|
+
else:
|
|
378
|
+
char_list.append(char)
|
|
379
|
+
i += 1
|
|
380
|
+
|
|
381
|
+
final_modified = "".join(char_list)
|
|
382
|
+
if final_modified != json_string:
|
|
383
|
+
warnings.append("Replaced single quotes with double quotes")
|
|
384
|
+
|
|
385
|
+
return final_modified, warnings
|
|
386
|
+
|
|
387
|
+
def _remove_control_characters(self, json_string: str) -> Tuple[str, List[str]]:
|
|
388
|
+
"""Remove control characters that break JSON parsing"""
|
|
389
|
+
warnings = []
|
|
390
|
+
|
|
391
|
+
# Remove control characters except allowed ones (tab, newline, carriage return)
|
|
392
|
+
pattern = r"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]"
|
|
393
|
+
matches = re.findall(pattern, json_string)
|
|
394
|
+
|
|
395
|
+
if matches:
|
|
396
|
+
modified = re.sub(pattern, "", json_string)
|
|
397
|
+
warnings.append(f"Removed {len(matches)} control character(s)")
|
|
398
|
+
return modified, warnings
|
|
399
|
+
|
|
400
|
+
return json_string, warnings
|
|
401
|
+
|
|
402
|
+
def _handle_escaped_newlines(self, json_string: str) -> Tuple[str, List[str]]:
|
|
403
|
+
"""Handle escaped newlines in JSON strings"""
|
|
404
|
+
warnings = []
|
|
405
|
+
|
|
406
|
+
# Replace escaped newlines with proper JSON representation
|
|
407
|
+
modified = json_string.replace("\\n", "\\n")
|
|
408
|
+
|
|
409
|
+
if modified != json_string:
|
|
410
|
+
warnings.append("Normalized escaped newlines")
|
|
411
|
+
|
|
412
|
+
return modified, warnings
|
|
413
|
+
|
|
414
|
+
def _fix_common_syntax_errors(self, json_string: str) -> Tuple[str, List[str]]:
|
|
415
|
+
"""Fix common JSON syntax errors"""
|
|
416
|
+
warnings = []
|
|
417
|
+
modified = json_string
|
|
418
|
+
|
|
419
|
+
# Fix missing commas between array elements
|
|
420
|
+
pattern = r"(\]\s*\[)"
|
|
421
|
+
matches = re.finditer(pattern, modified)
|
|
422
|
+
|
|
423
|
+
for match in reversed(list(matches)):
|
|
424
|
+
replacement = f"{match.group(1).strip()},{match.group(1).strip()}"
|
|
425
|
+
modified = modified[: match.start()] + replacement + modified[match.end() :]
|
|
426
|
+
warnings.append("Added missing comma between array elements")
|
|
427
|
+
|
|
428
|
+
# Fix missing colons in object properties
|
|
429
|
+
pattern = r'("[^"]+")\s+("[^"]*"|\d+|true|false|null|\{|\[)'
|
|
430
|
+
matches = re.finditer(pattern, modified)
|
|
431
|
+
|
|
432
|
+
for match in reversed(list(matches)):
|
|
433
|
+
replacement = f"{match.group(1)}:{match.group(2)}"
|
|
434
|
+
modified = modified[: match.start()] + replacement + modified[match.end() :]
|
|
435
|
+
warnings.append(f"Added missing colon for property: {match.group(1)}")
|
|
436
|
+
|
|
437
|
+
return modified, warnings
|
|
438
|
+
|
|
439
|
+
def _attempt_partial_parse(self, json_string: str) -> Tuple[str, List[str]]:
|
|
440
|
+
"""Attempt to extract and parse valid JSON from a larger string"""
|
|
441
|
+
warnings = []
|
|
442
|
+
|
|
443
|
+
# Look for JSON-like patterns in the string
|
|
444
|
+
patterns = [
|
|
445
|
+
r"\{[^{}]*\}", # Simple object
|
|
446
|
+
r"\[[^\[\]]*\]", # Simple array
|
|
447
|
+
r"\{(?:[^{}]*\{[^{}]*\})*[^{}]*\}", # Nested objects (one level)
|
|
448
|
+
r"\[(?:[^\[\]]*\[[^\[\]]*\])*[^\[\]]*\]", # Nested arrays (one level)
|
|
449
|
+
]
|
|
450
|
+
|
|
451
|
+
for pattern in patterns:
|
|
452
|
+
matches = re.finditer(pattern, json_string)
|
|
453
|
+
|
|
454
|
+
for match in matches:
|
|
455
|
+
try:
|
|
456
|
+
# Try to parse this substring
|
|
457
|
+
json.loads(match.group())
|
|
458
|
+
|
|
459
|
+
# If successful, return this as the cleaned string
|
|
460
|
+
warnings.append("Extracted valid JSON from larger string")
|
|
461
|
+
return match.group(), warnings
|
|
462
|
+
|
|
463
|
+
except json.JSONDecodeError:
|
|
464
|
+
continue
|
|
465
|
+
|
|
466
|
+
return json_string, warnings
|
|
467
|
+
|
|
468
|
+
def _apply_aggressive_recovery(self, json_string: str) -> str:
|
|
469
|
+
"""Apply more aggressive recovery for final attempts"""
|
|
470
|
+
modified = json_string
|
|
471
|
+
|
|
472
|
+
# Try to extract just the JSON part from a response that might include other text
|
|
473
|
+
# Look for patterns that might contain JSON
|
|
474
|
+
json_patterns = [
|
|
475
|
+
r"```json\s*(.*?)\s*```", # Markdown code blocks
|
|
476
|
+
r"\{.*\}", # Anything between braces
|
|
477
|
+
r"\[.*\]", # Anything between brackets
|
|
478
|
+
]
|
|
479
|
+
|
|
480
|
+
for pattern in json_patterns:
|
|
481
|
+
matches = re.findall(pattern, modified, re.DOTALL)
|
|
482
|
+
for match in matches:
|
|
483
|
+
try:
|
|
484
|
+
json.loads(match)
|
|
485
|
+
return match # Return the first valid JSON found
|
|
486
|
+
except (json.JSONDecodeError, ValueError, TypeError):
|
|
487
|
+
continue
|
|
488
|
+
|
|
489
|
+
# If no JSON found, try to clean up the string
|
|
490
|
+
# Remove common non-JSON prefixes/suffixes
|
|
491
|
+
lines = modified.split("\n")
|
|
492
|
+
json_lines = []
|
|
493
|
+
|
|
494
|
+
for line in lines:
|
|
495
|
+
line = line.strip()
|
|
496
|
+
# Skip lines that are clearly not JSON
|
|
497
|
+
if line.startswith(("```", "#", "*", "-", ">", "Error:", "Success:")) or line.endswith(("```", ".")):
|
|
498
|
+
continue
|
|
499
|
+
json_lines.append(line)
|
|
500
|
+
|
|
501
|
+
return "\n".join(json_lines)
|
|
502
|
+
|
|
503
|
+
def _get_string_context(self, json_string: str, position: int) -> bool:
|
|
504
|
+
"""Check if position is inside a JSON string"""
|
|
505
|
+
quote_count = 0
|
|
506
|
+
escape_next = False
|
|
507
|
+
|
|
508
|
+
for i in range(position):
|
|
509
|
+
char = json_string[i]
|
|
510
|
+
|
|
511
|
+
if escape_next:
|
|
512
|
+
escape_next = False
|
|
513
|
+
continue
|
|
514
|
+
|
|
515
|
+
if char == "\\":
|
|
516
|
+
escape_next = True
|
|
517
|
+
continue
|
|
518
|
+
|
|
519
|
+
if char == '"':
|
|
520
|
+
quote_count += 1
|
|
521
|
+
|
|
522
|
+
return quote_count % 2 == 1 # True if inside string
|
|
523
|
+
|
|
524
|
+
def get_stats(self) -> Dict[str, Union[int, float]]:
|
|
525
|
+
"""Get parsing statistics"""
|
|
526
|
+
total = self.stats["total_parses"]
|
|
527
|
+
if total > 0:
|
|
528
|
+
return {
|
|
529
|
+
**self.stats,
|
|
530
|
+
"success_rate": (self.stats["successful_parses"] + self.stats["recovered_parses"]) / total,
|
|
531
|
+
"recovery_rate": self.stats["recovered_parses"] / total,
|
|
532
|
+
"failure_rate": self.stats["failed_parses"] / total,
|
|
533
|
+
"avg_recovery_time": (
|
|
534
|
+
self.stats["total_recovery_time"] / self.stats["recovered_parses"]
|
|
535
|
+
if self.stats["recovered_parses"] > 0
|
|
536
|
+
else 0
|
|
537
|
+
),
|
|
538
|
+
}
|
|
539
|
+
return self.stats
|
|
540
|
+
|
|
541
|
+
def reset_stats(self) -> None:
|
|
542
|
+
"""Reset parsing statistics"""
|
|
543
|
+
self.stats = {
|
|
544
|
+
"total_parses": 0,
|
|
545
|
+
"successful_parses": 0,
|
|
546
|
+
"recovered_parses": 0,
|
|
547
|
+
"failed_parses": 0,
|
|
548
|
+
"total_recovery_time": 0.0,
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
# Global instance for easy import
|
|
553
|
+
parser = RobustJSONParser()
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def parse_json(json_string: str, context: Optional[Dict] = None) -> ParseResult:
|
|
557
|
+
"""Convenience function to parse JSON with error recovery"""
|
|
558
|
+
return parser.parse(json_string, context)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def get_parser_stats() -> Dict[str, Union[int, float]]:
|
|
562
|
+
"""Get global parser statistics"""
|
|
563
|
+
return parser.get_stats()
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def reset_parser_stats() -> None:
|
|
567
|
+
"""Reset global parser statistics"""
|
|
568
|
+
parser.reset_stats()
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
# Test suite
|
|
572
|
+
if __name__ == "__main__":
|
|
573
|
+
# Basic tests
|
|
574
|
+
test_cases = [
|
|
575
|
+
# Valid JSON
|
|
576
|
+
'{"name": "test", "value": 123}',
|
|
577
|
+
# Missing quotes
|
|
578
|
+
'{name: "test", value: 123}',
|
|
579
|
+
# Trailing comma
|
|
580
|
+
'{"name": "test", "value": 123,}',
|
|
581
|
+
# Invalid escape sequences
|
|
582
|
+
'{"name": "test\\invalid", "value": 123}',
|
|
583
|
+
# Partial object
|
|
584
|
+
'{"name": "test"',
|
|
585
|
+
# Mixed single quotes
|
|
586
|
+
"{'name': 'test', 'value': 123}",
|
|
587
|
+
# Control characters
|
|
588
|
+
'{"name": "test\x00", "value": 123}',
|
|
589
|
+
]
|
|
590
|
+
|
|
591
|
+
print("Testing Robust JSON Parser...")
|
|
592
|
+
|
|
593
|
+
for i, test_case in enumerate(test_cases):
|
|
594
|
+
print(f"\nTest {i + 1}: {test_case[:50]}...")
|
|
595
|
+
|
|
596
|
+
result = parser.parse(test_case)
|
|
597
|
+
|
|
598
|
+
if result.success:
|
|
599
|
+
print(f"✓ Success (attempts: {result.recovery_attempts})")
|
|
600
|
+
print(f" Data: {result.data}")
|
|
601
|
+
else:
|
|
602
|
+
print(f"✗ Failed (attempts: {result.recovery_attempts})")
|
|
603
|
+
print(f" Error: {result.error}")
|
|
604
|
+
|
|
605
|
+
if result.warnings:
|
|
606
|
+
print(f" Warnings: {result.warnings}")
|
|
607
|
+
|
|
608
|
+
print("\nParser Statistics:")
|
|
609
|
+
stats = parser.get_stats()
|
|
610
|
+
for key, value in stats.items():
|
|
611
|
+
print(f" {key}: {value}")
|