@powerbuilder/skill 1.0.3 → 1.0.6

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/README.md CHANGED
@@ -1,8 +1,5 @@
1
- # @powerbuilder/skill
2
1
 
3
- > **PowerBuilder** — a toolkit of AI agent skills for the Microsoft Power Platform.
4
-
5
- Install production-ready AI agent skills into your **.cursor**, **.claude**, or **.gemini** workspace folders with a single command.
2
+ **PowerBuilder** — a toolkit for the Microsoft Power Platform.
6
3
 
7
4
  ---
8
5
 
@@ -15,7 +12,6 @@ npx @powerbuilder/skill codeapp
15
12
 
16
13
  The wizard will:
17
14
  1. Auto-detect `.cursor`, `.claude`, and `.gemini` folders in your project
18
- 2. Copy the skill files into each detected agent folder
19
15
  3. Install `@playwright/cli` globally for automated testing
20
16
  4. Open `make.powerapps.com` in a persistent browser session for first-time login
21
17
 
@@ -46,12 +42,11 @@ The installer searches upward from your current directory to your home folder an
46
42
  ## Requirements
47
43
 
48
44
  - Node.js ≥ 18
49
- - At least one of: Cursor, Claude Code, or Gemini CLI installed in the workspace
50
45
 
51
46
  ---
52
47
 
53
48
  ## About PowerBuilder
54
49
 
55
- **PowerBuilder** is a personal toolkit by [TuongDoan](https://github.com/tuongdoan) — a growing collection of AI agent skills, scripts, and utilities for the Microsoft Power Platform.
50
+ **PowerBuilder** is a toolkit by [TuongDoan](https://github.com/tuongdoan) — a growing collection of AI agent skills, scripts, and utilities for the Microsoft Power Platform.
56
51
 
57
- © 2025 TuongDoan
52
+ © 2026 TuongDoan
package/lib/banner.js CHANGED
@@ -4,18 +4,15 @@ export function printBanner() {
4
4
  const cyan = chalk.cyanBright.bold;
5
5
  const yellow = chalk.yellowBright.bold;
6
6
  const dim = chalk.dim;
7
- const green = chalk.greenBright;
8
7
 
9
8
  console.log();
10
- console.log(cyan(' ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗ '));
11
- console.log(cyan(' ██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗'));
12
- console.log(cyan(' ██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝'));
13
- console.log(cyan(' ██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗'));
14
- console.log(cyan(' ██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║'));
15
- console.log(cyan(' ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝'));
9
+ console.log(cyan(' ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗ '));
10
+ console.log(cyan(' ██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ ██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗'));
11
+ console.log(cyan(' ██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ ██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝'));
12
+ console.log(cyan(' ██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ ██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗'));
13
+ console.log(cyan(' ██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ ██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║'));
14
+ console.log(cyan(' ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝'));
16
15
  console.log();
17
- console.log(' ' + yellow('⚡ Power Apps Code App Skill') + dim(' AI Agent Skill Installer'));
18
- console.log(' ' + green(' Skill Set by TuongDoan') + dim(' · github.com/tuongdoan · © 2025'));
19
- console.log(' ' + dim('─'.repeat(85)));
16
+ console.log(' ' + yellow('⚡ Power Apps Code App Skill') + dim(' · by TuongDoan · © 2026'));
20
17
  console.log();
21
18
  }
@@ -3,13 +3,10 @@ import { existsSync } from 'fs';
3
3
  import os from 'os';
4
4
 
5
5
  /**
6
- * Search for supported AI agent root folders starting from cwd up to home dir.
7
- * Returns an array of { target, agentFolder, dir } objects for each found target.
8
- *
9
- * Supported targets:
10
- * - .cursor → skills go into <target>/.cursor/rules/ (or just .cursor/skills/)
11
- * - .claude → skills go into <target>/.claude/skills/
12
- * - .gemini → skills go into <target>/.gemini/antigravity/skills/
6
+ * Detect where to install skills:
7
+ * - .cursor → optional: skip if folder doesn't exist
8
+ * - .gemini → optional: skip if folder doesn't exist
9
+ * - .claude → always: create ~/.claude if it doesn't exist
13
10
  */
14
11
  export function detectTargets(startDir = process.cwd()) {
15
12
  const home = os.homedir();
@@ -22,34 +19,30 @@ export function detectTargets(startDir = process.cwd()) {
22
19
  dirs.push(current);
23
20
  if (current === home) break;
24
21
  const parent = path.dirname(current);
25
- if (parent === current) break; // filesystem root
22
+ if (parent === current) break;
26
23
  current = parent;
27
24
  }
28
25
 
29
26
  for (const dir of dirs) {
30
27
  const cursorDir = path.join(dir, '.cursor');
31
- const claudeDir = path.join(dir, '.claude');
32
28
  const geminiDir = path.join(dir, '.gemini');
33
29
 
30
+ // .cursor — optional: only add if the folder already exists
34
31
  if (existsSync(cursorDir)) {
35
32
  targets.push({
36
33
  target: '.cursor',
34
+ label: 'Cursor',
37
35
  agentFolder: cursorDir,
38
36
  skillsDir: path.join(cursorDir, 'rules', 'skills'),
39
37
  dir,
40
38
  });
41
39
  }
42
- if (existsSync(claudeDir)) {
43
- targets.push({
44
- target: '.claude',
45
- agentFolder: claudeDir,
46
- skillsDir: path.join(claudeDir, 'skills'),
47
- dir,
48
- });
49
- }
40
+
41
+ // .gemini — optional: only add if the folder already exists
50
42
  if (existsSync(geminiDir)) {
51
43
  targets.push({
52
44
  target: '.gemini',
45
+ label: 'Google Antigravity',
53
46
  agentFolder: geminiDir,
54
47
  skillsDir: path.join(geminiDir, 'antigravity', 'skills'),
55
48
  dir,
@@ -57,6 +50,16 @@ export function detectTargets(startDir = process.cwd()) {
57
50
  }
58
51
  }
59
52
 
53
+ // .claude — always install to home dir; folder will be created if missing
54
+ const claudeDir = path.join(home, '.claude');
55
+ targets.push({
56
+ target: '.claude',
57
+ label: 'Claude',
58
+ agentFolder: claudeDir,
59
+ skillsDir: path.join(claudeDir, 'skills'),
60
+ dir: home,
61
+ });
62
+
60
63
  // Deduplicate by agentFolder
61
64
  const seen = new Set();
62
65
  return targets.filter(t => {
@@ -55,10 +55,6 @@ const SKILL_SRC = path.resolve(__dirname, '..', 'skills', 'codeapp');
55
55
  // ─── STEP 1 — Detect & confirm targets ───────────────────────────────────────
56
56
 
57
57
  async function stepDetectTargets() {
58
- hr();
59
- log(chalk.bold('Step 1/4 · Detecting AI agent folders…'));
60
- hr();
61
-
62
58
  const detected = detectTargets();
63
59
 
64
60
  if (detected.length === 0) {
@@ -67,21 +63,45 @@ async function stepDetectTargets() {
67
63
  process.exit(1);
68
64
  }
69
65
 
70
- info(`Found ${detected.length} target(s):`);
71
- for (const t of detected) {
72
- log(` ${chalk.cyanBright(t.target)} → ${chalk.dim(t.skillsDir)}`);
66
+ return detected;
67
+ }
68
+
69
+ // ─── SUMMARY — Show plan & confirm before doing anything ──────────────────────
70
+
71
+ async function stepShowSummary(targets) {
72
+ console.log();
73
+ log(chalk.bold.yellowBright(' 📋 Installation Plan'));
74
+ console.log();
75
+
76
+ // Item 1 — skill files, list human-friendly target names
77
+ log(` ${chalk.cyanBright('1.')} Power Apps Code App Skill for:`);
78
+ for (const t of targets) {
79
+ log(` ${chalk.greenBright('•')} ${chalk.white(t.label)}`);
73
80
  }
74
81
  console.log();
75
82
 
76
- const proceed = await askConfirm('Install Code App skill into ALL detected targets?');
83
+ // Item 2 playwright (description inline)
84
+ log(` ${chalk.cyanBright('2.')} Playwright CLI ${chalk.dim('(used for automated E2E testing of your Power Apps)')}`);
85
+ console.log();
86
+
87
+ // Login heads-up
88
+ log(chalk.bold.yellowBright(' ⚠️ One-time login required after install:'));
89
+ log(` After Playwright CLI is installed, a browser window will open`);
90
+ log(` and you will need to log in to ${chalk.white('Power Apps')} ${chalk.dim('(make.powerapps.com)')}`);
91
+ log(` This saves a persistent session so future test runs won't ask`);
92
+ log(` you to log in again.`);
93
+ console.log();
94
+
95
+ const proceed = await askConfirm('Proceed with installation?', true);
77
96
  if (!proceed) {
78
- warn('Installation cancelled.');
97
+ warn('Installation cancelled. Nothing was changed.');
79
98
  process.exit(0);
80
99
  }
81
-
82
- return detected;
100
+ console.log();
83
101
  }
84
102
 
103
+
104
+
85
105
  // ─── STEP 2 — Copy skill files ────────────────────────────────────────────────
86
106
 
87
107
  async function stepCopySkill(targets) {
@@ -185,11 +205,9 @@ async function stepOpenPowerApps() {
185
205
  // ─── MAIN ─────────────────────────────────────────────────────────────────────
186
206
 
187
207
  export async function runCodeAppWizard() {
188
- console.log(chalk.bold.cyanBright(' Power Apps Code App Skill Installer'));
189
- console.log(chalk.dim(' This wizard will install the skill into your AI agent folders'));
190
- console.log(chalk.dim(' and set up Playwright for automated testing.\n'));
191
-
208
+ // Detect first, show summary, confirm — then execute
192
209
  const targets = await stepDetectTargets();
210
+ await stepShowSummary(targets);
193
211
  await stepCopySkill(targets);
194
212
  await stepInstallPlaywright();
195
213
  await stepOpenPowerApps();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerbuilder/skill",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "PowerBuilder skill installer — drop production-ready AI agent skills into .cursor, .claude, or .gemini folders with one command.",
5
5
  "author": "TuongDoan",
6
6
  "license": "MIT",