codymaster 4.4.5 → 4.5.1

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.
Files changed (186) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +29 -14
  3. package/commands/demo.md +1 -1
  4. package/dist/context-bus.js +70 -0
  5. package/dist/context-db.js +265 -0
  6. package/dist/continuity.js +12 -0
  7. package/dist/file-watcher.js +79 -0
  8. package/dist/index.js +152 -1
  9. package/dist/l0-indexer.js +158 -0
  10. package/dist/mcp-context-server.js +400 -0
  11. package/dist/migrate-json-to-sqlite.js +126 -0
  12. package/dist/skill-chain.js +19 -3
  13. package/dist/token-budget.js +108 -0
  14. package/dist/uri-resolver.js +203 -0
  15. package/package.json +4 -1
  16. package/skills/_shared/helpers.md +50 -14
  17. package/skills/cm-autopilot/SKILL.md +29 -0
  18. package/skills/cm-autopilot/scripts/autopilot.py +190 -0
  19. package/skills/cm-continuity/SKILL.md +90 -28
  20. package/skills/cm-skill-chain/SKILL.md +47 -1
  21. package/skills/cm-start/SKILL.md +11 -2
  22. package/skills/boxme-git-config/SKILL.md +0 -56
  23. package/skills/boxme-local-dev/SKILL.md +0 -66
  24. package/skills/jobs-to-be-done/SKILL.md +0 -266
  25. package/skills/jobs-to-be-done/references/case-studies.md +0 -154
  26. package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
  27. package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
  28. package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
  29. package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
  30. package/skills/marketplace-report-crawler/SKILL.md +0 -176
  31. package/skills/marketplace-report-crawler/config/accounts.json +0 -41
  32. package/skills/marketplace-report-crawler/config/report-types.json +0 -422
  33. package/skills/marketplace-report-crawler/config/sessions.json +0 -3
  34. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
  35. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
  36. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
  37. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
  38. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
  39. package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
  40. package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
  41. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
  42. package/skills/medical-research/SKILL.md +0 -194
  43. package/skills/medical-research/scripts/evidence_checker.py +0 -288
  44. package/skills/mom-test/SKILL.md +0 -267
  45. package/skills/mom-test/references/avoiding-bad-data.md +0 -221
  46. package/skills/mom-test/references/case-studies.md +0 -306
  47. package/skills/mom-test/references/commitment-advancement.md +0 -219
  48. package/skills/mom-test/references/finding-conversations.md +0 -251
  49. package/skills/mom-test/references/processing-learning.md +0 -256
  50. package/skills/mom-test/references/question-patterns.md +0 -198
  51. package/skills/pandasai-analytics/SKILL.md +0 -251
  52. package/skills/release-it/SKILL.md +0 -235
  53. package/skills/release-it/references/anti-patterns.md +0 -279
  54. package/skills/release-it/references/capacity-planning.md +0 -285
  55. package/skills/release-it/references/chaos-engineering.md +0 -325
  56. package/skills/release-it/references/deployment-strategies.md +0 -331
  57. package/skills/release-it/references/observability.md +0 -301
  58. package/skills/release-it/references/stability-patterns.md +0 -355
  59. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
  60. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
  61. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
  62. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
  63. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
  64. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
  65. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
  66. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
  67. package/skills/skill-creator-ultra/README.md +0 -1242
  68. package/skills/skill-creator-ultra/SKILL.md +0 -388
  69. package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
  70. package/skills/skill-creator-ultra/agents/comparator.md +0 -202
  71. package/skills/skill-creator-ultra/agents/grader.md +0 -223
  72. package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
  73. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
  74. package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
  75. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
  76. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
  77. package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
  78. package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
  79. package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
  80. package/skills/skill-creator-ultra/install.ps1 +0 -289
  81. package/skills/skill-creator-ultra/install.sh +0 -313
  82. package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
  83. package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
  84. package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
  85. package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
  86. package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
  87. package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
  88. package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
  89. package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
  90. package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
  91. package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
  92. package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
  93. package/skills/skill-creator-ultra/resources/checklist.md +0 -243
  94. package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
  95. package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
  96. package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
  97. package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
  98. package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
  99. package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
  100. package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
  101. package/skills/skill-creator-ultra/resources/schemas.md +0 -430
  102. package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
  103. package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
  104. package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
  105. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
  106. package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
  107. package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
  108. package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
  109. package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
  110. package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
  111. package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
  112. package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
  113. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
  114. package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
  115. package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
  116. package/skills/tailwind-mastery/SKILL.md +0 -229
  117. package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
  118. package/skills/vercel-react-best-practices/README.md +0 -123
  119. package/skills/vercel-react-best-practices/SKILL.md +0 -143
  120. package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  121. package/skills/vercel-react-best-practices/rules/_template.md +0 -28
  122. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  123. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  124. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  125. package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  126. package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  127. package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  128. package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  129. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  130. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  131. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  132. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  133. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  134. package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  135. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  136. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  137. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  138. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  139. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  140. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  141. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  142. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  143. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  144. package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  145. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  146. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  147. package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  148. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  149. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  150. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  151. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  152. package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  153. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  154. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  155. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  156. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  157. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  158. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  159. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  160. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  161. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  162. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  163. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  164. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  165. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  166. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  167. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  168. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  169. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  170. package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  171. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  172. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  173. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  174. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  175. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  176. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  177. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  178. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  179. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  180. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  181. package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  182. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  183. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
  184. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  185. package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  186. package/skills/web-design-guidelines/SKILL.md +0 -39
@@ -1,102 +0,0 @@
1
- #!/usr/bin/env bash
2
- # =============================================================================
3
- # ab-wrapper.sh — agent-browser thin wrapper
4
- # =============================================================================
5
- # Provides shorthand commands for marketplace report crawling.
6
- # Cross-agent compatible: any AI agent can call these commands.
7
- #
8
- # Usage:
9
- # ./ab-wrapper.sh login <platform> <brand-id> # Guided login
10
- # ./ab-wrapper.sh check <platform> <brand-id> # Check session
11
- # ./ab-wrapper.sh crawl <platform> <brand-id> <YYYYMM> # Crawl reports
12
- # ./ab-wrapper.sh open <platform> <brand-id> <url> # Open URL with session
13
- # ./ab-wrapper.sh snapshot <platform> <brand-id> # Get page snapshot
14
- # ./ab-wrapper.sh close <platform> <brand-id> # Close browser
15
- # =============================================================================
16
-
17
- set -euo pipefail
18
-
19
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20
- PROFILE_ROOT="${MARKETPLACE_PROFILE_ROOT:-$HOME/.marketplace-crawler/profiles}"
21
- AB_CMD="${AGENT_BROWSER_CMD:-npx -y agent-browser}"
22
-
23
- get_profile_dir() {
24
- echo "$PROFILE_ROOT/${1}-${2}"
25
- }
26
-
27
- ensure_ab() {
28
- if ! command -v agent-browser &>/dev/null && ! npx -y agent-browser --version &>/dev/null 2>&1; then
29
- echo "❌ agent-browser not found. Installing..."
30
- npm install -g agent-browser 2>/dev/null || {
31
- echo "⚠️ Global install failed. Using npx (slower first run)."
32
- }
33
- fi
34
- }
35
-
36
- # --- Commands ---
37
-
38
- case "${1:-help}" in
39
- login)
40
- "$SCRIPT_DIR/session-manager.sh" login "$2" "$3"
41
- ;;
42
- check)
43
- "$SCRIPT_DIR/session-manager.sh" check "$2" "$3"
44
- ;;
45
- crawl)
46
- platform="$2"
47
- brand_id="$3"
48
- period="${4:-$(date -v-1m +%Y%m 2>/dev/null || date -d '-1 month' +%Y%m)}"
49
- echo "🕷️ Starting crawl: $platform / $brand_id / $period"
50
- node "$SCRIPT_DIR/crawl-runner.js" --plan --platform "$platform" --brand-id "$brand_id" --period "$period"
51
- ;;
52
- open)
53
- profile_dir=$(get_profile_dir "$2" "$3")
54
- mkdir -p "$profile_dir"
55
- $AB_CMD --profile "$profile_dir" open "$4"
56
- ;;
57
- snapshot)
58
- profile_dir=$(get_profile_dir "$2" "$3")
59
- $AB_CMD --profile "$profile_dir" snapshot -i --json
60
- ;;
61
- screenshot)
62
- profile_dir=$(get_profile_dir "$2" "$3")
63
- output="${4:-/tmp/marketplace-screenshot-$(date +%s).png}"
64
- $AB_CMD --profile "$profile_dir" screenshot "$output"
65
- echo "📸 Screenshot saved: $output"
66
- ;;
67
- close)
68
- profile_dir=$(get_profile_dir "$2" "$3")
69
- $AB_CMD --profile "$profile_dir" close 2>/dev/null || true
70
- echo "🔒 Browser closed for $2/$3"
71
- ;;
72
- exec)
73
- # Pass any agent-browser command with the correct profile
74
- profile_dir=$(get_profile_dir "$2" "$3")
75
- shift 3
76
- $AB_CMD --profile "$profile_dir" "$@"
77
- ;;
78
- help|*)
79
- echo ""
80
- echo "🕷️ ab-wrapper — Marketplace Browser Automation"
81
- echo "════════════════════════════════════════════════"
82
- echo ""
83
- echo "Session Management:"
84
- echo " login <platform> <brand-id> Guided login (headed browser)"
85
- echo " check <platform> <brand-id> Check session validity"
86
- echo ""
87
- echo "Crawling:"
88
- echo " crawl <platform> <brand-id> [YYYYMM] Generate & show crawl plan"
89
- echo ""
90
- echo "Browser Control:"
91
- echo " open <platform> <brand-id> <url> Open URL with saved session"
92
- echo " snapshot <platform> <brand-id> Get accessibility tree (JSON)"
93
- echo " screenshot <platform> <brand-id> [path] Take screenshot"
94
- echo " close <platform> <brand-id> Close browser"
95
- echo " exec <platform> <brand-id> <ab-args...> Run any agent-browser command"
96
- echo ""
97
- echo "Environment:"
98
- echo " MARKETPLACE_PROFILE_ROOT Default: ~/.marketplace-crawler/profiles"
99
- echo " AGENT_BROWSER_CMD Default: npx -y agent-browser"
100
- echo ""
101
- ;;
102
- esac
@@ -1,114 +0,0 @@
1
- /**
2
- * Lazada Browser Actions
3
- * ==================================================
4
- * JavaScript snippets to inject into Lazada Seller Center pages.
5
- */
6
-
7
- /**
8
- * Open calendar and go to the target month using next/prev buttons
9
- * Used for platform_income, platform_wallet
10
- */
11
- function lazadaCalendar_selectMonthRange(yearMonth) {
12
- // Try to find the date picker input
13
- const dateInputs = document.querySelectorAll('.next-date-picker-input input, input[placeholder*="YYYY"]');
14
- if (dateInputs.length > 0) {
15
- dateInputs[0].click(); // Open picker
16
-
17
- setTimeout(() => {
18
- // Find the 'Last Month' preset if it exists
19
- const presets = document.querySelectorAll('.next-date-picker-quick span');
20
- for (const preset of presets) {
21
- if (preset.textContent.trim() === 'Tháng trước' || preset.textContent.trim() === 'Last month') {
22
- preset.click();
23
- return;
24
- }
25
- }
26
-
27
- // Otherwise find the 'OK' button and click it to accept default (usually last 30 days)
28
- const okBtn = document.querySelector('.next-btn-primary');
29
- if (okBtn) okBtn.click();
30
- }, 500);
31
- }
32
- }
33
-
34
- /**
35
- * Lazada Paid Ads uses a specific date input format
36
- * Used for paid_ads_onsite_report, paid_ads_product
37
- */
38
- function lazadaAds_setDateRange(startDateStr, endDateStr) {
39
- // Check the 'Product' checkbox if needed for paid_ads_product
40
- const productCheckbox = document.querySelector('input[type="checkbox"][value="product"]');
41
- if (productCheckbox && !productCheckbox.checked) {
42
- productCheckbox.click();
43
- }
44
-
45
- // Find date inputs (DD/MM/YYYY format usually)
46
- const inputs = document.querySelectorAll('.next-input input');
47
- if (inputs.length >= 2) {
48
- // Start Date
49
- inputs[0].value = startDateStr;
50
- inputs[0].dispatchEvent(new Event('input', { bubbles: true }));
51
- inputs[0].dispatchEvent(new Event('change', { bubbles: true }));
52
-
53
- // End Date
54
- inputs[1].value = endDateStr;
55
- inputs[1].dispatchEvent(new Event('input', { bubbles: true }));
56
- inputs[1].dispatchEvent(new Event('change', { bubbles: true }));
57
- }
58
- }
59
-
60
- /**
61
- * Select from Lazada dropdown list
62
- * Used for shipping_fee_details
63
- */
64
- function lazadaMultiSelect_selectDates(targetYYYYMM) {
65
- // Find the dropdown button
66
- const dropdownTrigger = document.querySelector('.next-select-trigger');
67
- if (dropdownTrigger) {
68
- dropdownTrigger.click();
69
-
70
- setTimeout(() => {
71
- // Select logic
72
- const items = document.querySelectorAll('.next-menu-item');
73
- for(const item of items) {
74
- if(item.textContent.trim().includes(targetYYYYMM)) {
75
- item.click();
76
- }
77
- }
78
- }, 500);
79
- }
80
- }
81
-
82
- /**
83
- * Click export button on Lazada
84
- */
85
- function lazadaClickExport() {
86
- const buttons = document.querySelectorAll('button');
87
- for (const btn of buttons) {
88
- const text = btn.textContent.trim().toLowerCase();
89
- if (text.includes('tải xuống') || text.includes('xuất dữ liệu') || text.includes('export') || text.includes('download')) {
90
- btn.click();
91
-
92
- // Some export buttons open a dropdown. If so, look for Excel/PDF option.
93
- setTimeout(() => {
94
- const menuItems = document.querySelectorAll('.next-menu-item');
95
- for (const item of menuItems) {
96
- if (item.textContent.toLowerCase().includes('excel') || item.textContent.toLowerCase().includes('pdf')) {
97
- item.click();
98
- return true;
99
- }
100
- }
101
- }, 500);
102
-
103
- return true;
104
- }
105
- }
106
- return false;
107
- }
108
-
109
- module.exports = {
110
- lazadaCalendar_selectMonthRange,
111
- lazadaAds_setDateRange,
112
- lazadaMultiSelect_selectDates,
113
- lazadaClickExport
114
- };
@@ -1,94 +0,0 @@
1
- /**
2
- * Shopee Browser Actions
3
- * ==================================================
4
- * JavaScript snippets to inject into Shopee Seller pages.
5
- */
6
-
7
- /**
8
- * Select month range on Shopee's typical calendar-range picker
9
- * Used for platform_income, platform_wallet, ads_wallet_historical
10
- */
11
- function shopeeCalendar_selectMonthRange(yearMonth) {
12
- // Shopee usually has a date range input that opens a popper with two calendars.
13
- const dateRangeInputs = document.querySelectorAll('.shopee-date-range-picker input');
14
- if (dateRangeInputs.length > 0) {
15
- dateRangeInputs[0].click(); // Open picker
16
-
17
- setTimeout(() => {
18
- // Very naive approach: try to find 'THIS_MONTH' or 'LAST_MONTH' button
19
- // Or try to select the 1st and last day. Shopee's calendar is highly custom.
20
- const lastMonthBtn = Array.from(document.querySelectorAll('.shopee-popover span, .shopee-popover div')).find(el => el.textContent.trim() === 'Tháng trước' || el.textContent.trim() === 'Last Month');
21
- if (lastMonthBtn) {
22
- lastMonthBtn.click();
23
- }
24
- }, 500);
25
- }
26
- }
27
-
28
- /**
29
- * Select a specific month in a month-picker
30
- * Used for platform_report (PDF)
31
- */
32
- function shopeeMonthPicker_selectMonth(yearMonth) {
33
- const monthInput = document.querySelector('.shopeesc-month-picker, .month-picker-input');
34
- if (monthInput) {
35
- monthInput.click();
36
- setTimeout(() => {
37
- // Find the specific month cell
38
- const monthStr = parseInt(yearMonth.substring(4, 6), 10).toString();
39
- const cells = document.querySelectorAll('.month-cell, .shopee-month-table td');
40
- for (const cell of cells) {
41
- if (cell.textContent.trim() === monthStr || cell.textContent.trim().includes(`Tháng ${monthStr}`)) {
42
- cell.click();
43
- break;
44
- }
45
- }
46
- }, 500);
47
- }
48
- }
49
-
50
- /**
51
- * Input Start and End date directly into text inputs
52
- * Used for paid_ads_onsite_report (date_input)
53
- */
54
- function shopeeDateInput_setDate(startDateStr, endDateStr) {
55
- // Usually there are two inputs: start date and end date
56
- const inputs = document.querySelectorAll('.shopee-input__input[placeholder*="YYYY"], input[placeholder*="Ngày"]');
57
- if (inputs.length >= 2) {
58
- // Start date
59
- const startInput = inputs[0];
60
- startInput.value = startDateStr;
61
- startInput.dispatchEvent(new Event('input', { bubbles: true }));
62
- startInput.dispatchEvent(new Event('change', { bubbles: true }));
63
-
64
- // End date
65
- const endInput = inputs[1];
66
- endInput.value = endDateStr;
67
- endInput.dispatchEvent(new Event('input', { bubbles: true }));
68
- endInput.dispatchEvent(new Event('change', { bubbles: true }));
69
- }
70
- }
71
-
72
- /**
73
- * Click export button
74
- */
75
- function shopeeClickExport() {
76
- // Tries to find common export buttons
77
- const exportBtn = Array.from(document.querySelectorAll('button')).find(btn => {
78
- const text = btn.textContent.trim().toLowerCase();
79
- return text.includes('xuất') || text.includes('export') || text.includes('tải');
80
- });
81
-
82
- if (exportBtn) {
83
- exportBtn.click();
84
- return true;
85
- }
86
- return false;
87
- }
88
-
89
- module.exports = {
90
- shopeeCalendar_selectMonthRange,
91
- shopeeMonthPicker_selectMonth,
92
- shopeeDateInput_setDate,
93
- shopeeClickExport
94
- };
@@ -1,272 +0,0 @@
1
- /**
2
- * TikTok Browser Actions — Date Selection & Export
3
- * ==================================================
4
- * JavaScript snippets to inject into TikTok Seller Center pages.
5
- *
6
- * Extracted from Power Automate Desktop flow: "20260209 GBS Tiktok"
7
- *
8
- * TikTok uses:
9
- * 1. core-picker (TikTok Design System) — for Income, Wallet pages
10
- * 2. pulse-select — for pagination on Invoice page
11
- */
12
-
13
- // ============================================================================
14
- // TIKTOK INCOME / WALLET — core-picker date range
15
- // URL: https://seller-vn.tiktok.com/finance/transactions?shop_region=VN&tab=settled_tab
16
- // URL: https://seller-vn.tiktok.com/finance/withdraw-new
17
- // ============================================================================
18
-
19
- /**
20
- * Select first and last day of target month in TikTok core-picker
21
- * Used for TikTok Income and Wallet pages
22
- *
23
- * @param {string} yearMonth - Format: "YYYYMM" (e.g., "202602")
24
- */
25
- function tiktokCorePicker_selectMonthRange(yearMonth) {
26
- const lastDay = new Date(yearMonth.slice(0, 4), yearMonth.slice(4, 6), 0)
27
- .getDate().toString().padStart(2, '0');
28
-
29
- const cells = [...document.querySelectorAll('.core-picker-cell-in-view .core-picker-date-value')];
30
- const first = cells.find(c => c.textContent.trim() === '01');
31
- const last = cells.find(c => c.textContent.trim() === lastDay);
32
-
33
- first?.click();
34
- setTimeout(() => last?.click(), 100);
35
- }
36
-
37
- // ============================================================================
38
- // TIKTOK AFFILIATE INVOICE — Month picker + Table scraping
39
- // URL: https://seller-vn.tiktok.com/finance/invoice?shop_region=VN
40
- // ============================================================================
41
-
42
- /**
43
- * Select target month in TikTok month picker (Jan-Dec display)
44
- * Used for TikTok Affiliate Invoice page
45
- *
46
- * @param {string} yearMonth - Format: "YYYYMM" (e.g., "202602")
47
- */
48
- function tiktokMonthPicker_selectMonth(yearMonth) {
49
- const month = parseInt(yearMonth.substring(4, 6), 10);
50
- const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
51
- 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
52
- const monthName = monthNames[month - 1];
53
-
54
- const cells = document.querySelectorAll('.core-picker-date-value');
55
- let targetCell = null;
56
-
57
- for (let i = 0; i < cells.length; i++) {
58
- if (cells[i].textContent.trim() === monthName) {
59
- targetCell = cells[i];
60
- break;
61
- }
62
- }
63
-
64
- if (targetCell) {
65
- targetCell.click();
66
- setTimeout(function() {
67
- targetCell.click(); // Double-click to confirm
68
- }, 300);
69
- }
70
- }
71
-
72
- /**
73
- * Set pagination to 50 items per page
74
- * Used on TikTok Affiliate Invoice page for large datasets
75
- */
76
- function tiktokPagination_set50PerPage() {
77
- const options = document.querySelectorAll('.pulse-select-option');
78
-
79
- for (let option of options) {
80
- const label = option.querySelector('.pulse-select-option-label-single');
81
- if (label && label.textContent.trim() === '50/Page') {
82
- option.click();
83
- return true;
84
- }
85
- }
86
- return false;
87
- }
88
-
89
- /**
90
- * Get max page number from TikTok pagination
91
- * @returns {number|null} Max page number
92
- */
93
- function tiktokPagination_getMaxPage() {
94
- const paginationElement = document.querySelector('.core-pagination-list');
95
- if (!paginationElement) return null;
96
-
97
- const pageItems = paginationElement.querySelectorAll('.core-pagination-item');
98
- let maxPage = 0;
99
-
100
- pageItems.forEach(item => {
101
- const text = item.textContent.trim();
102
- if (/^\d+$/.test(text)) {
103
- const pageNumber = parseInt(text, 10);
104
- if (pageNumber > maxPage) {
105
- maxPage = pageNumber;
106
- }
107
- }
108
- });
109
-
110
- return maxPage || null;
111
- }
112
-
113
- /**
114
- * Click next page button in TikTok pagination
115
- */
116
- function tiktokPagination_clickNext() {
117
- const element = document.querySelector('.core-pagination-item-next');
118
- if (!element) return;
119
-
120
- element.scrollIntoView({ behavior: 'smooth', block: 'center' });
121
-
122
- const rect = element.getBoundingClientRect();
123
- const x = rect.left + rect.width / 2;
124
- const y = rect.top + rect.height / 2;
125
-
126
- element.dispatchEvent(new MouseEvent('mousemove', {
127
- view: window, bubbles: true, cancelable: true, clientX: x, clientY: y
128
- }));
129
-
130
- element.dispatchEvent(new MouseEvent('click', {
131
- view: window, bubbles: true, cancelable: true, button: 0
132
- }));
133
- }
134
-
135
- // ============================================================================
136
- // HELPER — Scroll to bottom
137
- // ============================================================================
138
-
139
- function scrollToBottom() {
140
- window.scrollTo({
141
- top: document.body.scrollHeight,
142
- behavior: "smooth"
143
- });
144
- }
145
-
146
- // ============================================================================
147
- // BROWSER AGENT INSTRUCTIONS — TIKTOK COMPLETE FLOWS
148
- // ============================================================================
149
-
150
- /**
151
- * === TIKTOK PLATFORM INCOME ===
152
- * 1. Navigate to: https://seller-vn.tiktok.com/finance/transactions?shop_region=VN&tab=settled_tab
153
- * 2. Wait for text "Lịch sử xuất dữ liệu" to appear (up to 200s)
154
- * 3. Wait 1s
155
- * 4. Click "Xuất" button
156
- * 5. Wait 1s → Click SVG calendar icon to open date picker
157
- * 6. Wait 1s → Click another SVG to clear existing date
158
- * 7. Execute tiktokCorePicker_selectMonthRange(yearMonth)
159
- * 8. Wait 1s → Click "OK" button
160
- * 9. Wait 2s → Click "Xuất" (the export Span inside popup)
161
- * 10. Wait for "Đang xuất" text to disappear (up to 600s!)
162
- * 11. Wait 1s → Click "Tải xuống" button
163
- * 12. Save file as: {yearMonth}_{brand}_platform_income.xlsx
164
- *
165
- * === TIKTOK WALLET ===
166
- * 1. Navigate to: https://seller-vn.tiktok.com/finance/withdraw-new?is_new_connect=0&shop_region=VN
167
- * 2. Wait for "Lịch sử xuất dữ liệu" (up to 200s)
168
- * 3. Scroll down 500px
169
- * 4. Click "Xuất"
170
- * 5. Click SVG → clear → select date range (same as Income)
171
- * 6. Click OK → Click "Xuất" button
172
- * 7. Wait for "Đang xuất" to disappear (up to 600s)
173
- * 8. Click "Tải xuống"
174
- * 9. Save as: {yearMonth}_{brand}_platform_wallet.xlsx
175
- *
176
- * === TIKTOK AFFILIATE INVOICE ===
177
- * 1. Navigate to: https://seller-vn.tiktok.com/finance/invoice?shop_region=VN
178
- * 2. Wait for page load
179
- * 3. Click "Biên nhận hoa hồng liên kết"
180
- * 4. Wait 2s → Click SVG to open month picker
181
- * 5. Execute tiktokMonthPicker_selectMonth(yearMonth)
182
- * 6. Wait 3s → Click "OK"
183
- * 7. Check if "Nothing here at the moment" exists
184
- * - If yes: skip (no data)
185
- * - If no: continue below
186
- * 8. Scroll to bottom
187
- * 9. Click pagination dropdown → Execute tiktokPagination_set50PerPage()
188
- * 10. Get max page: tiktokPagination_getMaxPage()
189
- * 11. If single page: extract table → save as .xlsx
190
- * 12. If multiple pages: loop through pages:
191
- * a. Extract table data from current page
192
- * b. Save as: {yearMonth}_{brand}_affiliate_invoice_report_part_{pageNum}.xlsx
193
- * c. Click next: tiktokPagination_clickNext()
194
- * d. Wait 2s → repeat
195
- *
196
- * TABLE EXTRACTION CSS SELECTOR:
197
- * Rows: html > body > div:eq(0) > div:eq(1) > main > div:eq(0) >
198
- * div:eq(0) > div:eq(0) > div:eq(1) > div:eq(0) > div:eq(0) >
199
- * div:eq(0) > div:eq(0) > div:eq(2) > div:eq(0) > div:eq(0) >
200
- * div:eq(0) > div:eq(0) > div:eq(0) > table > tbody > tr
201
- *
202
- * Columns:
203
- * - td:eq(0) > div > span > div > div (Column 1)
204
- * - td:eq(1) > div > span (Column 2)
205
- * - td:eq(2) > div > span (Column 3)
206
- * - td:eq(3) > div > span (Column 4)
207
- * - td:eq(4) > div > span (Column 5)
208
- */
209
-
210
- // ============================================================================
211
- // TIKTOK ADS AND AFFILIATE ORDERS
212
- // ============================================================================
213
-
214
- /**
215
- * Handle TikTok Business Center (Ads) date picker
216
- * Used for ads_cost, ads_revenue
217
- */
218
- function tiktokAds_setDateRange(startDateStr, endDateStr) {
219
- // Usually involves clicking the date picker button
220
- const pickerBtn = document.querySelector('.byted-date-picker, .date-picker-trigger');
221
- if (pickerBtn) {
222
- pickerBtn.click();
223
- setTimeout(() => {
224
- // Very naive: find inputs or presets inside the popup
225
- // TikTok Business Center uses a complex React date picker
226
- const presets = document.querySelectorAll('.byted-picker-preset-item');
227
- for (const preset of presets) {
228
- if (preset.textContent.trim().includes('Last Month') || preset.textContent.trim().includes('Tháng trước')) {
229
- preset.click();
230
- break;
231
- }
232
- }
233
- }, 500);
234
- }
235
- }
236
-
237
- /**
238
- * Click typical TikTok export buttons
239
- */
240
- function tiktokClickExport() {
241
- const exportBtns = document.querySelectorAll('button');
242
- for (const btn of exportBtns) {
243
- const text = btn.textContent.trim().toLowerCase();
244
- if (text.includes('export') || text.includes('xuất') || text.includes('tải')) {
245
- btn.click();
246
- return true;
247
- }
248
- }
249
-
250
- // Also check divs/spans that act as buttons (TikTok uses these heavily)
251
- const allElements = document.querySelectorAll('div, span');
252
- for (const el of allElements) {
253
- const text = el.textContent.trim().toLowerCase();
254
- if ((text === 'export' || text === 'xuất' || text === 'tải xuống') && el.children.length === 0) {
255
- el.click();
256
- return true;
257
- }
258
- }
259
-
260
- return false;
261
- }
262
-
263
- module.exports = {
264
- tiktokCorePicker_selectMonthRange,
265
- tiktokMonthPicker_selectMonth,
266
- tiktokPagination_set50PerPage,
267
- tiktokPagination_getMaxPage,
268
- tiktokPagination_clickNext,
269
- scrollToBottom,
270
- tiktokAds_setDateRange,
271
- tiktokClickExport
272
- };