@leejungkiin/awkit 1.7.1 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/awk.js +576 -84
- package/core/CLAUDE.md +1 -1
- package/core/GEMINI.md +148 -167
- package/core/GEMINI.md.bak +149 -116
- package/core/skill-runtime-manifest.json +3 -0
- package/docs/Claude Fable 5.md +3826 -0
- package/docs/android_kotlin_system_instruction.md +210 -0
- package/docs/brainstorm_ponytail_integration.md +146 -0
- package/docs/brainstorm_smart_setup.md +113 -0
- package/docs/deep-research-report (1).md +293 -0
- package/docs/history/GEMINI.v1.md +135 -0
- package/docs/history/brainstorm_antigravity_unified_architecture.v1.md +105 -0
- package/docs/history/implementation_plan.v1.md +58 -0
- package/package.json +4 -1
- package/scripts/artifact-storage.js +130 -0
- package/scripts/automation-gate.js +35 -2
- package/scripts/claude-plan.js +76 -0
- package/scripts/dependency-manager.js +210 -0
- package/scripts/exec-rtk.js +11 -5
- package/scripts/i18n-helper.js +381 -0
- package/scripts/multi-model-pipeline.js +144 -0
- package/skill-packs/mobile-ios/pack.json +4 -2
- package/skill-packs/reverse-engineering/pack.json +1 -0
- package/skills/CATALOG.md +20 -0
- package/skills/GEMINI.md +9 -1
- package/skills/TRIGGER_INDEX.md +10 -0
- package/skills/ai-music/SKILL.md +275 -0
- package/skills/android-re-analyzer/SKILL.md +238 -0
- package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
- package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
- package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
- package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
- package/skills/android-re-analyzer/references/setup-guide.md +221 -0
- package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
- package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
- package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
- package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
- package/skills/animal-island-ui-style/SKILL.md +1450 -0
- package/skills/app-store-review-agent/SKILL.md +164 -0
- package/skills/app-store-review-agent/references/guidelines/README.md +154 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/ai_apps.md +37 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/all_apps.md +50 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/crypto_finance.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/games.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/health_fitness.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/kids.md +27 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/macos.md +38 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/social_ugc.md +32 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/subscription_iap.md +34 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/vpn.md +18 -0
- package/skills/app-store-review-agent/references/rules/design/minimum_functionality.md +96 -0
- package/skills/app-store-review-agent/references/rules/design/sign_in_with_apple.md +54 -0
- package/skills/app-store-review-agent/references/rules/entitlements/unused_entitlements.md +83 -0
- package/skills/app-store-review-agent/references/rules/metadata/accurate_metadata.md +54 -0
- package/skills/app-store-review-agent/references/rules/metadata/apple_trademark.md +99 -0
- package/skills/app-store-review-agent/references/rules/metadata/china_storefront.md +72 -0
- package/skills/app-store-review-agent/references/rules/metadata/competitor_terms.md +56 -0
- package/skills/app-store-review-agent/references/rules/metadata/subscription_metadata.md +81 -0
- package/skills/app-store-review-agent/references/rules/privacy/privacy_manifest.md +84 -0
- package/skills/app-store-review-agent/references/rules/privacy/unnecessary_data.md +60 -0
- package/skills/app-store-review-agent/references/rules/subscription/misleading_pricing.md +63 -0
- package/skills/app-store-review-agent/references/rules/subscription/missing_tos_pp.md +54 -0
- package/skills/awf-ponytail/SKILL.md +91 -0
- package/skills/awf-ponytail-review/SKILL.md +67 -0
- package/skills/awf-session-restore/SKILL.md +3 -3
- package/skills/brainstorm-agent/SKILL.md +11 -2
- package/skills/brainstorm-agent/templates/brief-template.md +8 -0
- package/skills/claude-planner/SKILL.md +47 -0
- package/skills/code-review/SKILL.md +87 -0
- package/skills/expo-game-development/SKILL.md +163 -0
- package/skills/flutter/LICENSE.txt +202 -0
- package/skills/flutter/SKILL.md +127 -0
- package/skills/flutter-project-creater/LICENSE.txt +202 -0
- package/skills/flutter-project-creater/SKILL.md +106 -0
- package/skills/game-developer/SKILL.md +163 -0
- package/skills/game-developer/references/ecs-patterns.md +501 -0
- package/skills/game-developer/references/multiplayer-networking.md +475 -0
- package/skills/game-developer/references/performance-optimization.md +422 -0
- package/skills/game-developer/references/unity-patterns.md +271 -0
- package/skills/game-developer/references/unreal-cpp.md +352 -0
- package/skills/generate-gui-assets/SKILL.md +305 -0
- package/skills/generate-gui-assets/agents/openai.yaml +4 -0
- package/skills/generate-gui-assets/references/catalog-schema.md +58 -0
- package/skills/generate-gui-assets/references/extraction-techniques.md +21 -0
- package/skills/generate-gui-assets/references/prompt-patterns.md +58 -0
- package/skills/generate-gui-assets/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/generate-gui-assets/scripts/build_gui_contact_sheet.py +51 -0
- package/skills/generate-gui-assets/scripts/clean_chroma_edges.py +262 -0
- package/skills/generate-gui-assets/scripts/copy_approved_icons.py +64 -0
- package/skills/generate-gui-assets/scripts/prepare_gui_asset_run.py +91 -0
- package/skills/generate-gui-assets/scripts/suggest_grid_options.py +63 -0
- package/skills/generate-gui-assets/scripts/validate_gui_catalog.py +50 -0
- package/skills/godot-game-development/SKILL.md +142 -0
- package/skills/hatch-pet/LICENSE.txt +201 -0
- package/skills/hatch-pet/SKILL.md +420 -0
- package/skills/hatch-pet/agents/openai.yaml +4 -0
- package/skills/hatch-pet/references/animation-rows.md +29 -0
- package/skills/hatch-pet/references/codex-pet-contract.md +35 -0
- package/skills/hatch-pet/references/qa-rubric.md +60 -0
- package/skills/hatch-pet/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/hatch-pet/scripts/clean_chroma_edges.py +262 -0
- package/skills/hatch-pet/scripts/compose_atlas.py +150 -0
- package/skills/hatch-pet/scripts/derive_running_left_from_running_right.py +143 -0
- package/skills/hatch-pet/scripts/extract_strip_frames.py +323 -0
- package/skills/hatch-pet/scripts/finalize_pet_run.py +382 -0
- package/skills/hatch-pet/scripts/generate_pet_images.py +287 -0
- package/skills/hatch-pet/scripts/inspect_frames.py +246 -0
- package/skills/hatch-pet/scripts/make_contact_sheet.py +96 -0
- package/skills/hatch-pet/scripts/package_custom_pet.py +108 -0
- package/skills/hatch-pet/scripts/pet_job_status.py +117 -0
- package/skills/hatch-pet/scripts/prepare_pet_run.py +673 -0
- package/skills/hatch-pet/scripts/queue_pet_repairs.py +172 -0
- package/skills/hatch-pet/scripts/record_imagegen_result.py +250 -0
- package/skills/hatch-pet/scripts/render_animation_videos.py +134 -0
- package/skills/hatch-pet/scripts/render_animation_videos.sh +5 -0
- package/skills/hatch-pet/scripts/validate_atlas.py +139 -0
- package/skills/i18n-orchestrator/SKILL.md +37 -0
- package/skills/ios-simulator-skill/SKILL.md +390 -0
- package/skills/ios-simulator-skill/scripts/accessibility_audit.py +300 -0
- package/skills/ios-simulator-skill/scripts/app_launcher.py +326 -0
- package/skills/ios-simulator-skill/scripts/app_state_capture.py +400 -0
- package/skills/ios-simulator-skill/scripts/appearance.py +385 -0
- package/skills/ios-simulator-skill/scripts/build_and_test.py +348 -0
- package/skills/ios-simulator-skill/scripts/clipboard.py +103 -0
- package/skills/ios-simulator-skill/scripts/common/__init__.py +61 -0
- package/skills/ios-simulator-skill/scripts/common/cache_utils.py +289 -0
- package/skills/ios-simulator-skill/scripts/common/device_utils.py +462 -0
- package/skills/ios-simulator-skill/scripts/common/env_config.py +35 -0
- package/skills/ios-simulator-skill/scripts/common/hang_pipeline.py +862 -0
- package/skills/ios-simulator-skill/scripts/common/hang_sessions.py +490 -0
- package/skills/ios-simulator-skill/scripts/common/idb_utils.py +180 -0
- package/skills/ios-simulator-skill/scripts/common/screenshot_utils.py +338 -0
- package/skills/ios-simulator-skill/scripts/container.py +668 -0
- package/skills/ios-simulator-skill/scripts/gesture.py +394 -0
- package/skills/ios-simulator-skill/scripts/hang_watcher.py +1533 -0
- package/skills/ios-simulator-skill/scripts/keyboard.py +391 -0
- package/skills/ios-simulator-skill/scripts/localization_audit.py +483 -0
- package/skills/ios-simulator-skill/scripts/location.py +467 -0
- package/skills/ios-simulator-skill/scripts/log_monitor.py +493 -0
- package/skills/ios-simulator-skill/scripts/model_inspector.py +645 -0
- package/skills/ios-simulator-skill/scripts/navigator.py +461 -0
- package/skills/ios-simulator-skill/scripts/privacy_manager.py +310 -0
- package/skills/ios-simulator-skill/scripts/push_notification.py +240 -0
- package/skills/ios-simulator-skill/scripts/screen_mapper.py +296 -0
- package/skills/ios-simulator-skill/scripts/sim_health_check.sh +245 -0
- package/skills/ios-simulator-skill/scripts/sim_list.py +299 -0
- package/skills/ios-simulator-skill/scripts/simctl_boot.py +312 -0
- package/skills/ios-simulator-skill/scripts/simctl_create.py +316 -0
- package/skills/ios-simulator-skill/scripts/simctl_delete.py +357 -0
- package/skills/ios-simulator-skill/scripts/simctl_erase.py +351 -0
- package/skills/ios-simulator-skill/scripts/simctl_shutdown.py +290 -0
- package/skills/ios-simulator-skill/scripts/simulator_selector.py +375 -0
- package/skills/ios-simulator-skill/scripts/status_bar.py +250 -0
- package/skills/ios-simulator-skill/scripts/test_recorder.py +323 -0
- package/skills/ios-simulator-skill/scripts/visual_diff.py +235 -0
- package/skills/ios-simulator-skill/scripts/xcode/__init__.py +13 -0
- package/skills/ios-simulator-skill/scripts/xcode/builder.py +397 -0
- package/skills/ios-simulator-skill/scripts/xcode/cache.py +204 -0
- package/skills/ios-simulator-skill/scripts/xcode/config.py +178 -0
- package/skills/ios-simulator-skill/scripts/xcode/reporter.py +343 -0
- package/skills/ios-simulator-skill/scripts/xcode/xcresult.py +451 -0
- package/skills/ios-visual-qa-strategist/SKILL.md +111 -0
- package/skills/ios-visual-qa-strategist/agents/openai.yaml +4 -0
- package/skills/ios-visual-qa-strategist/references/ios-tool-selection.md +61 -0
- package/skills/ios-visual-qa-strategist/references/minimal-capture-policy.md +56 -0
- package/skills/ios-visual-qa-strategist/references/visual-reasoning-heuristics.md +53 -0
- package/skills/orchestrator/SKILL.md +0 -20
- package/skills/persistent-storage/SKILL.md +55 -0
- package/skills/short-maker/SKILL.md +23 -0
- package/skills/short-maker/scripts/effects.js +56 -0
- package/skills/short-maker/scripts/shortmaker-bridge.js +332 -0
- package/skills/short-maker/scripts/videomix.js +601 -0
- package/skills/short-maker/templates/hyperframes/cinematic-character.template.html +172 -0
- package/skills/short-maker/templates/hyperframes/index.template.html +194 -0
- package/skills/smali-to-kotlin/SKILL.md +128 -0
- package/skills/smali-to-kotlin/examples/getting-started/tech-stack.md +58 -0
- package/skills/smali-to-kotlin/examples/pipeline/data-ui-parity.md +118 -0
- package/skills/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +106 -0
- package/skills/smali-to-kotlin/library-patterns.md +189 -0
- package/skills/smali-to-kotlin/phase-0-discovery.md +128 -0
- package/skills/smali-to-kotlin/phase-1-architecture.md +166 -0
- package/skills/smali-to-kotlin/phase-2-blueprint-ui.md +347 -0
- package/skills/smali-to-kotlin/phase-2-blueprint.md +228 -0
- package/skills/smali-to-kotlin/phase-3-build.md +248 -0
- package/skills/smali-to-kotlin/phase-3-logic-build.md +268 -0
- package/skills/smali-to-kotlin/smali-reading-guide.md +310 -0
- package/skills/smali-to-kotlin/templates/app-map.md +101 -0
- package/skills/smali-to-kotlin/templates/architecture.md +142 -0
- package/skills/smali-to-kotlin/templates/blueprint.md +145 -0
- package/skills/spec-gate/SKILL.md +6 -2
- package/skills/symphony-enforcer/SKILL.md +8 -0
- package/skills/symphony-enforcer/examples/mindful-stop.md +2 -0
- package/skills/symphony-enforcer/examples/three-phase.md +16 -0
- package/skills/symphony-enforcer/examples/trigger-points.md +7 -1
- package/skills/unity-game-development/SKILL.md +231 -0
- package/skills/video-edit/SKILL.md +36 -0
- package/skills/video-edit/scripts/video_edit.py +324 -0
- package/templates/project-identity/android.json +2 -2
- package/templates/project-identity/backend-nestjs.json +2 -2
- package/templates/project-identity/expo.json +2 -2
- package/templates/project-identity/ios.json +2 -2
- package/templates/project-identity/web-nextjs.json +2 -2
- package/templates/setup-mapping.json +48 -0
- package/templates/specs/design-template.md +161 -71
- package/templates/specs/requirements-template.md +65 -133
- package/templates/specs/task-spec-template.xml +3 -0
- package/workflows/_uncategorized/critic.md +40 -0
- package/workflows/_uncategorized/git-rebase-flow.md +81 -0
- package/workflows/_uncategorized/image-gen.md +118 -0
- package/workflows/_uncategorized/multi-model-pipeline.md +60 -0
- package/workflows/_uncategorized/pixel-gen.md +86 -0
- package/workflows/_uncategorized/pixel-setup.md +90 -0
- package/workflows/_uncategorized/ponytail-review.md +59 -0
- package/workflows/_uncategorized/reverse-android-build.md +222 -0
- package/workflows/_uncategorized/reverse-android-design.md +139 -0
- package/workflows/_uncategorized/reverse-android-discover.md +150 -0
- package/workflows/_uncategorized/reverse-android-scan.md +158 -0
- package/workflows/_uncategorized/reverse-android.md +143 -0
- package/workflows/_uncategorized/reverse-ios-build.md +240 -0
- package/workflows/_uncategorized/reverse-ios-design.md +112 -0
- package/workflows/_uncategorized/reverse-ios-discover.md +120 -0
- package/workflows/_uncategorized/reverse-ios-scan.md +155 -0
- package/workflows/_uncategorized/reverse-ios.md +152 -0
- package/workflows/_uncategorized/safety-router.md +34 -0
- package/workflows/_uncategorized/teach.md +89 -0
- package/workflows/_uncategorized/verify-ui.md +53 -0
- package/workflows/_uncategorized/visualize-screenshots.md +34 -0
- package/workflows/ads/ads-analyst.md +201 -0
- package/workflows/ads/ads-audit.md +106 -0
- package/workflows/ads/ads-optimize.md +97 -0
- package/workflows/ads/ads-targeting.md +241 -0
- package/workflows/ads/adsExpert.md +160 -0
- package/workflows/ads/smali-ads-config.md +400 -0
- package/workflows/ads/smali-ads-flow.md +331 -0
- package/workflows/ads/smali-ads-interstitial.md +377 -0
- package/workflows/ads/smali-ads-native.md +382 -0
- package/workflows/context/teach.md +89 -0
- package/workflows/gitnexus.md +8 -8
- package/workflows/lifecycle/brainstorm.md +43 -0
- package/workflows/lifecycle/code.md +5 -0
- package/workflows/lifecycle/init.md +23 -5
- package/workflows/lifecycle/multi-model-pipeline.md +60 -0
- package/workflows/quality/ponytail-review.md +59 -0
- package/workflows/roles/critic.md +40 -0
- package/workflows/roles/safety-router.md +34 -0
package/bin/awk.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* awkit list-packs List available skill packs
|
|
20
20
|
* awkit tg setup Setup Telegram Bot API credentials
|
|
21
21
|
* awkit tg send Send a message via Telegram Bot API
|
|
22
|
+
* awkit build Run project build command securely based on configuration
|
|
22
23
|
* awkit version Show current version
|
|
23
24
|
*
|
|
24
25
|
* Created by Kien AI
|
|
@@ -43,6 +44,11 @@ const { cmdGate } = require('../scripts/automation-gate');
|
|
|
43
44
|
const { cmdObsidian } = require('../scripts/obsidian-sync');
|
|
44
45
|
const { cmdQuota } = require('../scripts/cockpit-quota');
|
|
45
46
|
const { cmdVideo } = require('../scripts/video-analyzer');
|
|
47
|
+
const { cmdI18n } = require('../scripts/i18n-helper');
|
|
48
|
+
const { cmdStorage } = require('../scripts/artifact-storage');
|
|
49
|
+
const { cmdPipeline } = require('../scripts/multi-model-pipeline');
|
|
50
|
+
const depManager = require('../scripts/dependency-manager');
|
|
51
|
+
|
|
46
52
|
|
|
47
53
|
// ─── Platform Definitions ──────────────────────────────────────────────────
|
|
48
54
|
|
|
@@ -368,7 +374,7 @@ function copyDirRecursive(src, dest, options = {}) {
|
|
|
368
374
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
369
375
|
|
|
370
376
|
for (const entry of entries) {
|
|
371
|
-
if (entry.name === '.DS_Store' || entry.name === '.git') continue;
|
|
377
|
+
if (entry.name === '.DS_Store' || entry.name === '.git' || entry.name === '.venv' || entry.name === 'node_modules') continue;
|
|
372
378
|
|
|
373
379
|
const srcPath = path.join(src, entry.name);
|
|
374
380
|
|
|
@@ -898,14 +904,19 @@ function cmdUpdate() {
|
|
|
898
904
|
log(`${C.gray} local repo: v${AWK_VERSION}${C.reset}`);
|
|
899
905
|
log('');
|
|
900
906
|
|
|
901
|
-
// 3. Already up-to-date?
|
|
902
|
-
if (npmLatest
|
|
903
|
-
|
|
904
|
-
|
|
907
|
+
// 3. Already up-to-date or newer?
|
|
908
|
+
if (npmLatest) {
|
|
909
|
+
if (npmLatest === installedVersion) {
|
|
910
|
+
ok(`Already on the latest version (v${installedVersion}) 🎉`);
|
|
911
|
+
return;
|
|
912
|
+
} else if (isNewerVersion(installedVersion, npmLatest)) {
|
|
913
|
+
ok(`Your installed version (v${installedVersion}) is newer than the npm registry version (v${npmLatest}) 🎉`);
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
905
916
|
}
|
|
906
917
|
|
|
907
918
|
// 4. New version available on npm → install from registry
|
|
908
|
-
if (npmLatest && npmLatest
|
|
919
|
+
if (npmLatest && isNewerVersion(npmLatest, installedVersion)) {
|
|
909
920
|
info(`Upgrading: v${installedVersion} → v${npmLatest}`);
|
|
910
921
|
info('Running: npm install -g @leejungkiin/awkit');
|
|
911
922
|
try {
|
|
@@ -924,13 +935,15 @@ function cmdUpdate() {
|
|
|
924
935
|
// 5. Offline fallback: compare AWK_VERSION (local repo) vs installed
|
|
925
936
|
if (installedVersion === AWK_VERSION) {
|
|
926
937
|
ok(`Already on latest version (v${AWK_VERSION}) — could not verify with npm`);
|
|
927
|
-
} else {
|
|
938
|
+
} else if (isNewerVersion(AWK_VERSION, installedVersion)) {
|
|
928
939
|
info(`Upgrading from v${installedVersion} → v${AWK_VERSION} (local only, npm unreachable)`);
|
|
929
940
|
cmdInstall(['--update']);
|
|
941
|
+
} else {
|
|
942
|
+
ok(`Your installed version (v${installedVersion}) is newer than or equal to local repo version (v${AWK_VERSION})`);
|
|
930
943
|
}
|
|
931
944
|
}
|
|
932
945
|
|
|
933
|
-
function cmdDoctor() {
|
|
946
|
+
async function cmdDoctor() {
|
|
934
947
|
log('');
|
|
935
948
|
log(`${C.cyan}${C.bold}🏥 AWK Health Check${C.reset}`);
|
|
936
949
|
log('');
|
|
@@ -998,16 +1011,27 @@ function cmdDoctor() {
|
|
|
998
1011
|
warn('schemas/ directory missing'); issues++;
|
|
999
1012
|
}
|
|
1000
1013
|
|
|
1001
|
-
// 4.5. Check RTK Integration
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1014
|
+
// 4.5. Check RTK & GitNexus Integration
|
|
1015
|
+
if (depManager.checkRtk()) {
|
|
1016
|
+
ok(`RTK (Rust Token Killer) is installed (v${depManager.getRtkVersion() || 'unknown'})`);
|
|
1017
|
+
} else {
|
|
1018
|
+
warn('RTK (Rust Token Killer) not found.');
|
|
1019
|
+
if (promptYN('Would you like to install RTK automatically now?')) {
|
|
1020
|
+
depManager.installRtk();
|
|
1006
1021
|
} else {
|
|
1007
|
-
|
|
1022
|
+
issues++;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
if (depManager.checkGitnexus()) {
|
|
1027
|
+
ok('GitNexus (Code Intelligence Indexer) is installed and active');
|
|
1028
|
+
} else {
|
|
1029
|
+
warn('GitNexus (Code Intelligence Indexer) not found.');
|
|
1030
|
+
if (promptYN('Would you like to install GitNexus globally now?')) {
|
|
1031
|
+
depManager.installGitnexus();
|
|
1032
|
+
} else {
|
|
1033
|
+
issues++;
|
|
1008
1034
|
}
|
|
1009
|
-
} catch (e) {
|
|
1010
|
-
warn(`RTK check failed: ${e.message}`);
|
|
1011
1035
|
}
|
|
1012
1036
|
|
|
1013
1037
|
// 5. Check version
|
|
@@ -1021,6 +1045,25 @@ function cmdDoctor() {
|
|
|
1021
1045
|
warn('Version file missing. Run "awkit install" first.'); issues++;
|
|
1022
1046
|
}
|
|
1023
1047
|
|
|
1048
|
+
// 5.5. Check Updates
|
|
1049
|
+
try {
|
|
1050
|
+
const updates = await depManager.checkUpdates(AWK_VERSION);
|
|
1051
|
+
if (updates.latestAwkit && isNewerVersion(updates.latestAwkit, AWK_VERSION)) {
|
|
1052
|
+
warn(`AWKit update available: v${updates.latestAwkit} (current: v${AWK_VERSION})`);
|
|
1053
|
+
} else {
|
|
1054
|
+
ok('AWKit is up-to-date');
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const currentRtk = depManager.getRtkVersion();
|
|
1058
|
+
if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
|
|
1059
|
+
warn(`RTK update available: v${updates.latestRtk} (current: v${currentRtk})`);
|
|
1060
|
+
} else if (currentRtk) {
|
|
1061
|
+
ok('RTK is up-to-date');
|
|
1062
|
+
}
|
|
1063
|
+
} catch (e) {
|
|
1064
|
+
warn(`Update check failed: ${e.message}`);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1024
1067
|
log('');
|
|
1025
1068
|
log(`${C.bold}Runtime Profile:${C.reset}`);
|
|
1026
1069
|
log(` Profile: ${C.cyan}${installState.profile}${C.reset}`);
|
|
@@ -1710,15 +1753,19 @@ function cmdListPacks() {
|
|
|
1710
1753
|
}
|
|
1711
1754
|
|
|
1712
1755
|
for (const pack of packs) {
|
|
1713
|
-
const readmePath = path.join(packsDir, pack.name, 'README.md');
|
|
1714
1756
|
const configPath = path.join(packsDir, pack.name, 'pack.json');
|
|
1757
|
+
const config = fs.existsSync(configPath) ? readJsonFile(configPath, {}) : {};
|
|
1758
|
+
if (config.hidden === true) {
|
|
1759
|
+
continue;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
const readmePath = path.join(packsDir, pack.name, 'README.md');
|
|
1715
1763
|
let desc = '';
|
|
1716
1764
|
if (fs.existsSync(readmePath)) {
|
|
1717
1765
|
const content = fs.readFileSync(readmePath, 'utf8');
|
|
1718
1766
|
desc = content.split('\n').find(l => l.trim() && !l.startsWith('#')) || '';
|
|
1719
1767
|
}
|
|
1720
|
-
if (!desc
|
|
1721
|
-
const config = readJsonFile(configPath, {});
|
|
1768
|
+
if (!desc) {
|
|
1722
1769
|
desc = config.description || '';
|
|
1723
1770
|
}
|
|
1724
1771
|
log(` ${C.green}${pack.name}${C.reset} ${C.gray}${desc}${C.reset}`);
|
|
@@ -1938,6 +1985,47 @@ function cmdSync() {
|
|
|
1938
1985
|
log('');
|
|
1939
1986
|
}
|
|
1940
1987
|
|
|
1988
|
+
// ─── Build: Safe project-specific compilation ────────────────────────────────
|
|
1989
|
+
|
|
1990
|
+
function cmdBuild() {
|
|
1991
|
+
log('');
|
|
1992
|
+
log(`${C.cyan}${C.bold}🔨 AWK Build Control${C.reset}`);
|
|
1993
|
+
log('');
|
|
1994
|
+
|
|
1995
|
+
const pjPath = path.join(process.cwd(), '.project-identity');
|
|
1996
|
+
const pj = readJsonFile(pjPath, {});
|
|
1997
|
+
|
|
1998
|
+
if (!pj.automation || !pj.automation.build) {
|
|
1999
|
+
warn('No build configuration found in .project-identity under "automation.build".');
|
|
2000
|
+
log('Skipping build...');
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
const { enabled, command } = pj.automation.build;
|
|
2005
|
+
|
|
2006
|
+
if (!enabled) {
|
|
2007
|
+
warn('Build is disabled for this project (automation.build.enabled is false).');
|
|
2008
|
+
log('Skipping build...');
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
if (!command) {
|
|
2013
|
+
err('Build command is not configured in .project-identity (automation.build.command is empty).');
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
info(`Running build command: ${C.bold}${command}${C.reset}`);
|
|
2018
|
+
try {
|
|
2019
|
+
execSync(command, { stdio: 'inherit' });
|
|
2020
|
+
log('');
|
|
2021
|
+
ok('Build successful!');
|
|
2022
|
+
} catch (e) {
|
|
2023
|
+
log('');
|
|
2024
|
+
err(`Build failed: ${e.message}`);
|
|
2025
|
+
process.exit(1);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
|
|
1941
2029
|
async function cmdAdmin() {
|
|
1942
2030
|
info('Mở Symphony Dashboard...');
|
|
1943
2031
|
try {
|
|
@@ -2035,6 +2123,29 @@ function cmdHelp() {
|
|
|
2035
2123
|
log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
|
|
2036
2124
|
log('');
|
|
2037
2125
|
|
|
2126
|
+
// Project Context Detector
|
|
2127
|
+
const cwd = process.cwd();
|
|
2128
|
+
const identityPath = path.join(cwd, '.project-identity');
|
|
2129
|
+
if (fs.existsSync(identityPath)) {
|
|
2130
|
+
try {
|
|
2131
|
+
const raw = fs.readFileSync(identityPath, 'utf8');
|
|
2132
|
+
const identity = JSON.parse(raw);
|
|
2133
|
+
const icon = identity.icon || '⚡';
|
|
2134
|
+
const name = identity.projectName || 'Unnamed Project';
|
|
2135
|
+
const pType = identity.projectType ? `Type: ${identity.projectType}` : 'Type: Generic';
|
|
2136
|
+
|
|
2137
|
+
let bCmd = 'Disabled';
|
|
2138
|
+
if (identity.automation && identity.automation.build && identity.automation.build.enabled) {
|
|
2139
|
+
bCmd = identity.automation.build.command || 'Enabled';
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
log(`${C.cyan}👉 Active Project: ${icon} ${C.bold}${name}${C.reset}`);
|
|
2143
|
+
log(` [${pType} | Build Control: ${bCmd === 'Disabled' ? C.yellow + 'Manual' : C.green + bCmd}${C.reset}]`);
|
|
2144
|
+
log(` Run ${C.green}awkit identity${C.reset} for full configuration details.`);
|
|
2145
|
+
log('');
|
|
2146
|
+
} catch (_) {}
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2038
2149
|
// Install
|
|
2039
2150
|
log(`${C.bold}⚙️ Setup${C.reset}`);
|
|
2040
2151
|
log(line);
|
|
@@ -2056,6 +2167,8 @@ function cmdHelp() {
|
|
|
2056
2167
|
log(` ${C.gray} --force${C.reset} Overwrite existing files`);
|
|
2057
2168
|
log(` ${C.gray} Generates: .project-identity, <Name>.code-workspace,${C.reset}`);
|
|
2058
2169
|
log(` ${C.gray} CODEBASE.md, thiết lập router (AGENTS.md, CLAUDE.md)${C.reset}`);
|
|
2170
|
+
log(` ${C.green}identity${C.reset} Show project identity & active configurations (alias: config)`);
|
|
2171
|
+
log(` ${C.green}build${C.reset} Run project build based on .project-identity config`);
|
|
2059
2172
|
log('');
|
|
2060
2173
|
|
|
2061
2174
|
// Maintenance
|
|
@@ -2098,6 +2211,24 @@ function cmdHelp() {
|
|
|
2098
2211
|
log(` ${C.green}disable-pack${C.reset} <name> Uninstall a skill pack (backed up)`);
|
|
2099
2212
|
log('');
|
|
2100
2213
|
|
|
2214
|
+
// Storage
|
|
2215
|
+
log(`${C.bold}🗄️ Storage${C.reset}`);
|
|
2216
|
+
log(line);
|
|
2217
|
+
log(` ${C.green}storage set${C.reset} <key> <val> Save key-value pair`);
|
|
2218
|
+
log(` ${C.green}storage get${C.reset} <key> Retrieve value by key`);
|
|
2219
|
+
log(` ${C.green}storage delete${C.reset} <key> Delete key`);
|
|
2220
|
+
log(` ${C.green}storage list${C.reset} [prefix] List keys with optional prefix`);
|
|
2221
|
+
log(` ${C.gray} --shared Access shared storage space${C.reset}`);
|
|
2222
|
+
log('');
|
|
2223
|
+
|
|
2224
|
+
// Pipeline
|
|
2225
|
+
log(`${C.bold}🔗 Pipeline${C.reset}`);
|
|
2226
|
+
log(line);
|
|
2227
|
+
log(` ${C.green}pipeline plan${C.reset} <Feature> Lập kế hoạch kiến trúc (Opus 4.6 via agy)`);
|
|
2228
|
+
log(` ${C.green}pipeline ui${C.reset} <Feature> Thiết kế shell & GUI assets (Codex)`);
|
|
2229
|
+
log(` ${C.green}pipeline code${C.reset} <Feature> Thực thi viết code & review (Gemini + Critic)`);
|
|
2230
|
+
log('');
|
|
2231
|
+
|
|
2101
2232
|
// Trello
|
|
2102
2233
|
log(`${C.bold}📋 Trello${C.reset}`);
|
|
2103
2234
|
log(line);
|
|
@@ -2139,6 +2270,11 @@ function cmdHelp() {
|
|
|
2139
2270
|
if (packs.length) {
|
|
2140
2271
|
log(` Available packs:`);
|
|
2141
2272
|
for (const p of packs) {
|
|
2273
|
+
const configPath = path.join(packsDir, p.name, 'pack.json');
|
|
2274
|
+
const config = fs.existsSync(configPath) ? readJsonFile(configPath, {}) : {};
|
|
2275
|
+
if (config.hidden === true) {
|
|
2276
|
+
continue;
|
|
2277
|
+
}
|
|
2142
2278
|
const readmePath = path.join(packsDir, p.name, 'README.md');
|
|
2143
2279
|
let tagline = '';
|
|
2144
2280
|
if (fs.existsSync(readmePath)) {
|
|
@@ -2212,10 +2348,55 @@ function detectProjectType(cwd) {
|
|
|
2212
2348
|
if (entries.includes('pubspec.yaml')) {
|
|
2213
2349
|
return 'flutter';
|
|
2214
2350
|
}
|
|
2351
|
+
|
|
2352
|
+
// JS/Node project check
|
|
2353
|
+
if (entries.includes('package.json')) {
|
|
2354
|
+
try {
|
|
2355
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
2356
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2357
|
+
if (pkg.bin) {
|
|
2358
|
+
return 'cli';
|
|
2359
|
+
}
|
|
2360
|
+
if (deps['next']) {
|
|
2361
|
+
return 'web-nextjs';
|
|
2362
|
+
}
|
|
2363
|
+
if (deps['@nestjs/core']) {
|
|
2364
|
+
return 'backend-nestjs';
|
|
2365
|
+
}
|
|
2366
|
+
return 'node';
|
|
2367
|
+
} catch (_) { /* continue */ }
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2215
2370
|
// Default: generic mobile-firebase
|
|
2216
2371
|
return 'mobile-firebase';
|
|
2217
2372
|
}
|
|
2218
2373
|
|
|
2374
|
+
/**
|
|
2375
|
+
* Get the default safe build command based on projectType.
|
|
2376
|
+
*/
|
|
2377
|
+
function getDefaultBuildCommand(projectType) {
|
|
2378
|
+
switch (projectType) {
|
|
2379
|
+
case 'ios':
|
|
2380
|
+
return 'xcodebuild -scheme YourScheme -sdk iphonesimulator -configuration Debug';
|
|
2381
|
+
case 'android':
|
|
2382
|
+
return './gradlew assembleDebug';
|
|
2383
|
+
case 'expo':
|
|
2384
|
+
return 'npx expo prebuild';
|
|
2385
|
+
case 'flutter':
|
|
2386
|
+
return 'flutter build apk --debug';
|
|
2387
|
+
case 'web-nextjs':
|
|
2388
|
+
return 'npm run build';
|
|
2389
|
+
case 'backend-nestjs':
|
|
2390
|
+
return 'npm run build';
|
|
2391
|
+
case 'cli':
|
|
2392
|
+
case 'node':
|
|
2393
|
+
return 'npm test';
|
|
2394
|
+
case 'mobile-firebase':
|
|
2395
|
+
default:
|
|
2396
|
+
return 'npm run build';
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2219
2400
|
/**
|
|
2220
2401
|
* Build .project-identity object from detected type + project name.
|
|
2221
2402
|
*/
|
|
@@ -2326,6 +2507,70 @@ function buildProjectIdentity(projectName, projectType, cwd, date) {
|
|
|
2326
2507
|
servicesDir: 'lib/shared/services',
|
|
2327
2508
|
modelsDir: 'lib/shared/models',
|
|
2328
2509
|
},
|
|
2510
|
+
cli: {
|
|
2511
|
+
projectType: 'cli',
|
|
2512
|
+
techStack: {
|
|
2513
|
+
platform: 'CLI',
|
|
2514
|
+
language: 'JavaScript / TypeScript',
|
|
2515
|
+
runtime: 'Node.js',
|
|
2516
|
+
framework: 'Vanilla NodeJS',
|
|
2517
|
+
testing: 'Jest / doctor',
|
|
2518
|
+
},
|
|
2519
|
+
codingStandards: { language: 'en', namingConvention: 'camelCase', indentation: 'spaces-4', lineLength: 120 },
|
|
2520
|
+
architecture: 'Modular',
|
|
2521
|
+
featuresDir: 'src/commands',
|
|
2522
|
+
sharedUIDir: 'src/ui',
|
|
2523
|
+
servicesDir: 'src/services',
|
|
2524
|
+
modelsDir: 'src/models',
|
|
2525
|
+
},
|
|
2526
|
+
node: {
|
|
2527
|
+
projectType: 'node',
|
|
2528
|
+
techStack: {
|
|
2529
|
+
platform: 'NodeJS Backend/App',
|
|
2530
|
+
language: 'JavaScript / TypeScript',
|
|
2531
|
+
runtime: 'Node.js',
|
|
2532
|
+
testing: 'Jest',
|
|
2533
|
+
},
|
|
2534
|
+
codingStandards: { language: 'en', namingConvention: 'camelCase', indentation: 'spaces-4', lineLength: 120 },
|
|
2535
|
+
architecture: 'Modular',
|
|
2536
|
+
featuresDir: 'src/features',
|
|
2537
|
+
sharedUIDir: 'src/views',
|
|
2538
|
+
servicesDir: 'src/services',
|
|
2539
|
+
modelsDir: 'src/models',
|
|
2540
|
+
},
|
|
2541
|
+
'web-nextjs': {
|
|
2542
|
+
projectType: 'web-nextjs',
|
|
2543
|
+
techStack: {
|
|
2544
|
+
platform: 'Web',
|
|
2545
|
+
language: 'TypeScript / JavaScript',
|
|
2546
|
+
framework: 'Next.js',
|
|
2547
|
+
styling: 'Tailwind CSS / CSS Modules',
|
|
2548
|
+
stateManagement: 'Zustand / Redux Toolkit / React Context',
|
|
2549
|
+
networking: 'Axios / Fetch',
|
|
2550
|
+
},
|
|
2551
|
+
codingStandards: { language: 'en', namingConvention: 'camelCase', indentation: 'spaces-2', lineLength: 100 },
|
|
2552
|
+
architecture: 'App Router / Pages Router',
|
|
2553
|
+
featuresDir: 'src/app',
|
|
2554
|
+
sharedUIDir: 'src/components',
|
|
2555
|
+
servicesDir: 'src/services',
|
|
2556
|
+
modelsDir: 'src/models',
|
|
2557
|
+
},
|
|
2558
|
+
'backend-nestjs': {
|
|
2559
|
+
projectType: 'backend-nestjs',
|
|
2560
|
+
techStack: {
|
|
2561
|
+
platform: 'Backend',
|
|
2562
|
+
language: 'TypeScript',
|
|
2563
|
+
framework: 'NestJS',
|
|
2564
|
+
database: 'PostgreSQL / MySQL / MongoDB',
|
|
2565
|
+
orm: 'Prisma / TypeORM / Mongoose',
|
|
2566
|
+
},
|
|
2567
|
+
codingStandards: { language: 'en', namingConvention: 'camelCase', indentation: 'spaces-2', lineLength: 100 },
|
|
2568
|
+
architecture: 'Controller-Service-Repository',
|
|
2569
|
+
featuresDir: 'src/modules',
|
|
2570
|
+
sharedUIDir: 'src/common',
|
|
2571
|
+
servicesDir: 'src/services',
|
|
2572
|
+
modelsDir: 'src/models',
|
|
2573
|
+
},
|
|
2329
2574
|
};
|
|
2330
2575
|
|
|
2331
2576
|
// Fallback: generic mobile-firebase
|
|
@@ -2394,6 +2639,10 @@ function buildProjectIdentity(projectName, projectType, cwd, date) {
|
|
|
2394
2639
|
"pixel-mcp": {
|
|
2395
2640
|
enabled: false
|
|
2396
2641
|
}
|
|
2642
|
+
},
|
|
2643
|
+
build: {
|
|
2644
|
+
enabled: false,
|
|
2645
|
+
command: getDefaultBuildCommand(projectType)
|
|
2397
2646
|
}
|
|
2398
2647
|
},
|
|
2399
2648
|
modelPolicy: {
|
|
@@ -2637,6 +2886,10 @@ async function cmdInit(forceFlag = false) {
|
|
|
2637
2886
|
"pixel-mcp": {
|
|
2638
2887
|
enabled: false
|
|
2639
2888
|
}
|
|
2889
|
+
},
|
|
2890
|
+
build: {
|
|
2891
|
+
enabled: false,
|
|
2892
|
+
command: getDefaultBuildCommand(projectType)
|
|
2640
2893
|
}
|
|
2641
2894
|
};
|
|
2642
2895
|
fs.writeFileSync(identityPath, JSON.stringify(currentIdentity, null, 2) + '\n');
|
|
@@ -2657,6 +2910,18 @@ async function cmdInit(forceFlag = false) {
|
|
|
2657
2910
|
currentIdentity.automation.mcp = { "pixel-mcp": { enabled: false } };
|
|
2658
2911
|
changed = true;
|
|
2659
2912
|
}
|
|
2913
|
+
if (!currentIdentity.projectType) {
|
|
2914
|
+
currentIdentity.projectType = projectType;
|
|
2915
|
+
changed = true;
|
|
2916
|
+
}
|
|
2917
|
+
if (!currentIdentity.automation.build) {
|
|
2918
|
+
const detectedType = currentIdentity.projectType || projectType || 'mobile-firebase';
|
|
2919
|
+
currentIdentity.automation.build = {
|
|
2920
|
+
enabled: false,
|
|
2921
|
+
command: getDefaultBuildCommand(detectedType)
|
|
2922
|
+
};
|
|
2923
|
+
changed = true;
|
|
2924
|
+
}
|
|
2660
2925
|
if (!currentIdentity.modelPolicy) {
|
|
2661
2926
|
currentIdentity.modelPolicy = {
|
|
2662
2927
|
mode: "auto",
|
|
@@ -2841,17 +3106,20 @@ Additional project context can be found in:
|
|
|
2841
3106
|
).trim();
|
|
2842
3107
|
|
|
2843
3108
|
if (hasSource) {
|
|
2844
|
-
|
|
3109
|
+
const usePnpm = fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'));
|
|
3110
|
+
const indexCmd = usePnpm ? 'pnpm dlx gitnexus analyze' : 'npx -y gitnexus analyze';
|
|
3111
|
+
info(`Running index with: ${indexCmd}...`);
|
|
3112
|
+
execSync(indexCmd, {
|
|
2845
3113
|
cwd,
|
|
2846
3114
|
stdio: 'ignore',
|
|
2847
3115
|
});
|
|
2848
3116
|
ok('GitNexus index created (.gitnexus/)');
|
|
2849
3117
|
} else {
|
|
2850
|
-
dim('No source files found — skipping GitNexus index (run later: npx gitnexus analyze)');
|
|
3118
|
+
dim('No source files found — skipping GitNexus index (run later: pnpm dlx gitnexus analyze or npx gitnexus analyze)');
|
|
2851
3119
|
}
|
|
2852
3120
|
} catch (e) {
|
|
2853
3121
|
warn(`GitNexus indexing failed: ${e.message}`);
|
|
2854
|
-
dim('Run manually later: npx gitnexus analyze');
|
|
3122
|
+
dim('Run manually later: pnpm dlx gitnexus analyze or npx gitnexus analyze');
|
|
2855
3123
|
}
|
|
2856
3124
|
|
|
2857
3125
|
// ── 6. Summary ─────────────────────────────────────────────────────────────
|
|
@@ -2866,9 +3134,10 @@ Additional project context can be found in:
|
|
|
2866
3134
|
dim(`GitNexus: code intelligence index`);
|
|
2867
3135
|
log('');
|
|
2868
3136
|
log(`${C.cyan}👉 Open ${workspaceName} in VS Code to get started.${C.reset}`);
|
|
3137
|
+
log(`${C.cyan}👉 Run '/init' in AI chat to activate Smart Ecosystem Setup (SAEE) & recommendations.${C.reset}`);
|
|
2869
3138
|
log(`${C.cyan}👉 Run '/codebase-sync' in AI chat to keep CODEBASE.md updated.${C.reset}`);
|
|
2870
3139
|
log(`${C.cyan}👉 Run 'symphony task list' to manage tasks.${C.reset}`);
|
|
2871
|
-
log(`${C.cyan}👉 Run 'npx gitnexus analyze' after major changes to refresh index.${C.reset}`);
|
|
3140
|
+
log(`${C.cyan}👉 Run 'pnpm dlx gitnexus analyze' (or 'npx gitnexus analyze') after major changes to refresh index.${C.reset}`);
|
|
2872
3141
|
log('');
|
|
2873
3142
|
|
|
2874
3143
|
// ── 7. Open Documentation ───────────────────────────────────────────────────
|
|
@@ -3520,41 +3789,90 @@ function cmdTrello(args) {
|
|
|
3520
3789
|
}
|
|
3521
3790
|
}
|
|
3522
3791
|
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
const
|
|
3792
|
+
/**
|
|
3793
|
+
* Helper to check if semantic version `latest` is newer than `current`.
|
|
3794
|
+
*/
|
|
3795
|
+
function isNewerVersion(latest, current) {
|
|
3796
|
+
if (!latest || !current) return false;
|
|
3797
|
+
const clean = v => v.replace(/^v/, '');
|
|
3798
|
+
const lClean = clean(latest);
|
|
3799
|
+
const cClean = clean(current);
|
|
3800
|
+
if (lClean === cClean) return false;
|
|
3801
|
+
|
|
3802
|
+
const parse = v => {
|
|
3803
|
+
const parts = v.split('-');
|
|
3804
|
+
const numbers = parts[0].split('.').map(Number);
|
|
3805
|
+
const prerelease = parts[1] ? parts[1].split('.') : [];
|
|
3806
|
+
return { numbers, prerelease };
|
|
3807
|
+
};
|
|
3529
3808
|
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3809
|
+
const l = parse(lClean);
|
|
3810
|
+
const c = parse(cClean);
|
|
3811
|
+
|
|
3812
|
+
// Compare main version numbers
|
|
3813
|
+
for (let i = 0; i < 3; i++) {
|
|
3814
|
+
const ln = l.numbers[i] || 0;
|
|
3815
|
+
const cn = c.numbers[i] || 0;
|
|
3816
|
+
if (ln > cn) return true;
|
|
3817
|
+
if (ln < cn) return false;
|
|
3818
|
+
}
|
|
3819
|
+
|
|
3820
|
+
const lIsPrerelease = l.prerelease.length > 0;
|
|
3821
|
+
const cIsPrerelease = c.prerelease.length > 0;
|
|
3822
|
+
|
|
3823
|
+
if (lIsPrerelease && !cIsPrerelease) return false;
|
|
3824
|
+
if (!lIsPrerelease && cIsPrerelease) return true;
|
|
3825
|
+
|
|
3826
|
+
const maxLength = Math.max(l.prerelease.length, c.prerelease.length);
|
|
3827
|
+
for (let i = 0; i < maxLength; i++) {
|
|
3828
|
+
const lp = l.prerelease[i];
|
|
3829
|
+
const cp = c.prerelease[i];
|
|
3830
|
+
if (lp === undefined) return false;
|
|
3831
|
+
if (cp === undefined) return true;
|
|
3832
|
+
const lpNum = parseInt(lp, 10);
|
|
3833
|
+
const cpNum = parseInt(cp, 10);
|
|
3834
|
+
const lpIsNum = !isNaN(lpNum);
|
|
3835
|
+
const cpIsNum = !isNaN(cpNum);
|
|
3836
|
+
if (lpIsNum && cpIsNum) {
|
|
3837
|
+
if (lpNum > cpNum) return true;
|
|
3838
|
+
if (lpNum < cpNum) return false;
|
|
3839
|
+
} else if (lpIsNum) {
|
|
3840
|
+
return false;
|
|
3841
|
+
} else if (cpIsNum) {
|
|
3842
|
+
return true;
|
|
3843
|
+
} else {
|
|
3844
|
+
if (lp > cp) return true;
|
|
3845
|
+
if (lp < cp) return false;
|
|
3846
|
+
}
|
|
3537
3847
|
}
|
|
3848
|
+
return false;
|
|
3849
|
+
}
|
|
3538
3850
|
|
|
3539
|
-
|
|
3540
|
-
try { fs.writeFileSync(checkFile, now.toString()); } catch (_) { }
|
|
3851
|
+
// ─── Auto-Update Checker ──────────────────────────────────────────────────────
|
|
3541
3852
|
|
|
3542
|
-
|
|
3853
|
+
async function checkAutoUpdate() {
|
|
3543
3854
|
try {
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
// Simple string comparison for versions like "1.0.0" (Assumes SemVer)
|
|
3548
|
-
if (npmVersion && npmVersion !== AWK_VERSION) {
|
|
3855
|
+
const updates = await depManager.checkUpdates(AWK_VERSION);
|
|
3856
|
+
if (updates.latestAwkit && isNewerVersion(updates.latestAwkit, AWK_VERSION)) {
|
|
3549
3857
|
log('');
|
|
3550
|
-
log(`${C.yellow}${C.bold}🌟 [Thông báo] Có phiên bản mới cho AWKit! (v${
|
|
3858
|
+
log(`${C.yellow}${C.bold}🌟 [Thông báo] Có phiên bản mới cho AWKit! (v${updates.latestAwkit})${C.reset}`);
|
|
3551
3859
|
log(`${C.gray} Phiên bản hiện tại: v${AWK_VERSION}${C.reset}`);
|
|
3552
3860
|
log(`${C.gray} Chạy lệnh sau để nâng cấp:${C.reset}`);
|
|
3553
3861
|
log(`${C.cyan} npm i -g @leejungkiin/awkit && awkit install${C.reset}`);
|
|
3554
3862
|
log('');
|
|
3555
3863
|
}
|
|
3864
|
+
|
|
3865
|
+
const currentRtk = depManager.getRtkVersion();
|
|
3866
|
+
if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
|
|
3867
|
+
log('');
|
|
3868
|
+
log(`${C.yellow}${C.bold}🌟 [Thông báo] Có phiên bản mới cho RTK! (v${updates.latestRtk})${C.reset}`);
|
|
3869
|
+
log(`${C.gray} Phiên bản hiện tại: v${currentRtk}${C.reset}`);
|
|
3870
|
+
log(`${C.gray} Chạy lệnh sau để nâng cấp:${C.reset}`);
|
|
3871
|
+
log(`${C.cyan} awkit rtk setup${C.reset}`);
|
|
3872
|
+
log('');
|
|
3873
|
+
}
|
|
3556
3874
|
} catch (_) {
|
|
3557
|
-
// Fail silently
|
|
3875
|
+
// Fail silently in auto check
|
|
3558
3876
|
}
|
|
3559
3877
|
}
|
|
3560
3878
|
|
|
@@ -3585,7 +3903,7 @@ function cmdGitnexus(args) {
|
|
|
3585
3903
|
const registry = readGitnexusRegistry();
|
|
3586
3904
|
if (registry.length === 0) {
|
|
3587
3905
|
info('No GitNexus indexed repositories found.');
|
|
3588
|
-
dim('Run `npx gitnexus analyze` in a project to index it.');
|
|
3906
|
+
dim('Run `pnpm dlx gitnexus analyze` or `npx gitnexus analyze` in a project to index it.');
|
|
3589
3907
|
return;
|
|
3590
3908
|
}
|
|
3591
3909
|
|
|
@@ -3618,7 +3936,7 @@ function cmdGitnexus(args) {
|
|
|
3618
3936
|
|
|
3619
3937
|
if (!match) {
|
|
3620
3938
|
warn('Current directory is not indexed by GitNexus.');
|
|
3621
|
-
dim('Run `npx gitnexus analyze` to index this project.');
|
|
3939
|
+
dim('Run `pnpm dlx gitnexus analyze` or `npx gitnexus analyze` to index this project.');
|
|
3622
3940
|
return;
|
|
3623
3941
|
}
|
|
3624
3942
|
|
|
@@ -3644,7 +3962,7 @@ function cmdGitnexus(args) {
|
|
|
3644
3962
|
if (stale) {
|
|
3645
3963
|
log('');
|
|
3646
3964
|
warn(`Index is ${ageDays} days old. Consider refreshing:`);
|
|
3647
|
-
dim(' npx gitnexus analyze');
|
|
3965
|
+
dim(' pnpm dlx gitnexus analyze (or npx gitnexus analyze)');
|
|
3648
3966
|
}
|
|
3649
3967
|
|
|
3650
3968
|
// Show projectId from .project-identity if available
|
|
@@ -3868,43 +4186,77 @@ async function cmdRtkSetup() {
|
|
|
3868
4186
|
log(`${C.cyan}${C.bold}║ ⚙️ RTK Auto-Setup & Configuration ║${C.reset}`);
|
|
3869
4187
|
log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
|
|
3870
4188
|
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
execSync('which cargo', { stdio: 'ignore' });
|
|
3874
|
-
ok('Cargo is installed.');
|
|
3875
|
-
} catch (_) {
|
|
3876
|
-
err('Cargo/Rust not found. Please install Rust (https://rustup.rs/) and retry.');
|
|
3877
|
-
return;
|
|
3878
|
-
}
|
|
3879
|
-
|
|
3880
|
-
log(`\nInstalling RTK (Rust Token Killer) via Cargo...`);
|
|
3881
|
-
try {
|
|
3882
|
-
execSync('cargo install --git https://github.com/rtk-ai/rtk', { stdio: 'inherit' });
|
|
3883
|
-
ok('RTK successfully installed/updated via Cargo.');
|
|
3884
|
-
} catch (e) {
|
|
3885
|
-
err(`Failed to install RTK: ${e.message}`);
|
|
3886
|
-
return;
|
|
3887
|
-
}
|
|
4189
|
+
const installed = depManager.installRtk();
|
|
4190
|
+
if (!installed) return;
|
|
3888
4191
|
|
|
3889
4192
|
const zshrcPath = path.join(HOME, '.zshrc');
|
|
3890
4193
|
log(`\nConfiguring Shell Aliases in ~/.zshrc...`);
|
|
3891
4194
|
if (fs.existsSync(zshrcPath)) {
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
alias
|
|
3897
|
-
alias
|
|
3898
|
-
alias
|
|
3899
|
-
alias
|
|
4195
|
+
let zshrc = fs.readFileSync(zshrcPath, 'utf8');
|
|
4196
|
+
|
|
4197
|
+
// Clean up old aliases to avoid collision
|
|
4198
|
+
const oldAliases = [
|
|
4199
|
+
'alias git="rtk git"',
|
|
4200
|
+
'alias npm="rtk npm"',
|
|
4201
|
+
'alias pnpm="rtk pnpm"',
|
|
4202
|
+
'alias yarn="rtk yarn"',
|
|
4203
|
+
'alias cargo="rtk cargo"'
|
|
4204
|
+
];
|
|
4205
|
+
for (const oldAlias of oldAliases) {
|
|
4206
|
+
if (zshrc.includes(oldAlias)) {
|
|
4207
|
+
zshrc = zshrc.replace(new RegExp(`\\n?${oldAlias}\\n?`, 'g'), '\n');
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
|
|
4211
|
+
const functionBlock = `
|
|
4212
|
+
# RTK Integration for AI Agents (AWKit)
|
|
4213
|
+
unalias npm pnpm yarn cargo git 2>/dev/null
|
|
4214
|
+
npm() {
|
|
4215
|
+
if [[ "$1" == "login" || "$1" == "adduser" || "$1" == "publish" ]]; then
|
|
4216
|
+
command npm "$@"
|
|
4217
|
+
else
|
|
4218
|
+
rtk npm "$@"
|
|
4219
|
+
fi
|
|
4220
|
+
}
|
|
4221
|
+
pnpm() {
|
|
4222
|
+
if [[ "$1" == "login" || "$1" == "publish" ]]; then
|
|
4223
|
+
command pnpm "$@"
|
|
4224
|
+
else
|
|
4225
|
+
rtk pnpm "$@"
|
|
4226
|
+
fi
|
|
4227
|
+
}
|
|
4228
|
+
yarn() {
|
|
4229
|
+
if [[ "$1" == "login" || "$1" == "publish" ]]; then
|
|
4230
|
+
command yarn "$@"
|
|
4231
|
+
else
|
|
4232
|
+
rtk yarn "$@"
|
|
4233
|
+
fi
|
|
4234
|
+
}
|
|
4235
|
+
cargo() {
|
|
4236
|
+
if [[ "$1" == "login" || "$1" == "publish" ]]; then
|
|
4237
|
+
command cargo "$@"
|
|
4238
|
+
else
|
|
4239
|
+
rtk cargo "$@"
|
|
4240
|
+
fi
|
|
4241
|
+
}
|
|
4242
|
+
git() {
|
|
4243
|
+
if [[ "$1" == "rebase" ]]; then
|
|
4244
|
+
command git "$@"
|
|
4245
|
+
else
|
|
4246
|
+
rtk git "$@"
|
|
4247
|
+
fi
|
|
4248
|
+
}
|
|
3900
4249
|
`;
|
|
3901
|
-
if
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
ok('Shell aliases successfully added to ~/.zshrc.');
|
|
3906
|
-
log(`\n${C.cyan}Please reload your shell (source ~/.zshrc) to apply shifts.${C.reset}`);
|
|
4250
|
+
// Clean up old RTK integration block if exists to allow updating
|
|
4251
|
+
if (zshrc.includes('# RTK Integration for AI Agents (AWKit)')) {
|
|
4252
|
+
const startIdx = zshrc.indexOf('# RTK Integration for AI Agents (AWKit)');
|
|
4253
|
+
zshrc = zshrc.substring(0, startIdx);
|
|
3907
4254
|
}
|
|
4255
|
+
|
|
4256
|
+
zshrc += functionBlock;
|
|
4257
|
+
fs.writeFileSync(zshrcPath, zshrc, 'utf8');
|
|
4258
|
+
ok('Shell wrappers successfully added/updated in ~/.zshrc.');
|
|
4259
|
+
log(`\n${C.cyan}Please reload your shell (source ~/.zshrc) to apply shifts.${C.reset}`);
|
|
3908
4260
|
} else {
|
|
3909
4261
|
warn('~/.zshrc not found. Skipping alias setup.');
|
|
3910
4262
|
}
|
|
@@ -3920,6 +4272,130 @@ async function cmdRtk(args) {
|
|
|
3920
4272
|
}
|
|
3921
4273
|
}
|
|
3922
4274
|
|
|
4275
|
+
// ─── Project Identity CLI View ───────────────────────────────────────────────
|
|
4276
|
+
|
|
4277
|
+
function cmdIdentity(args = []) {
|
|
4278
|
+
const cwd = process.cwd();
|
|
4279
|
+
const identityPath = path.join(cwd, '.project-identity');
|
|
4280
|
+
|
|
4281
|
+
if (!fs.existsSync(identityPath)) {
|
|
4282
|
+
err('No .project-identity found in the current directory.');
|
|
4283
|
+
log(` Run ${C.cyan}awkit init${C.reset} to create one for this project.`);
|
|
4284
|
+
return;
|
|
4285
|
+
}
|
|
4286
|
+
|
|
4287
|
+
try {
|
|
4288
|
+
const raw = fs.readFileSync(identityPath, 'utf8');
|
|
4289
|
+
const identity = JSON.parse(raw);
|
|
4290
|
+
|
|
4291
|
+
// Handle specific field querying
|
|
4292
|
+
if (args.length > 0) {
|
|
4293
|
+
const query = args[0];
|
|
4294
|
+
|
|
4295
|
+
if (query === '--keys') {
|
|
4296
|
+
console.log(Object.keys(identity).join('\n'));
|
|
4297
|
+
return;
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4300
|
+
if (query === '--json') {
|
|
4301
|
+
console.log(JSON.stringify(identity, null, 2));
|
|
4302
|
+
return;
|
|
4303
|
+
}
|
|
4304
|
+
|
|
4305
|
+
// Helper to get nested value by dot notation (e.g., automation.build.enabled)
|
|
4306
|
+
const getNested = (obj, path) => {
|
|
4307
|
+
return path.split('.').reduce((acc, part) => acc && acc[part], obj);
|
|
4308
|
+
};
|
|
4309
|
+
|
|
4310
|
+
const val = getNested(identity, query);
|
|
4311
|
+
if (val !== undefined) {
|
|
4312
|
+
if (typeof val === 'object') {
|
|
4313
|
+
console.log(JSON.stringify(val));
|
|
4314
|
+
} else {
|
|
4315
|
+
console.log(val);
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
return; // Exit silently if undefined, ideal for bash scripts
|
|
4319
|
+
}
|
|
4320
|
+
|
|
4321
|
+
const border = `${C.cyan}${C.bold}╔═══════════════════════════════════════════════════════╗${C.reset}`;
|
|
4322
|
+
const bottom = `${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`;
|
|
4323
|
+
const line = `${C.gray}${'─'.repeat(56)}${C.reset}`;
|
|
4324
|
+
|
|
4325
|
+
log('');
|
|
4326
|
+
log(border);
|
|
4327
|
+
log(`${C.cyan}${C.bold}║ 🆔 PROJECT IDENTITY: ${C.green}${C.bold}${String(identity.projectName || 'Unnamed Project').padEnd(30)}${C.cyan}${C.bold} ║${C.reset}`);
|
|
4328
|
+
log(bottom);
|
|
4329
|
+
log('');
|
|
4330
|
+
|
|
4331
|
+
// Basic Info
|
|
4332
|
+
log(`${C.bold}ℹ️ Basic Information${C.reset}`);
|
|
4333
|
+
log(line);
|
|
4334
|
+
log(` ${C.bold}Project Stage:${C.reset} ${identity.projectStage || 'development'}`);
|
|
4335
|
+
log(` ${C.bold}Project Type:${C.reset} ${identity.projectType ? C.green + identity.projectType + C.reset : C.yellow + 'Not configured' + C.reset}`);
|
|
4336
|
+
log(` ${C.bold}Primary Lang:${C.reset} ${identity.primaryLanguage || 'en'}`);
|
|
4337
|
+
if (identity.techStack) {
|
|
4338
|
+
const rt = Array.isArray(identity.techStack.runtime) ? identity.techStack.runtime.join(', ') : 'N/A';
|
|
4339
|
+
const lang = Array.isArray(identity.techStack.languages) ? identity.techStack.languages.join(', ') : 'N/A';
|
|
4340
|
+
log(` ${C.bold}Runtime/Lang:${C.reset} ${rt} / ${lang}`);
|
|
4341
|
+
}
|
|
4342
|
+
log('');
|
|
4343
|
+
|
|
4344
|
+
// Build Configuration
|
|
4345
|
+
log(`${C.bold}🛠️ Build & Run Control${C.reset}`);
|
|
4346
|
+
log(line);
|
|
4347
|
+
if (identity.automation && identity.automation.build) {
|
|
4348
|
+
const b = identity.automation.build;
|
|
4349
|
+
const statusStr = b.enabled ? `${C.green}Enabled (Safe Auto-Run via awkit build)${C.reset}` : `${C.yellow}Disabled / Manual Only${C.reset}`;
|
|
4350
|
+
log(` ${C.bold}Build Control:${C.reset} ${statusStr}`);
|
|
4351
|
+
log(` ${C.bold}Build Command:${C.reset} ${C.cyan}${b.command || 'N/A'}${C.reset}`);
|
|
4352
|
+
} else {
|
|
4353
|
+
log(` ${C.bold}Build Control:${C.reset} ${C.yellow}Not Configured (Manual Mode)${C.reset}`);
|
|
4354
|
+
}
|
|
4355
|
+
log('');
|
|
4356
|
+
|
|
4357
|
+
// Automation Gates
|
|
4358
|
+
log(`${C.bold}🔒 Automation & Sync Gates${C.reset}`);
|
|
4359
|
+
log(line);
|
|
4360
|
+
if (identity.automation) {
|
|
4361
|
+
const git = identity.automation.git || {};
|
|
4362
|
+
log(` ${C.bold}Git AutoCommit:${C.reset} ${git.autoCommit ? C.green + 'true' : C.red + 'false'}${C.reset}`);
|
|
4363
|
+
log(` ${C.bold}Git AutoPush:${C.reset} ${git.autoPush ? C.green + 'true' : C.red + 'false'}${C.reset}`);
|
|
4364
|
+
|
|
4365
|
+
const trello = identity.automation.trello || {};
|
|
4366
|
+
const syncStr = trello.enabled
|
|
4367
|
+
? `${C.green}Enabled${C.reset} (AutoSync: ${trello.autoSync ? C.green + 'true' : C.red + 'false'}${C.reset})`
|
|
4368
|
+
: `${C.red}Disabled${C.reset}`;
|
|
4369
|
+
log(` ${C.bold}Trello Sync:${C.reset} ${syncStr}`);
|
|
4370
|
+
if (identity.trello) {
|
|
4371
|
+
log(` ${C.bold}Trello Board:${C.reset} ${identity.trello.board || 'N/A'}`);
|
|
4372
|
+
log(` ${C.bold}Trello Card:${C.reset} ${identity.trello.card || 'N/A'}`);
|
|
4373
|
+
}
|
|
4374
|
+
|
|
4375
|
+
const tg = identity.automation.telegram || {};
|
|
4376
|
+
const tgStr = tg.enabled ? `${C.green}Enabled${C.reset}` : `${C.red}Disabled${C.reset}`;
|
|
4377
|
+
log(` ${C.bold}Telegram Alerts:${C.reset} ${tgStr}`);
|
|
4378
|
+
if (tg.triggers) {
|
|
4379
|
+
const trigs = Object.keys(tg.triggers).filter(k => tg.triggers[k]).join(', ');
|
|
4380
|
+
log(` ${C.bold}Alert Triggers:${C.reset} ${C.gray}${trigs || 'None'}${C.reset}`);
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
log('');
|
|
4384
|
+
|
|
4385
|
+
// Caveman Mode
|
|
4386
|
+
if (identity.communication && identity.communication.cavemanMode) {
|
|
4387
|
+
const cm = identity.communication.cavemanMode;
|
|
4388
|
+
log(`${C.bold}💬 Communication Mode${C.reset}`);
|
|
4389
|
+
log(line);
|
|
4390
|
+
log(` ${C.bold}Caveman Mode:${C.reset} ${cm.enabled ? C.green + 'Enabled (' + cm.level + ')' : C.red + 'Disabled'}${C.reset}`);
|
|
4391
|
+
log('');
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
} catch (e) {
|
|
4395
|
+
err(`Failed to parse .project-identity: ${e.message}`);
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
|
|
3923
4399
|
// ─── Native HTTP Server ───────────────────────────────────────────────────────
|
|
3924
4400
|
|
|
3925
4401
|
function cmdServe(args) {
|
|
@@ -4014,13 +4490,14 @@ function cmdServe(args) {
|
|
|
4014
4490
|
|
|
4015
4491
|
// ─── Main ────────────────────────────────────────────────────────────────────
|
|
4016
4492
|
|
|
4017
|
-
// Check for updates (max once per day) before continuing
|
|
4018
|
-
checkAutoUpdate();
|
|
4019
|
-
|
|
4020
4493
|
const [, , command, ...args] = process.argv;
|
|
4021
4494
|
|
|
4022
4495
|
(async () => {
|
|
4496
|
+
await checkAutoUpdate();
|
|
4023
4497
|
switch (command) {
|
|
4498
|
+
case 'build':
|
|
4499
|
+
cmdBuild();
|
|
4500
|
+
break;
|
|
4024
4501
|
case 'init':
|
|
4025
4502
|
await cmdInit(args.includes('--force'));
|
|
4026
4503
|
break;
|
|
@@ -4043,7 +4520,13 @@ const [, , command, ...args] = process.argv;
|
|
|
4043
4520
|
cmdHarvest(args.includes('--dry-run'));
|
|
4044
4521
|
break;
|
|
4045
4522
|
case 'doctor':
|
|
4046
|
-
cmdDoctor();
|
|
4523
|
+
await cmdDoctor();
|
|
4524
|
+
break;
|
|
4525
|
+
case 'storage':
|
|
4526
|
+
cmdStorage(args);
|
|
4527
|
+
break;
|
|
4528
|
+
case 'pipeline':
|
|
4529
|
+
cmdPipeline(args);
|
|
4047
4530
|
break;
|
|
4048
4531
|
case 'browser':
|
|
4049
4532
|
cmdBrowser(args);
|
|
@@ -4094,6 +4577,10 @@ const [, , command, ...args] = process.argv;
|
|
|
4094
4577
|
case 'rtk':
|
|
4095
4578
|
await cmdRtk(args);
|
|
4096
4579
|
break;
|
|
4580
|
+
case 'i18n':
|
|
4581
|
+
await cmdI18n(args);
|
|
4582
|
+
break;
|
|
4583
|
+
|
|
4097
4584
|
case 'gitnexus':
|
|
4098
4585
|
case 'gn':
|
|
4099
4586
|
cmdGitnexus(args);
|
|
@@ -4116,6 +4603,11 @@ const [, , command, ...args] = process.argv;
|
|
|
4116
4603
|
case 'restart':
|
|
4117
4604
|
await cmdRestart();
|
|
4118
4605
|
break;
|
|
4606
|
+
case 'identity':
|
|
4607
|
+
case 'config':
|
|
4608
|
+
case 'project':
|
|
4609
|
+
cmdIdentity(args);
|
|
4610
|
+
break;
|
|
4119
4611
|
case 'help':
|
|
4120
4612
|
case '--help':
|
|
4121
4613
|
case '-h':
|