@leejungkiin/awkit 1.5.1 → 1.5.3
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 +152 -139
- package/package.json +1 -1
- package/skill-packs/ads-management/pack.json +8 -0
- package/skill-packs/mobile-android/pack.json +2 -6
- package/skill-packs/neural-memory/pack.json +2 -2
- package/skill-packs/reverse-engineering/pack.json +9 -0
- package/workflows/mobile/reverse-android-build.md +0 -222
- package/workflows/mobile/reverse-android-design.md +0 -139
- package/workflows/mobile/reverse-android-discover.md +0 -150
- package/workflows/mobile/reverse-android.md +0 -143
- package/workflows/mobile/reverse-ios-build.md +0 -240
- package/workflows/mobile/reverse-ios-design.md +0 -112
- package/workflows/mobile/reverse-ios-discover.md +0 -120
- package/workflows/mobile/reverse-ios.md +0 -152
- /package/{skills → skill-packs/ads-management/skills}/admob-roas/SKILL.md +0 -0
- /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-analyst.md +0 -0
- /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-audit.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-creative.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-full-optimization.md +0 -0
- /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-optimize.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-plan.md +0 -0
- /package/{workflows/ads → skill-packs/ads-management/workflows}/ads-targeting.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/ads-management/workflows}/ads-user-analysis.md +0 -0
- /package/{workflows/ads → skill-packs/ads-management/workflows}/adsExpert.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/SKILL.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/api-extraction-patterns.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/call-flow-analysis.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/fernflower-usage.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/jadx-usage.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/references/setup-guide.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/check-deps.sh +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/decompile.sh +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/find-api-calls.sh +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/android-re-analyzer/scripts/install-dep.sh +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/SKILL.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/getting-started/tech-stack.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/pipeline/data-ui-parity.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/library-patterns.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-0-discovery.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-1-architecture.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-2-blueprint-ui.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-2-blueprint.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-3-build.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/phase-3-logic-build.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/smali-reading-guide.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/app-map.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/architecture.md +0 -0
- /package/{skills → skill-packs/reverse-engineering/skills}/smali-to-kotlin/templates/blueprint.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-build.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-design.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-discover.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android-scan.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-android.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-build.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-design.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-discover.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios-scan.md +0 -0
- /package/{workflows/_uncategorized → skill-packs/reverse-engineering/workflows}/reverse-ios.md +0 -0
- /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-config.md +0 -0
- /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-flow.md +0 -0
- /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-interstitial.md +0 -0
- /package/{workflows/ads → skill-packs/reverse-engineering/workflows}/smali-ads-native.md +0 -0
package/bin/awk.js
CHANGED
|
@@ -522,7 +522,7 @@ function cmdInstall(args = []) {
|
|
|
522
522
|
} else if (args.length > 0 && !args[0].startsWith('-') && args[0] !== 'all' && args[0] !== '--update') {
|
|
523
523
|
legacyArg = args[0];
|
|
524
524
|
}
|
|
525
|
-
|
|
525
|
+
|
|
526
526
|
if (legacyArg && PLATFORMS[legacyArg] && !selectedPlatforms.includes(legacyArg)) {
|
|
527
527
|
selectedPlatforms.push(legacyArg);
|
|
528
528
|
}
|
|
@@ -543,7 +543,7 @@ function cmdInstall(args = []) {
|
|
|
543
543
|
log(` 5. All of the above`);
|
|
544
544
|
log(`${C.gray}Press Enter to install only the active platform: ${PLATFORMS[defaultPlatform].name}.${C.reset}`);
|
|
545
545
|
const choice = promptChoice('Choice', defaultChoice).trim().toLowerCase();
|
|
546
|
-
|
|
546
|
+
|
|
547
547
|
if (choice === '5' || choice === 'all') {
|
|
548
548
|
selectedPlatforms = Object.keys(PLATFORMS);
|
|
549
549
|
} else {
|
|
@@ -587,73 +587,73 @@ function cmdInstall(args = []) {
|
|
|
587
587
|
checkSymphony({ silent: platform !== selectedPlatforms[0] });
|
|
588
588
|
|
|
589
589
|
// 1. Ensure target dirs exist
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
ok('Directories ready');
|
|
599
|
-
|
|
600
|
-
// 2. Sync rules (platform-specific)
|
|
601
|
-
if (platform === 'antigravity') {
|
|
602
|
-
info('Syncing GEMINI.md...');
|
|
603
|
-
syncGeminiMd();
|
|
604
|
-
} else if (platform === 'cline') {
|
|
605
|
-
info('Generating Cline global rules...');
|
|
606
|
-
generateClineRules(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
|
|
607
|
-
} else if (platform === 'codex') {
|
|
608
|
-
info('Generating Codex AGENTS.md...');
|
|
609
|
-
generateCodexAgentsMd(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
|
|
610
|
-
} else if (platform === 'claude') {
|
|
611
|
-
info('Generating Claude Code CLAUDE.md...');
|
|
612
|
-
const claudeTemplateSrc = path.join(AWK_ROOT, 'core', 'CLAUDE.md');
|
|
613
|
-
const claudeRulesDest = path.join(target, plat.rulesFile);
|
|
614
|
-
generateClaudeRules(claudeTemplateSrc, claudeRulesDest);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
// 3. Backup and install workflows
|
|
618
|
-
if (plat.dirs.workflows) {
|
|
619
|
-
info('Installing workflows...');
|
|
620
|
-
const wfSrc = path.join(AWK_ROOT, 'workflows');
|
|
621
|
-
const wfDest = path.join(target, plat.dirs.workflows);
|
|
622
|
-
|
|
623
|
-
// Backup existing workflows
|
|
624
|
-
if (fs.existsSync(wfDest)) {
|
|
625
|
-
const backupDir = getPlatformBackupRoot(platform);
|
|
626
|
-
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
|
|
627
|
-
|
|
628
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
629
|
-
const zipFile = path.join(backupDir, `workflows_${timestamp}.bak.zip`);
|
|
630
|
-
try {
|
|
631
|
-
execSync(`zip -r "${zipFile}" .`, { cwd: wfDest, stdio: 'ignore' });
|
|
632
|
-
dim(`Backup: ${zipFile}`);
|
|
633
|
-
} catch (e) {
|
|
634
|
-
warn(`Failed to create backup: ${e.message}`);
|
|
590
|
+
info('Creating directories...');
|
|
591
|
+
const dirKeys = Object.values(plat.dirs);
|
|
592
|
+
for (const dir of dirKeys) {
|
|
593
|
+
const fullPath = path.join(target, dir);
|
|
594
|
+
if (!fs.existsSync(fullPath)) {
|
|
595
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
635
596
|
}
|
|
636
597
|
}
|
|
598
|
+
ok('Directories ready');
|
|
599
|
+
|
|
600
|
+
// 2. Sync rules (platform-specific)
|
|
601
|
+
if (platform === 'antigravity') {
|
|
602
|
+
info('Syncing GEMINI.md...');
|
|
603
|
+
syncGeminiMd();
|
|
604
|
+
} else if (platform === 'cline') {
|
|
605
|
+
info('Generating Cline global rules...');
|
|
606
|
+
generateClineRules(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
|
|
607
|
+
} else if (platform === 'codex') {
|
|
608
|
+
info('Generating Codex AGENTS.md...');
|
|
609
|
+
generateCodexAgentsMd(path.join(AWK_ROOT, 'core', 'GEMINI.md'), plat.rulesFile);
|
|
610
|
+
} else if (platform === 'claude') {
|
|
611
|
+
info('Generating Claude Code CLAUDE.md...');
|
|
612
|
+
const claudeTemplateSrc = path.join(AWK_ROOT, 'core', 'CLAUDE.md');
|
|
613
|
+
const claudeRulesDest = path.join(target, plat.rulesFile);
|
|
614
|
+
generateClaudeRules(claudeTemplateSrc, claudeRulesDest);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// 3. Backup and install workflows
|
|
618
|
+
if (plat.dirs.workflows) {
|
|
619
|
+
info('Installing workflows...');
|
|
620
|
+
const wfSrc = path.join(AWK_ROOT, 'workflows');
|
|
621
|
+
const wfDest = path.join(target, plat.dirs.workflows);
|
|
622
|
+
|
|
623
|
+
// Backup existing workflows
|
|
624
|
+
if (fs.existsSync(wfDest)) {
|
|
625
|
+
const backupDir = getPlatformBackupRoot(platform);
|
|
626
|
+
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
|
|
627
|
+
|
|
628
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
629
|
+
const zipFile = path.join(backupDir, `workflows_${timestamp}.bak.zip`);
|
|
630
|
+
try {
|
|
631
|
+
execSync(`zip -r "${zipFile}" .`, { cwd: wfDest, stdio: 'ignore' });
|
|
632
|
+
dim(`Backup: ${zipFile}`);
|
|
633
|
+
} catch (e) {
|
|
634
|
+
warn(`Failed to create backup: ${e.message}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
637
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
638
|
+
if (platform === 'cline') {
|
|
639
|
+
generateClineWorkflows(wfSrc, wfDest);
|
|
640
|
+
} else if (platform !== 'codex') {
|
|
641
|
+
const wfCount = flattenWorkflows(wfSrc, wfDest);
|
|
642
|
+
ok(`${wfCount} workflows installed`);
|
|
643
|
+
}
|
|
643
644
|
}
|
|
644
|
-
}
|
|
645
645
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
646
|
+
// 4. Copy AGENTS.md
|
|
647
|
+
if (platform === 'antigravity' && plat.dirs.workflows) {
|
|
648
|
+
const agentsSrc = path.join(AWK_ROOT, 'core', 'AGENTS.md');
|
|
649
|
+
const agentsDest = path.join(target, plat.dirs.workflows, 'AGENTS.md');
|
|
650
|
+
if (fs.existsSync(agentsSrc)) {
|
|
651
|
+
fs.copyFileSync(agentsSrc, agentsDest);
|
|
652
|
+
ok('AGENTS.md installed');
|
|
653
|
+
}
|
|
653
654
|
}
|
|
654
|
-
}
|
|
655
655
|
|
|
656
|
-
|
|
656
|
+
// 5. Copy skills
|
|
657
657
|
if (plat.dirs.skills) {
|
|
658
658
|
info('Installing skills...');
|
|
659
659
|
const skillsSrc = path.join(AWK_ROOT, 'skills');
|
|
@@ -673,36 +673,36 @@ function cmdInstall(args = []) {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
676
|
+
// 6. Copy orchestrator
|
|
677
|
+
if (platform === 'antigravity') {
|
|
678
|
+
const orchSrc = path.join(AWK_ROOT, 'core', 'orchestrator.md');
|
|
679
|
+
const orchDestDir = path.join(target, plat.dirs.skills, 'orchestrator');
|
|
680
|
+
if (!fs.existsSync(orchDestDir)) fs.mkdirSync(orchDestDir, { recursive: true });
|
|
681
|
+
fs.copyFileSync(orchSrc, path.join(orchDestDir, 'SKILL.md'));
|
|
682
|
+
ok('Orchestrator skill installed');
|
|
683
|
+
}
|
|
684
684
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
685
|
+
// 7. Copy schemas (always overwrite)
|
|
686
|
+
if (plat.dirs.schemas) {
|
|
687
|
+
info('Installing schemas...');
|
|
688
|
+
const schemaSrc = path.join(AWK_ROOT, 'schemas');
|
|
689
|
+
const schemaDest = path.join(target, plat.dirs.schemas);
|
|
690
|
+
const schemaCount = copyDirRecursive(schemaSrc, schemaDest);
|
|
691
|
+
ok(`${schemaCount} schemas installed`);
|
|
692
|
+
}
|
|
693
693
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
694
|
+
// 8. Copy templates (don't overwrite existing)
|
|
695
|
+
if (plat.dirs.templates) {
|
|
696
|
+
info('Installing templates...');
|
|
697
|
+
const tmplSrc = path.join(AWK_ROOT, 'templates');
|
|
698
|
+
const tmplDest = path.join(target, plat.dirs.templates);
|
|
699
|
+
const tmplCount = copyDirRecursive(tmplSrc, tmplDest, { overwrite: false });
|
|
700
|
+
ok(`${tmplCount} templates installed`);
|
|
701
|
+
}
|
|
702
702
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
703
|
+
// 9. Save version
|
|
704
|
+
fs.writeFileSync(plat.versionFile, AWK_VERSION);
|
|
705
|
+
ok(`Version ${AWK_VERSION} saved`);
|
|
706
706
|
|
|
707
707
|
// 10. Install default skill packs
|
|
708
708
|
const defaultPacks = installDefaultPacks();
|
|
@@ -732,35 +732,35 @@ function cmdInstall(args = []) {
|
|
|
732
732
|
ok(`Install state saved (${desiredSkills.size} active skills)`);
|
|
733
733
|
|
|
734
734
|
// 11. Summary
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
735
|
+
log('');
|
|
736
|
+
log(`${C.gray}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
|
|
737
|
+
log(`${C.yellow}${C.bold}🎉 AWK v${AWK_VERSION} installed for ${plat.name}!${C.reset}`);
|
|
738
|
+
log('');
|
|
739
|
+
dim(`Platform: ${plat.name}`);
|
|
740
|
+
if (plat.dirs.workflows) dim(`Workflows: ${path.join(target, plat.dirs.workflows)}`);
|
|
741
|
+
if (plat.dirs.skills) dim(`Skills: ${path.join(target, plat.dirs.skills)}`);
|
|
742
|
+
if (plat.dirs.schemas) dim(`Schemas: ${path.join(target, plat.dirs.schemas)}`);
|
|
743
|
+
if (plat.dirs.templates) dim(`Templates: ${path.join(target, plat.dirs.templates)}`);
|
|
744
|
+
if (plat.dirs.agents) dim(`Agents: ${path.join(target, plat.dirs.agents)}`);
|
|
745
745
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
746
|
+
if (plat.rulesFile) {
|
|
747
|
+
dim(`Global Rules: ${plat.rulesFile}`);
|
|
748
|
+
}
|
|
749
|
+
if (activePacks.length > 0) {
|
|
750
|
+
dim(`Packs: ${activePacks.join(', ')}`);
|
|
751
|
+
}
|
|
752
|
+
if (platform === 'antigravity') {
|
|
753
|
+
dim(`Symphony: task tracking ready`);
|
|
754
|
+
}
|
|
755
|
+
log('');
|
|
756
756
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
757
|
+
if (platform === 'antigravity') {
|
|
758
|
+
log(`${C.cyan}👉 Run 'awkit init' in any project to initialize it.${C.reset}`);
|
|
759
|
+
} else if (platform === 'codex') {
|
|
760
|
+
log(`${C.cyan}👉 Type '$skill' in Codex to invoke skills.${C.reset}`);
|
|
761
|
+
}
|
|
762
|
+
log(`${C.cyan}👉 Run 'awkit doctor' to verify installation.${C.reset}`);
|
|
763
|
+
log('');
|
|
764
764
|
} // End of platform loop
|
|
765
765
|
}
|
|
766
766
|
|
|
@@ -987,7 +987,7 @@ function cmdBrowser(args) {
|
|
|
987
987
|
}
|
|
988
988
|
|
|
989
989
|
const recordingsDir = path.join(TARGETS.antigravity, 'browser_recordings');
|
|
990
|
-
|
|
990
|
+
|
|
991
991
|
log('');
|
|
992
992
|
log(`${C.cyan}${C.bold}🧹 AWK Browser Cleanup${C.reset}`);
|
|
993
993
|
log('');
|
|
@@ -1016,7 +1016,7 @@ function cmdBrowser(args) {
|
|
|
1016
1016
|
} else {
|
|
1017
1017
|
log(`Cleaning browser recordings older than ${C.yellow}${keepDays} days${C.reset}...`);
|
|
1018
1018
|
}
|
|
1019
|
-
|
|
1019
|
+
|
|
1020
1020
|
const now = Date.now();
|
|
1021
1021
|
const cutoff = now - (keepDays * 24 * 60 * 60 * 1000);
|
|
1022
1022
|
let deletedCount = 0;
|
|
@@ -1772,7 +1772,7 @@ async function cmdAdmin() {
|
|
|
1772
1772
|
stdio: 'ignore'
|
|
1773
1773
|
});
|
|
1774
1774
|
child.unref();
|
|
1775
|
-
|
|
1775
|
+
|
|
1776
1776
|
info('Vui lòng đợi 3 giây để service khởi động...');
|
|
1777
1777
|
await new Promise(r => setTimeout(r, 3000));
|
|
1778
1778
|
}
|
|
@@ -1805,9 +1805,9 @@ async function cmdRestart() {
|
|
|
1805
1805
|
// Probably no process running on port 3100
|
|
1806
1806
|
dim('Không tìm thấy service đang chạy.');
|
|
1807
1807
|
}
|
|
1808
|
-
|
|
1808
|
+
|
|
1809
1809
|
await new Promise(r => setTimeout(r, 1000));
|
|
1810
|
-
|
|
1810
|
+
|
|
1811
1811
|
// Auto-build production bundle so code changes take effect
|
|
1812
1812
|
const symphonyDir = path.join(AWK_ROOT, '..', 'symphony');
|
|
1813
1813
|
if (fs.existsSync(path.join(symphonyDir, 'package.json'))) {
|
|
@@ -1820,17 +1820,17 @@ async function cmdRestart() {
|
|
|
1820
1820
|
dim(buildErr.message?.slice(0, 200));
|
|
1821
1821
|
}
|
|
1822
1822
|
}
|
|
1823
|
-
|
|
1823
|
+
|
|
1824
1824
|
info('Đang khởi động lại service ngầm...');
|
|
1825
1825
|
const child = spawn('symphony', ['start'], {
|
|
1826
1826
|
detached: true,
|
|
1827
1827
|
stdio: 'ignore'
|
|
1828
1828
|
});
|
|
1829
1829
|
child.unref();
|
|
1830
|
-
|
|
1830
|
+
|
|
1831
1831
|
info('Vui lòng đợi 3 giây để service khởi động...');
|
|
1832
1832
|
await new Promise(r => setTimeout(r, 3000));
|
|
1833
|
-
|
|
1833
|
+
|
|
1834
1834
|
log(`${C.green}✅ Restart thành công!${C.reset}`);
|
|
1835
1835
|
} catch (e) {
|
|
1836
1836
|
err('Lỗi khi restart service: ' + e.message);
|
|
@@ -1958,8 +1958,8 @@ function cmdHelp() {
|
|
|
1958
1958
|
log(` ${C.gray}awkit harvest # Pull live edits → repo${C.reset}`);
|
|
1959
1959
|
log(` ${C.gray}awkit sync # harvest + install in one shot${C.reset}`);
|
|
1960
1960
|
log('');
|
|
1961
|
-
log(` ${C.cyan}# Enable
|
|
1962
|
-
log(` ${C.gray}awkit enable-pack
|
|
1961
|
+
log(` ${C.cyan}# Enable Marketing Skills${C.reset}`);
|
|
1962
|
+
log(` ${C.gray}awkit enable-pack marketing${C.reset}`);
|
|
1963
1963
|
log('');
|
|
1964
1964
|
log(` ${C.cyan}# Repo${C.reset}`);
|
|
1965
1965
|
log(` ${C.gray}https://github.com/babyskill/awk${C.reset}`);
|
|
@@ -2359,7 +2359,7 @@ async function cmdInit(forceFlag = false) {
|
|
|
2359
2359
|
log('');
|
|
2360
2360
|
warn('Trello API Key & Token are not set.');
|
|
2361
2361
|
log(` 👉 To setup Trello integration, please get your credentials at: https://trello.com/app-key`);
|
|
2362
|
-
|
|
2362
|
+
|
|
2363
2363
|
const readline = require('readline');
|
|
2364
2364
|
const rl = readline.createInterface({
|
|
2365
2365
|
input: process.stdin,
|
|
@@ -2388,14 +2388,14 @@ async function cmdInit(forceFlag = false) {
|
|
|
2388
2388
|
if (!fs.existsSync(profilePath) && fs.existsSync(path.join(os.homedir(), '.bashrc'))) {
|
|
2389
2389
|
profilePath = path.join(os.homedir(), '.bashrc');
|
|
2390
2390
|
}
|
|
2391
|
-
|
|
2391
|
+
|
|
2392
2392
|
const exportLines = `\n# Trello API Credentials for AWKit\nexport TRELLO_KEY="${apiKey}"\nexport TRELLO_TOKEN="${apiToken}"\n`;
|
|
2393
2393
|
fs.appendFileSync(profilePath, exportLines);
|
|
2394
|
-
|
|
2394
|
+
|
|
2395
2395
|
// Also inject into current process so immediate awkit trello calls work
|
|
2396
2396
|
process.env.TRELLO_KEY = apiKey;
|
|
2397
2397
|
process.env.TRELLO_TOKEN = apiToken;
|
|
2398
|
-
|
|
2398
|
+
|
|
2399
2399
|
ok(`Credentials saved to ${path.basename(profilePath)} ✅`);
|
|
2400
2400
|
log(` ${C.green}👉 Trello is ready! Credentials are active for this session and all future terminals.${C.reset}`);
|
|
2401
2401
|
} else {
|
|
@@ -2470,7 +2470,7 @@ Additional project context can be found in:
|
|
|
2470
2470
|
// ── 4.5. .gitignore ────────────────────────────────────────────────────────
|
|
2471
2471
|
const gitignorePath = path.join(cwd, '.gitignore');
|
|
2472
2472
|
const ignoreRules = ['log.txt', 'tmp/', '.gitnexus/', 'node_modules/'];
|
|
2473
|
-
|
|
2473
|
+
|
|
2474
2474
|
if (fs.existsSync(gitignorePath)) {
|
|
2475
2475
|
let content = fs.readFileSync(gitignorePath, 'utf8');
|
|
2476
2476
|
let added = 0;
|
|
@@ -2549,6 +2549,19 @@ Additional project context can be found in:
|
|
|
2549
2549
|
log(`${C.cyan}👉 Run 'symphony task list' to manage tasks.${C.reset}`);
|
|
2550
2550
|
log(`${C.cyan}👉 Run 'npx gitnexus analyze' after major changes to refresh index.${C.reset}`);
|
|
2551
2551
|
log('');
|
|
2552
|
+
|
|
2553
|
+
// ── 7. Open Documentation ───────────────────────────────────────────────────
|
|
2554
|
+
try {
|
|
2555
|
+
const platform = process.platform;
|
|
2556
|
+
let openCmd = 'xdg-open';
|
|
2557
|
+
if (platform === 'darwin') openCmd = 'open';
|
|
2558
|
+
else if (platform === 'win32') openCmd = 'start ""';
|
|
2559
|
+
|
|
2560
|
+
execSync(`${openCmd} "help.html"`, { cwd, stdio: 'ignore' });
|
|
2561
|
+
dim('Opened help.html in browser');
|
|
2562
|
+
} catch (e) {
|
|
2563
|
+
// Silently ignore if opening fails
|
|
2564
|
+
}
|
|
2552
2565
|
}
|
|
2553
2566
|
|
|
2554
2567
|
// ─── Telegram Bot API ─────────────────────────────────────────────────────────
|
|
@@ -3087,35 +3100,35 @@ function cmdTrello(args) {
|
|
|
3087
3100
|
err("Credentials or config missing for REST API fallback.");
|
|
3088
3101
|
break;
|
|
3089
3102
|
}
|
|
3090
|
-
|
|
3103
|
+
|
|
3091
3104
|
// 1. Get checklists
|
|
3092
3105
|
const clRes = spawnSync('npx', ['--yes', 'trello-cli', 'card:checklists', '--board', cfgItem.board, '--list', cfgItem.list, '--card', cfgItem.card, '--format', 'json'], { env: { ...process.env, TRELLO_KEY: credItem.api_key, TRELLO_TOKEN: credItem.api_token }, encoding: 'utf-8' });
|
|
3093
|
-
|
|
3106
|
+
|
|
3094
3107
|
if (clRes.status !== 0) {
|
|
3095
3108
|
err(`Failed to get checklists: ${clRes.stderr || clRes.stdout}`);
|
|
3096
3109
|
break;
|
|
3097
3110
|
}
|
|
3098
|
-
|
|
3111
|
+
|
|
3099
3112
|
try {
|
|
3100
3113
|
// Sometime trello-cli outputs to stdout along with some other logs.
|
|
3101
3114
|
// We extract the JSON array part.
|
|
3102
3115
|
const outText = clRes.stdout;
|
|
3103
3116
|
const jsonStr = outText.substring(outText.indexOf('['));
|
|
3104
3117
|
const checklists = JSON.parse(jsonStr);
|
|
3105
|
-
|
|
3118
|
+
|
|
3106
3119
|
if (!checklists || checklists.length === 0) {
|
|
3107
3120
|
err("No checklists found on card. Create one first using 'awkit trello checklist <name>'.");
|
|
3108
3121
|
break;
|
|
3109
3122
|
}
|
|
3110
|
-
|
|
3123
|
+
|
|
3111
3124
|
// Add to the LAST checklist (most recently appended usually)
|
|
3112
3125
|
const targetChecklist = checklists[checklists.length - 1];
|
|
3113
3126
|
const checklistId = targetChecklist.id;
|
|
3114
|
-
|
|
3127
|
+
|
|
3115
3128
|
// 2. Add item via curl
|
|
3116
3129
|
const url = `https://api.trello.com/1/checklists/${checklistId}/checkItems?name=${encodeURIComponent(text)}&key=${credItem.api_key}&token=${credItem.api_token}`;
|
|
3117
3130
|
const addRes = spawnSync('curl', ['-s', '-X', 'POST', url], { encoding: 'utf-8' });
|
|
3118
|
-
|
|
3131
|
+
|
|
3119
3132
|
const responseJson = JSON.parse(addRes.stdout);
|
|
3120
3133
|
if (responseJson.id) {
|
|
3121
3134
|
ok(`Item added successfully to checklist "${targetChecklist.name}".`);
|
|
@@ -3192,7 +3205,7 @@ function checkAutoUpdate() {
|
|
|
3192
3205
|
|
|
3193
3206
|
function cmdServe(args) {
|
|
3194
3207
|
const http = require('http');
|
|
3195
|
-
|
|
3208
|
+
|
|
3196
3209
|
let port = 8080;
|
|
3197
3210
|
let serveDir = process.cwd();
|
|
3198
3211
|
|
package/package.json
CHANGED
|
@@ -2,9 +2,5 @@
|
|
|
2
2
|
"name": "mobile-android",
|
|
3
3
|
"auto_install": false,
|
|
4
4
|
"description": "Android development skills: Kotlin, Jetpack Compose, reverse engineering, AdMob ROAS, and APK analysis",
|
|
5
|
-
"skills": [
|
|
6
|
-
|
|
7
|
-
"android-re-analyzer",
|
|
8
|
-
"admob-roas"
|
|
9
|
-
]
|
|
10
|
-
}
|
|
5
|
+
"skills": []
|
|
6
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neural-memory",
|
|
3
|
-
"auto_install":
|
|
3
|
+
"auto_install": true,
|
|
4
4
|
"description": "NeuralMemory-powered ambient brain sync with spreading activation recall",
|
|
5
5
|
"skills": [
|
|
6
6
|
"nm-memory-sync",
|
|
@@ -38,4 +38,4 @@
|
|
|
38
38
|
"Claude Code": "Run: /plugin install neural-memory"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|