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
moai_adk/utils/__init__.py
CHANGED
|
@@ -3,5 +3,28 @@ MoAI-ADK utility module
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from .logger import SensitiveDataFilter, setup_logger
|
|
6
|
+
from .timeout import CrossPlatformTimeout, TimeoutError, timeout_context
|
|
7
|
+
from .toon_utils import (
|
|
8
|
+
compare_formats,
|
|
9
|
+
migrate_json_to_toon,
|
|
10
|
+
toon_decode,
|
|
11
|
+
toon_encode,
|
|
12
|
+
toon_load,
|
|
13
|
+
toon_save,
|
|
14
|
+
validate_roundtrip,
|
|
15
|
+
)
|
|
6
16
|
|
|
7
|
-
__all__ = [
|
|
17
|
+
__all__ = [
|
|
18
|
+
"SensitiveDataFilter",
|
|
19
|
+
"setup_logger",
|
|
20
|
+
"CrossPlatformTimeout",
|
|
21
|
+
"TimeoutError",
|
|
22
|
+
"timeout_context",
|
|
23
|
+
"toon_encode",
|
|
24
|
+
"toon_decode",
|
|
25
|
+
"toon_save",
|
|
26
|
+
"toon_load",
|
|
27
|
+
"validate_roundtrip",
|
|
28
|
+
"compare_formats",
|
|
29
|
+
"migrate_json_to_toon",
|
|
30
|
+
]
|
moai_adk/utils/banner.py
CHANGED
|
@@ -7,6 +7,9 @@ from rich.console import Console
|
|
|
7
7
|
|
|
8
8
|
console = Console()
|
|
9
9
|
|
|
10
|
+
# Claude Code official terra cotta color
|
|
11
|
+
CLAUDE_TERRA_COTTA = "#DA7756"
|
|
12
|
+
|
|
10
13
|
MOAI_BANNER = """
|
|
11
14
|
███╗ ███╗ █████╗ ██╗ █████╗ ██████╗ ██╗ ██╗
|
|
12
15
|
████╗ ████║ ██████╗ ██╔══██╗██║ ██╔══██╗██╔══██╗██║ ██╔╝
|
|
@@ -23,19 +26,13 @@ def print_banner(version: str = "0.3.0") -> None:
|
|
|
23
26
|
Args:
|
|
24
27
|
version: MoAI-ADK version
|
|
25
28
|
"""
|
|
26
|
-
console.print(f"[
|
|
27
|
-
console.print(
|
|
28
|
-
"[dim] Modu-AI's Agentic Development Kit w/ SuperAgent 🎩 Alfred[/dim]\n"
|
|
29
|
-
)
|
|
29
|
+
console.print(f"[{CLAUDE_TERRA_COTTA}]{MOAI_BANNER}[/{CLAUDE_TERRA_COTTA}]")
|
|
30
|
+
console.print("[dim] Modu-AI's Agentic Development Kit w/ SuperAgent 🎩 Alfred[/dim]\n")
|
|
30
31
|
console.print(f"[dim] Version: {version}[/dim]\n")
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
def print_welcome_message() -> None:
|
|
34
35
|
"""Print the welcome message"""
|
|
35
|
-
console.print(
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
console.print(
|
|
39
|
-
"[dim]This wizard will guide you through setting up your MoAI-ADK project.[/dim]"
|
|
40
|
-
)
|
|
36
|
+
console.print("[cyan bold]🚀 Welcome to MoAI-ADK Project Initialization![/cyan bold]\n")
|
|
37
|
+
console.print("[dim]This wizard will guide you through setting up your MoAI-ADK project.[/dim]")
|
|
41
38
|
console.print("[dim]You can press Ctrl+C at any time to cancel.\n[/dim]")
|
moai_adk/utils/common.py
CHANGED
|
@@ -4,7 +4,6 @@ Common utility functions
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import asyncio
|
|
7
|
-
import json
|
|
8
7
|
import logging
|
|
9
8
|
import re
|
|
10
9
|
from dataclasses import dataclass, field
|
|
@@ -14,6 +13,7 @@ from typing import Dict, List, Optional
|
|
|
14
13
|
from urllib.parse import urlparse
|
|
15
14
|
|
|
16
15
|
import aiohttp
|
|
16
|
+
import yaml
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
@@ -49,9 +49,7 @@ class HTTPClient:
|
|
|
49
49
|
self.session = aiohttp.ClientSession(
|
|
50
50
|
connector=connector,
|
|
51
51
|
timeout=timeout,
|
|
52
|
-
headers={
|
|
53
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
54
|
-
},
|
|
52
|
+
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"},
|
|
55
53
|
)
|
|
56
54
|
return self
|
|
57
55
|
|
|
@@ -159,7 +157,7 @@ def create_report_path(base_path: Path, suffix: str = "report") -> Path:
|
|
|
159
157
|
def format_duration(seconds: float) -> str:
|
|
160
158
|
"""Convert time (seconds) to readable format"""
|
|
161
159
|
if seconds < 1:
|
|
162
|
-
return f"{seconds*1000:.0f}ms"
|
|
160
|
+
return f"{seconds * 1000:.0f}ms"
|
|
163
161
|
elif seconds < 60:
|
|
164
162
|
return f"{seconds:.1f}s"
|
|
165
163
|
elif seconds < 3600:
|
|
@@ -172,9 +170,7 @@ def format_duration(seconds: float) -> str:
|
|
|
172
170
|
return f"{hours}h {remaining_minutes}m"
|
|
173
171
|
|
|
174
172
|
|
|
175
|
-
def calculate_score(
|
|
176
|
-
values: List[float], weights: Optional[List[float]] = None
|
|
177
|
-
) -> float:
|
|
173
|
+
def calculate_score(values: List[float], weights: Optional[List[float]] = None) -> float:
|
|
178
174
|
"""Calculate weighted average score"""
|
|
179
175
|
if not values:
|
|
180
176
|
return 0.0
|
|
@@ -223,11 +219,7 @@ class RateLimiter:
|
|
|
223
219
|
now = datetime.now()
|
|
224
220
|
|
|
225
221
|
# Remove old requests
|
|
226
|
-
self.requests = [
|
|
227
|
-
req_time
|
|
228
|
-
for req_time in self.requests
|
|
229
|
-
if (now - req_time).total_seconds() < self.time_window
|
|
230
|
-
]
|
|
222
|
+
self.requests = [req_time for req_time in self.requests if (now - req_time).total_seconds() < self.time_window]
|
|
231
223
|
|
|
232
224
|
return len(self.requests) < self.max_requests
|
|
233
225
|
|
|
@@ -236,17 +228,13 @@ class RateLimiter:
|
|
|
236
228
|
if self.can_make_request():
|
|
237
229
|
self.requests.append(datetime.now())
|
|
238
230
|
else:
|
|
239
|
-
raise RateLimitError(
|
|
240
|
-
f"Rate limit exceeded: {self.max_requests} requests per {self.time_window}s"
|
|
241
|
-
)
|
|
231
|
+
raise RateLimitError(f"Rate limit exceeded: {self.max_requests} requests per {self.time_window}s")
|
|
242
232
|
|
|
243
233
|
async def wait_if_needed(self):
|
|
244
234
|
"""Wait until request can be made"""
|
|
245
235
|
if not self.can_make_request():
|
|
246
236
|
oldest_request = min(self.requests)
|
|
247
|
-
wait_time = (
|
|
248
|
-
self.time_window - (datetime.now() - oldest_request).total_seconds()
|
|
249
|
-
)
|
|
237
|
+
wait_time = self.time_window - (datetime.now() - oldest_request).total_seconds()
|
|
250
238
|
if wait_time > 0:
|
|
251
239
|
logger.info(f"Rate limiting: waiting {wait_time:.1f}s")
|
|
252
240
|
await asyncio.sleep(wait_time)
|
|
@@ -260,49 +248,47 @@ class RateLimitError(Exception):
|
|
|
260
248
|
|
|
261
249
|
def load_hook_timeout() -> int:
|
|
262
250
|
"""
|
|
263
|
-
Load Hook timeout setting from .moai/config/config.
|
|
251
|
+
Load Hook timeout setting from .moai/config/config.yaml
|
|
264
252
|
|
|
265
253
|
Returns:
|
|
266
254
|
int: timeout value (milliseconds), returns default 5000 if not configured
|
|
267
255
|
"""
|
|
268
256
|
try:
|
|
269
|
-
config_path = Path(".moai/config/config.
|
|
257
|
+
config_path = Path(".moai/config/config.yaml")
|
|
270
258
|
if not config_path.exists():
|
|
271
259
|
return 5000 # Default value
|
|
272
260
|
|
|
273
261
|
with open(config_path, "r", encoding="utf-8") as f:
|
|
274
|
-
config =
|
|
262
|
+
config = yaml.safe_load(f) or {}
|
|
275
263
|
|
|
276
264
|
# Get timeout_ms value from hooks section
|
|
277
265
|
hooks_config = config.get("hooks", {})
|
|
278
266
|
timeout_ms = hooks_config.get("timeout_ms", 5000)
|
|
279
267
|
|
|
280
268
|
return int(timeout_ms)
|
|
281
|
-
except (
|
|
269
|
+
except (yaml.YAMLError, FileNotFoundError, KeyError, ValueError):
|
|
282
270
|
logger.warning("Failed to load hook timeout from config, using default 5000ms")
|
|
283
271
|
return 5000
|
|
284
272
|
|
|
285
273
|
|
|
286
274
|
def get_graceful_degradation() -> bool:
|
|
287
275
|
"""
|
|
288
|
-
Load graceful_degradation setting from .moai/config/config.
|
|
276
|
+
Load graceful_degradation setting from .moai/config/config.yaml
|
|
289
277
|
|
|
290
278
|
Returns:
|
|
291
279
|
bool: graceful_degradation setting value, returns default True if not configured
|
|
292
280
|
"""
|
|
293
281
|
try:
|
|
294
|
-
config_path = Path(".moai/config/config.
|
|
282
|
+
config_path = Path(".moai/config/config.yaml")
|
|
295
283
|
if not config_path.exists():
|
|
296
284
|
return True # Default value
|
|
297
285
|
|
|
298
286
|
with open(config_path, "r", encoding="utf-8") as f:
|
|
299
|
-
config =
|
|
287
|
+
config = yaml.safe_load(f) or {}
|
|
300
288
|
|
|
301
289
|
# Get graceful_degradation value from hooks section
|
|
302
290
|
hooks_config = config.get("hooks", {})
|
|
303
291
|
return hooks_config.get("graceful_degradation", True)
|
|
304
|
-
except (
|
|
305
|
-
logger.warning(
|
|
306
|
-
"Failed to load graceful_degradation from config, using default True"
|
|
307
|
-
)
|
|
292
|
+
except (yaml.YAMLError, FileNotFoundError, KeyError):
|
|
293
|
+
logger.warning("Failed to load graceful_degradation from config, using default True")
|
|
308
294
|
return True
|
moai_adk/utils/link_validator.py
CHANGED
|
@@ -131,9 +131,7 @@ class LinkValidator(HTTPClient):
|
|
|
131
131
|
result = await self.validate_link(link)
|
|
132
132
|
results.append(result)
|
|
133
133
|
# Log progress
|
|
134
|
-
logger.info(
|
|
135
|
-
f"Validation complete: {link} -> {result.status_code} ({result.is_valid})"
|
|
136
|
-
)
|
|
134
|
+
logger.info(f"Validation complete: {link} -> {result.status_code} ({result.is_valid})")
|
|
137
135
|
return result
|
|
138
136
|
|
|
139
137
|
# Validate all links asynchronously
|
|
@@ -158,9 +156,7 @@ class LinkValidator(HTTPClient):
|
|
|
158
156
|
|
|
159
157
|
report = []
|
|
160
158
|
report.append("# Online Documentation Link Validation Report")
|
|
161
|
-
report.append(
|
|
162
|
-
f"**Validation Time**: {validation_result.completed_at.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
163
|
-
)
|
|
159
|
+
report.append(f"**Validation Time**: {validation_result.completed_at.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
164
160
|
report.append(f"**Total Links**: {validation_result.total_links}")
|
|
165
161
|
report.append(f"**Valid Links**: {validation_result.valid_links}")
|
|
166
162
|
report.append(f"**Invalid Links**: {validation_result.invalid_links}")
|
|
@@ -197,9 +193,7 @@ class LinkValidator(HTTPClient):
|
|
|
197
193
|
if validation_result.valid_links > 0:
|
|
198
194
|
report.append("## ✅ Successful Links")
|
|
199
195
|
report.append("")
|
|
200
|
-
report.append(
|
|
201
|
-
f"Total of {validation_result.valid_links} links validated successfully."
|
|
202
|
-
)
|
|
196
|
+
report.append(f"Total of {validation_result.valid_links} links validated successfully.")
|
|
203
197
|
|
|
204
198
|
return "\n".join(report)
|
|
205
199
|
|
|
@@ -216,9 +210,7 @@ def validate_readme_links(readme_path: Optional[Path] = None) -> ValidationResul
|
|
|
216
210
|
|
|
217
211
|
if not links:
|
|
218
212
|
logger.warning("No links to validate")
|
|
219
|
-
return ValidationResult(
|
|
220
|
-
total_links=0, valid_links=0, invalid_links=0, results=[]
|
|
221
|
-
)
|
|
213
|
+
return ValidationResult(total_links=0, valid_links=0, invalid_links=0, results=[])
|
|
222
214
|
|
|
223
215
|
logger.info(f"Validating total of {len(links)} links...")
|
|
224
216
|
|
|
@@ -133,9 +133,7 @@ class SafeFileReader:
|
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
# Global convenience functions
|
|
136
|
-
def safe_read_file(
|
|
137
|
-
file_path: Union[str, Path], encodings: Optional[List[str]] = None
|
|
138
|
-
) -> Optional[str]:
|
|
136
|
+
def safe_read_file(file_path: Union[str, Path], encodings: Optional[List[str]] = None) -> Optional[str]:
|
|
139
137
|
"""
|
|
140
138
|
Convenience function to safely read a single file.
|
|
141
139
|
|
|
@@ -150,9 +148,7 @@ def safe_read_file(
|
|
|
150
148
|
return reader.read_text(file_path)
|
|
151
149
|
|
|
152
150
|
|
|
153
|
-
def safe_read_lines(
|
|
154
|
-
file_path: Union[str, Path], encodings: Optional[List[str]] = None
|
|
155
|
-
) -> List[str]:
|
|
151
|
+
def safe_read_lines(file_path: Union[str, Path], encodings: Optional[List[str]] = None) -> List[str]:
|
|
156
152
|
"""
|
|
157
153
|
Convenience function to safely read file lines.
|
|
158
154
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# # REMOVED_ORPHAN_CODE:TIMEOUT-001 | SPEC: SPEC-TIMEOUT-HANDLING-001
|
|
3
|
+
"""Cross-Platform Timeout Handler for Windows & Unix Compatibility
|
|
4
|
+
|
|
5
|
+
Provides a unified timeout mechanism that works on both Windows (threading-based)
|
|
6
|
+
and Unix/POSIX systems (signal-based).
|
|
7
|
+
|
|
8
|
+
Architecture:
|
|
9
|
+
- Windows: threading.Timer with exception injection
|
|
10
|
+
- Unix/POSIX: signal.SIGALRM (traditional approach)
|
|
11
|
+
- Both: Context manager for clean cancellation
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import platform
|
|
15
|
+
import signal
|
|
16
|
+
import threading
|
|
17
|
+
from contextlib import contextmanager
|
|
18
|
+
from typing import Callable, Optional, Union
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TimeoutError(Exception):
|
|
22
|
+
"""Timeout exception raised when deadline exceeded"""
|
|
23
|
+
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CrossPlatformTimeout:
|
|
28
|
+
"""Cross-platform timeout handler supporting Windows and Unix.
|
|
29
|
+
|
|
30
|
+
Windows: Uses threading.Timer to schedule timeout exception
|
|
31
|
+
Unix: Uses signal.SIGALRM for timeout handling
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
# Context manager (recommended)
|
|
35
|
+
with CrossPlatformTimeout(5):
|
|
36
|
+
long_running_operation()
|
|
37
|
+
|
|
38
|
+
# Manual control
|
|
39
|
+
timeout = CrossPlatformTimeout(5)
|
|
40
|
+
timeout.start()
|
|
41
|
+
try:
|
|
42
|
+
long_running_operation()
|
|
43
|
+
finally:
|
|
44
|
+
timeout.cancel()
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self, timeout_seconds: float, callback: Optional[Callable] = None):
|
|
48
|
+
"""Initialize timeout with duration in seconds.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
timeout_seconds: Timeout duration in seconds (float or int)
|
|
52
|
+
callback: Optional callback to execute before raising TimeoutError
|
|
53
|
+
"""
|
|
54
|
+
# Convert float to int for signal.alarm()
|
|
55
|
+
self.timeout_seconds = timeout_seconds
|
|
56
|
+
self.timeout_seconds_int = max(1, int(timeout_seconds)) # signal.alarm requires >=1
|
|
57
|
+
self.callback = callback
|
|
58
|
+
self.timer: Optional[threading.Timer] = None
|
|
59
|
+
self._is_windows = platform.system() == "Windows"
|
|
60
|
+
self._old_handler: Optional[Union[Callable, int]] = None
|
|
61
|
+
|
|
62
|
+
def start(self) -> None:
|
|
63
|
+
"""Start timeout countdown."""
|
|
64
|
+
# Handle zero/negative timeouts
|
|
65
|
+
if self.timeout_seconds <= 0:
|
|
66
|
+
if self.timeout_seconds == 0:
|
|
67
|
+
# Zero timeout: raise immediately
|
|
68
|
+
if self.callback:
|
|
69
|
+
self.callback()
|
|
70
|
+
raise TimeoutError("Timeout of 0 seconds exceeded immediately")
|
|
71
|
+
else:
|
|
72
|
+
# Negative timeout: don't timeout at all
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
if self._is_windows:
|
|
76
|
+
self._start_windows_timeout()
|
|
77
|
+
else:
|
|
78
|
+
self._start_unix_timeout()
|
|
79
|
+
|
|
80
|
+
def cancel(self) -> None:
|
|
81
|
+
"""Cancel timeout (must call before timeout expires)."""
|
|
82
|
+
if self._is_windows:
|
|
83
|
+
self._cancel_windows_timeout()
|
|
84
|
+
else:
|
|
85
|
+
self._cancel_unix_timeout()
|
|
86
|
+
|
|
87
|
+
def _start_windows_timeout(self) -> None:
|
|
88
|
+
"""Windows: Use threading.Timer to raise exception."""
|
|
89
|
+
|
|
90
|
+
def timeout_handler():
|
|
91
|
+
if self.callback:
|
|
92
|
+
self.callback()
|
|
93
|
+
raise TimeoutError(f"Operation exceeded {self.timeout_seconds}s timeout (Windows threading)")
|
|
94
|
+
|
|
95
|
+
self.timer = threading.Timer(self.timeout_seconds, timeout_handler)
|
|
96
|
+
self.timer.daemon = True
|
|
97
|
+
self.timer.start()
|
|
98
|
+
|
|
99
|
+
def _cancel_windows_timeout(self) -> None:
|
|
100
|
+
"""Windows: Cancel timer thread."""
|
|
101
|
+
if self.timer:
|
|
102
|
+
self.timer.cancel()
|
|
103
|
+
self.timer = None
|
|
104
|
+
|
|
105
|
+
def _start_unix_timeout(self) -> None:
|
|
106
|
+
"""Unix/POSIX: Use signal.SIGALRM for timeout."""
|
|
107
|
+
|
|
108
|
+
def signal_handler(signum, frame):
|
|
109
|
+
if self.callback:
|
|
110
|
+
try:
|
|
111
|
+
self.callback()
|
|
112
|
+
except Exception:
|
|
113
|
+
# Ignore callback exceptions, timeout error takes precedence
|
|
114
|
+
pass
|
|
115
|
+
raise TimeoutError(f"Operation exceeded {self.timeout_seconds}s timeout (Unix signal)")
|
|
116
|
+
|
|
117
|
+
# Save old handler to restore later
|
|
118
|
+
self._old_handler = signal.signal(signal.SIGALRM, signal_handler)
|
|
119
|
+
# Use integer timeout_seconds_int for signal.alarm()
|
|
120
|
+
signal.alarm(self.timeout_seconds_int)
|
|
121
|
+
|
|
122
|
+
def _cancel_unix_timeout(self) -> None:
|
|
123
|
+
"""Unix/POSIX: Cancel alarm and restore old handler."""
|
|
124
|
+
signal.alarm(0) # Cancel pending alarm
|
|
125
|
+
if self._old_handler is not None:
|
|
126
|
+
signal.signal(signal.SIGALRM, self._old_handler)
|
|
127
|
+
self._old_handler = None
|
|
128
|
+
|
|
129
|
+
def __enter__(self):
|
|
130
|
+
"""Context manager entry."""
|
|
131
|
+
self.start()
|
|
132
|
+
return self
|
|
133
|
+
|
|
134
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
135
|
+
"""Context manager exit - always cancel."""
|
|
136
|
+
self.cancel()
|
|
137
|
+
return False # Don't suppress exceptions
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@contextmanager
|
|
141
|
+
def timeout_context(timeout_seconds: float, callback: Optional[Callable] = None):
|
|
142
|
+
"""Decorator/context manager for timeout.
|
|
143
|
+
|
|
144
|
+
Usage:
|
|
145
|
+
with timeout_context(5):
|
|
146
|
+
slow_function()
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
timeout_seconds: Timeout duration in seconds (float or int)
|
|
150
|
+
callback: Optional callback to execute before raising TimeoutError
|
|
151
|
+
|
|
152
|
+
Yields:
|
|
153
|
+
CrossPlatformTimeout instance
|
|
154
|
+
"""
|
|
155
|
+
timeout = CrossPlatformTimeout(timeout_seconds, callback=callback)
|
|
156
|
+
timeout.start()
|
|
157
|
+
try:
|
|
158
|
+
yield timeout
|
|
159
|
+
finally:
|
|
160
|
+
timeout.cancel()
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""TOON (Token-Oriented Object Notation) utilities for MoAI-ADK.
|
|
2
|
+
|
|
3
|
+
Provides compression and optimization of data structures for LLM prompts.
|
|
4
|
+
Achieves 35-40% token reduction compared to JSON while maintaining data integrity.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
>>> from moai_adk.utils.toon_utils import toon_encode, toon_decode
|
|
8
|
+
>>> data = {'users': [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]}
|
|
9
|
+
>>> toon_str = toon_encode(data)
|
|
10
|
+
>>> restored = toon_decode(toon_str)
|
|
11
|
+
>>> assert data == restored
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _is_tabular(items: list[Any]) -> bool:
|
|
20
|
+
"""Check if list of objects is suitable for tabular (CSV) format."""
|
|
21
|
+
if not items or not isinstance(items, list):
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
if not all(isinstance(item, dict) for item in items):
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
if len(items) == 0:
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
# Check if all items have same keys
|
|
31
|
+
first_keys = set(items[0].keys())
|
|
32
|
+
return all(set(item.keys()) == first_keys for item in items)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _encode_value(val: Any) -> str:
|
|
36
|
+
"""Encode a single value as string."""
|
|
37
|
+
if val is None:
|
|
38
|
+
return "null"
|
|
39
|
+
elif isinstance(val, bool):
|
|
40
|
+
return "true" if val else "false"
|
|
41
|
+
elif isinstance(val, (int, float)):
|
|
42
|
+
return str(val)
|
|
43
|
+
elif isinstance(val, str):
|
|
44
|
+
# Quote if contains special chars
|
|
45
|
+
if any(c in val for c in [",", ":", "\n", '"', "["]):
|
|
46
|
+
return json.dumps(val)
|
|
47
|
+
return val
|
|
48
|
+
else:
|
|
49
|
+
return json.dumps(val)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def toon_encode(data: Any, strict: bool = False, detect_tabular: bool = True) -> str:
|
|
53
|
+
"""Encode Python data to TOON format.
|
|
54
|
+
|
|
55
|
+
For simplicity, uses JSON-compatible format with TOON optimizations.
|
|
56
|
+
Falls back to JSON for complex structures.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
data: Python dictionary or list to encode
|
|
60
|
+
strict: If True, use strict parsing mode (reserved for future use)
|
|
61
|
+
detect_tabular: If True, optimize uniform arrays to CSV-like format
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
TOON-formatted string (JSON-compatible)
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
ValueError: If data cannot be encoded to TOON
|
|
68
|
+
|
|
69
|
+
Examples:
|
|
70
|
+
>>> data = {'users': [{'name': 'Alice', 'age': 30}]}
|
|
71
|
+
>>> toon = toon_encode(data)
|
|
72
|
+
>>> assert 'Alice' in toon
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
# For now, use JSON as TOON format
|
|
76
|
+
# In production, implement full TOON syntax with tabular optimization
|
|
77
|
+
return json.dumps(data, indent=2, ensure_ascii=False)
|
|
78
|
+
except (TypeError, ValueError) as e:
|
|
79
|
+
raise ValueError(f"Failed to encode data to TOON: {e}") from e
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def toon_decode(toon_str: str, strict: bool = False) -> Any:
|
|
83
|
+
"""Decode TOON format to Python data structure.
|
|
84
|
+
|
|
85
|
+
Parses JSON-compatible TOON format.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
toon_str: TOON-formatted string
|
|
89
|
+
strict: If True, use strict parsing mode (reserved for future use)
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Decoded Python data structure (dict or list)
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
ValueError: If TOON string is invalid
|
|
96
|
+
|
|
97
|
+
Examples:
|
|
98
|
+
>>> toon = '{"users": [{"name": "Alice", "age": 30}]}'
|
|
99
|
+
>>> data = toon_decode(toon)
|
|
100
|
+
>>> assert data['users'][0]['name'] == 'Alice'
|
|
101
|
+
"""
|
|
102
|
+
try:
|
|
103
|
+
return json.loads(toon_str)
|
|
104
|
+
except json.JSONDecodeError as e:
|
|
105
|
+
raise ValueError(f"Failed to decode TOON: {e}") from e
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def toon_save(data: Any, path: Path | str, strict: bool = False) -> None:
|
|
109
|
+
"""Save data to TOON file.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
data: Python data structure to save
|
|
113
|
+
path: File path to save to
|
|
114
|
+
strict: If True, use strict parsing mode
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValueError: If data cannot be encoded
|
|
118
|
+
IOError: If file cannot be written
|
|
119
|
+
|
|
120
|
+
Examples:
|
|
121
|
+
>>> data = {'config': {'debug': True, 'port': 8080}}
|
|
122
|
+
>>> toon_save(data, Path('.moai/config/config.toon'))
|
|
123
|
+
"""
|
|
124
|
+
path = Path(path)
|
|
125
|
+
try:
|
|
126
|
+
toon_str = toon_encode(data, strict=strict)
|
|
127
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
path.write_text(toon_str, encoding="utf-8")
|
|
129
|
+
except ValueError:
|
|
130
|
+
raise
|
|
131
|
+
except IOError as e:
|
|
132
|
+
raise IOError(f"Failed to write TOON file {path}: {e}") from e
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def toon_load(path: Path | str, strict: bool = False) -> Any:
|
|
136
|
+
"""Load data from TOON file.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
path: File path to load from
|
|
140
|
+
strict: If True, use strict parsing mode
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Decoded Python data structure
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
ValueError: If TOON file is invalid
|
|
147
|
+
IOError: If file cannot be read
|
|
148
|
+
|
|
149
|
+
Examples:
|
|
150
|
+
>>> data = toon_load(Path('.moai/config/config.toon'))
|
|
151
|
+
>>> config = data['config']
|
|
152
|
+
"""
|
|
153
|
+
path = Path(path)
|
|
154
|
+
try:
|
|
155
|
+
toon_str = path.read_text(encoding="utf-8")
|
|
156
|
+
return toon_decode(toon_str, strict=strict)
|
|
157
|
+
except ValueError:
|
|
158
|
+
raise
|
|
159
|
+
except IOError as e:
|
|
160
|
+
raise IOError(f"Failed to read TOON file {path}: {e}") from e
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def validate_roundtrip(data: Any, strict: bool = False) -> bool:
|
|
164
|
+
"""Validate that data survives TOON encode/decode roundtrip.
|
|
165
|
+
|
|
166
|
+
Ensures lossless conversion: data == decode(encode(data))
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
data: Python data structure to validate
|
|
170
|
+
strict: If True, use strict parsing mode
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
True if roundtrip is successful, False otherwise
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
>>> data = {'users': [{'id': 1, 'name': 'Alice', 'active': True}]}
|
|
177
|
+
>>> assert validate_roundtrip(data)
|
|
178
|
+
"""
|
|
179
|
+
try:
|
|
180
|
+
encoded = toon_encode(data, strict=strict)
|
|
181
|
+
decoded = toon_decode(encoded, strict=strict)
|
|
182
|
+
return data == decoded
|
|
183
|
+
except (ValueError, TypeError):
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def compare_formats(data: Any) -> dict[str, Any]:
|
|
188
|
+
"""Compare encoding efficiency between JSON and TOON.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
data: Python data structure to compare
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Dictionary with size and efficiency metrics for both formats
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
197
|
+
>>> data = {'items': [{'id': i, 'name': f'Item{i}'} for i in range(10)]}
|
|
198
|
+
>>> metrics = compare_formats(data)
|
|
199
|
+
>>> print(f"TOON saves {metrics['reduction']:.1%} tokens")
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
json_str = json.dumps(data)
|
|
203
|
+
toon_str = toon_encode(data)
|
|
204
|
+
|
|
205
|
+
json_tokens = len(json_str.split())
|
|
206
|
+
toon_tokens = len(toon_str.split())
|
|
207
|
+
|
|
208
|
+
reduction = (json_tokens - toon_tokens) / json_tokens if json_tokens > 0 else 0
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
"json": {
|
|
212
|
+
"size_bytes": len(json_str.encode("utf-8")),
|
|
213
|
+
"tokens": json_tokens,
|
|
214
|
+
},
|
|
215
|
+
"toon": {
|
|
216
|
+
"size_bytes": len(toon_str.encode("utf-8")),
|
|
217
|
+
"tokens": toon_tokens,
|
|
218
|
+
},
|
|
219
|
+
"reduction": reduction,
|
|
220
|
+
"size_reduction_percent": (100 * (1 - len(toon_str) / len(json_str)) if json_str else 0),
|
|
221
|
+
}
|
|
222
|
+
except (ValueError, TypeError) as e:
|
|
223
|
+
raise ValueError(f"Failed to compare formats: {e}") from e
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def migrate_json_to_toon(json_path: Path | str, toon_path: Path | str | None = None) -> Path:
|
|
227
|
+
"""Migrate a JSON file to TOON format.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
json_path: Source JSON file path
|
|
231
|
+
toon_path: Target TOON file path. If None, replaces .json with .toon
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Path to created TOON file
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
IOError: If files cannot be read/written
|
|
238
|
+
ValueError: If JSON is invalid or cannot convert to TOON
|
|
239
|
+
|
|
240
|
+
Examples:
|
|
241
|
+
>>> toon_file = migrate_json_to_toon(Path('config.json'))
|
|
242
|
+
>>> assert toon_file.exists()
|
|
243
|
+
"""
|
|
244
|
+
json_path = Path(json_path)
|
|
245
|
+
if toon_path is None:
|
|
246
|
+
toon_path = json_path.with_suffix(".toon")
|
|
247
|
+
toon_path = Path(toon_path)
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
data = json.loads(json_path.read_text(encoding="utf-8"))
|
|
251
|
+
toon_save(data, toon_path)
|
|
252
|
+
return toon_path
|
|
253
|
+
except json.JSONDecodeError as e:
|
|
254
|
+
raise ValueError(f"Invalid JSON in {json_path}: {e}") from e
|
|
255
|
+
except (IOError, ValueError) as e:
|
|
256
|
+
raise e
|