fluentui-design 0.1.0
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/CHANGELOG.md +50 -0
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/bin.d.ts +18 -0
- package/dist/bin.js +71 -0
- package/dist/bin.js.map +1 -0
- package/dist/skill/install-skill.d.ts +256 -0
- package/dist/skill/install-skill.js +546 -0
- package/dist/skill/install-skill.js.map +1 -0
- package/package.json +90 -0
- package/skills/fluentui-design/SKILL.md +184 -0
- package/skills/fluentui-design/references/checklists/accessibility-review.md +51 -0
- package/skills/fluentui-design/references/checklists/design-before-code.md +53 -0
- package/skills/fluentui-design/references/checklists/visual-review.md +45 -0
- package/skills/fluentui-design/references/foundation/accessibility.md +70 -0
- package/skills/fluentui-design/references/foundation/composition-and-state.md +92 -0
- package/skills/fluentui-design/references/foundation/responsive-and-localization.md +63 -0
- package/skills/fluentui-design/references/foundation/styling-and-tokens.md +71 -0
- package/skills/fluentui-design/references/index.md +42 -0
- package/skills/fluentui-design/references/maintenance/refresh-and-repin.md +68 -0
- package/skills/fluentui-design/references/patterns/PAT-001-application-shell.md +77 -0
- package/skills/fluentui-design/references/patterns/PAT-002-list-page.md +85 -0
- package/skills/fluentui-design/references/patterns/PAT-003-record-detail.md +74 -0
- package/skills/fluentui-design/references/patterns/PAT-004-form-page.md +78 -0
- package/skills/fluentui-design/references/patterns/PAT-005-contextual-edit.md +75 -0
- package/skills/fluentui-design/references/patterns/PAT-006-settings-page.md +78 -0
- package/skills/fluentui-design/references/patterns/PAT-007-multi-step-task.md +79 -0
- package/skills/fluentui-design/references/patterns/PAT-008-dashboard.md +78 -0
- package/skills/fluentui-design/references/rules/index.md +97 -0
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install and update the Fluent UI design Agent Skill into coding agents.
|
|
3
|
+
*
|
|
4
|
+
* The skill ships inside the `fluentui-design` package at
|
|
5
|
+
* `skills/fluentui-design/`. This installer copies it into the skill
|
|
6
|
+
* directories of the supported clients (OpenCode, Claude Code, Codex, and the
|
|
7
|
+
* shared `.agents/skills` convention), globally or per project. It replaces
|
|
8
|
+
* only the namespaced `fluentui-design/` directory and never touches any other
|
|
9
|
+
* skill.
|
|
10
|
+
*
|
|
11
|
+
* @module skill/install-skill
|
|
12
|
+
*/
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import readline from "node:readline/promises";
|
|
18
|
+
/** The skill directory name installed into every client. */
|
|
19
|
+
export const SKILL_DIR_NAME = "fluentui-design";
|
|
20
|
+
/** The marker file written inside an installed skill directory. */
|
|
21
|
+
export const MARKER_FILE = ".fluentui-design-skill.json";
|
|
22
|
+
/** The value recorded in the marker's `source` field. */
|
|
23
|
+
export const SOURCE_NAME = "fluentui-design";
|
|
24
|
+
/** Prefix of the temporary sibling directory used during an atomic install. */
|
|
25
|
+
export const TEMP_PREFIX = ".fluentui-design-skill.tmp-";
|
|
26
|
+
/** Prefix of the backup directory kept while an install is in flight. */
|
|
27
|
+
export const BACKUP_PREFIX = ".fluentui-design-skill.bak-";
|
|
28
|
+
/**
|
|
29
|
+
* Supported clients and the directories in which each looks for skills.
|
|
30
|
+
*/
|
|
31
|
+
export const CLIENTS = [
|
|
32
|
+
{ id: "opencode", global: [".config", "opencode", "skills"], project: [".opencode", "skills"] },
|
|
33
|
+
{ id: "claude", global: [".claude", "skills"], project: [".claude", "skills"] },
|
|
34
|
+
{ id: "codex", global: [".codex", "skills"], project: [".codex", "skills"] },
|
|
35
|
+
{ id: "agents", global: [".agents", "skills"], project: [".agents", "skills"] },
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the packaged skill directory.
|
|
39
|
+
*
|
|
40
|
+
* Works in both layouts: shipped (`<package>/dist/skill` ->
|
|
41
|
+
* `<package>/skills`) and repository (`<repo>/src/skill` ->
|
|
42
|
+
* `<repo>/.agents/skills`). The packaged copy is preferred when both exist.
|
|
43
|
+
*
|
|
44
|
+
* @param moduleUrl - `import.meta.url` of this module.
|
|
45
|
+
* @param override - Optional explicit source directory.
|
|
46
|
+
* @returns Absolute path to the skill directory.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveSourceDir(moduleUrl, override) {
|
|
49
|
+
if (override) {
|
|
50
|
+
return path.resolve(override);
|
|
51
|
+
}
|
|
52
|
+
const moduleDir = path.dirname(fileURLToPath(moduleUrl));
|
|
53
|
+
const packaged = path.join(moduleDir, "..", "..", "skills", SKILL_DIR_NAME);
|
|
54
|
+
const repository = path.join(moduleDir, "..", "..", ".agents", "skills", SKILL_DIR_NAME);
|
|
55
|
+
for (const candidate of [packaged, repository]) {
|
|
56
|
+
if (fs.existsSync(path.join(candidate, "SKILL.md"))) {
|
|
57
|
+
return path.resolve(candidate);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return path.resolve(packaged);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Detects which clients are present on the machine.
|
|
64
|
+
*
|
|
65
|
+
* A client is present when its global directory, the global directory's
|
|
66
|
+
* parent, or its project directory exists.
|
|
67
|
+
*
|
|
68
|
+
* @param options - Detection inputs.
|
|
69
|
+
* @param options.home - Home directory.
|
|
70
|
+
* @param options.cwd - Project root.
|
|
71
|
+
* @param options.exists - Existence predicate (injectable for tests).
|
|
72
|
+
* @returns Detected clients with resolved global and project directories.
|
|
73
|
+
*/
|
|
74
|
+
export function detectClients(options) {
|
|
75
|
+
const detected = [];
|
|
76
|
+
for (const client of CLIENTS) {
|
|
77
|
+
const globalDir = path.join(options.home, ...client.global);
|
|
78
|
+
const projectDir = path.join(options.cwd, ...client.project);
|
|
79
|
+
const present = options.exists(globalDir) ||
|
|
80
|
+
options.exists(path.dirname(globalDir)) ||
|
|
81
|
+
options.exists(projectDir);
|
|
82
|
+
if (present) {
|
|
83
|
+
detected.push({ id: client.id, globalDir, projectDir });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return detected;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolves the skills directories to operate on.
|
|
90
|
+
*
|
|
91
|
+
* Explicit `--target` directories win, then `--project`, otherwise every
|
|
92
|
+
* detected client's global directory is used.
|
|
93
|
+
*
|
|
94
|
+
* @param options - Selection options.
|
|
95
|
+
* @param options.targets - Explicit target directories.
|
|
96
|
+
* @param options.project - Use project directories instead of global ones.
|
|
97
|
+
* @param detected - Detected clients.
|
|
98
|
+
* @returns Absolute target skills directories.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveTargets(options, detected) {
|
|
101
|
+
if (options.targets.length > 0) {
|
|
102
|
+
return options.targets.map((target) => path.resolve(target));
|
|
103
|
+
}
|
|
104
|
+
if (options.project) {
|
|
105
|
+
return detected.map((client) => client.projectDir);
|
|
106
|
+
}
|
|
107
|
+
return detected.map((client) => client.globalDir);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Reports whether a path exists as any entry type, including a dangling
|
|
111
|
+
* symlink (which `fs.existsSync` reports as absent because it follows links).
|
|
112
|
+
*
|
|
113
|
+
* @param targetPath - Path to test.
|
|
114
|
+
* @returns True when an entry exists.
|
|
115
|
+
*/
|
|
116
|
+
function entryExists(targetPath) {
|
|
117
|
+
try {
|
|
118
|
+
fs.lstatSync(targetPath);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Reads the installed marker, if present and parseable.
|
|
127
|
+
*
|
|
128
|
+
* @param targetDir - Installed skill directory.
|
|
129
|
+
* @returns The parsed marker, or undefined.
|
|
130
|
+
*/
|
|
131
|
+
export function readMarker(targetDir) {
|
|
132
|
+
const markerPath = path.join(targetDir, MARKER_FILE);
|
|
133
|
+
if (!fs.existsSync(markerPath)) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(fs.readFileSync(markerPath, "utf-8"));
|
|
138
|
+
return isSkillMarker(parsed) ? parsed : undefined;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Type guard for a parsed marker object.
|
|
146
|
+
*
|
|
147
|
+
* The marker is read back from disk, so its shape is untrusted input and is
|
|
148
|
+
* validated instead of asserted.
|
|
149
|
+
*
|
|
150
|
+
* @param value - Parsed JSON value.
|
|
151
|
+
* @returns True when the value has the marker's required string fields.
|
|
152
|
+
*/
|
|
153
|
+
function isSkillMarker(value) {
|
|
154
|
+
if (typeof value !== "object" || value === null) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return ("version" in value &&
|
|
158
|
+
typeof value.version === "string" &&
|
|
159
|
+
"source" in value &&
|
|
160
|
+
typeof value.source === "string" &&
|
|
161
|
+
"installedAt" in value &&
|
|
162
|
+
typeof value.installedAt === "string");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Writes the version marker into a skill directory.
|
|
166
|
+
*
|
|
167
|
+
* @param dir - Skill directory.
|
|
168
|
+
* @param version - Installed package version.
|
|
169
|
+
*/
|
|
170
|
+
function writeMarker(dir, version) {
|
|
171
|
+
const marker = {
|
|
172
|
+
version,
|
|
173
|
+
source: SOURCE_NAME,
|
|
174
|
+
installedAt: new Date().toISOString(),
|
|
175
|
+
};
|
|
176
|
+
fs.writeFileSync(path.join(dir, MARKER_FILE), `${JSON.stringify(marker, null, 2)}\n`, "utf-8");
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Escapes regular-expression metacharacters in a literal string.
|
|
180
|
+
*
|
|
181
|
+
* @param value - Literal text to escape.
|
|
182
|
+
* @returns The text safe to embed in a regular expression.
|
|
183
|
+
*/
|
|
184
|
+
function escapeForRegExp(value) {
|
|
185
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Removes leftover temp and backup directories from an interrupted run.
|
|
189
|
+
*
|
|
190
|
+
* @param targetDir - Skills directory to clean.
|
|
191
|
+
*/
|
|
192
|
+
function cleanLeftovers(targetDir) {
|
|
193
|
+
const leftover = new RegExp(`^(${escapeForRegExp(TEMP_PREFIX)}|${escapeForRegExp(BACKUP_PREFIX)})\\d+$`);
|
|
194
|
+
for (const entry of fs.readdirSync(targetDir)) {
|
|
195
|
+
if (leftover.test(entry)) {
|
|
196
|
+
fs.rmSync(path.join(targetDir, entry), { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Guards against replacing a directory that is not this skill.
|
|
202
|
+
*
|
|
203
|
+
* A destination is safe to replace when it is absent, when it carries a
|
|
204
|
+
* marker, or when it contains a `SKILL.md`. Anything else is unrelated content
|
|
205
|
+
* and is left untouched.
|
|
206
|
+
*
|
|
207
|
+
* @param dest - Candidate destination directory.
|
|
208
|
+
* @throws When the destination exists but does not look like a skill.
|
|
209
|
+
*/
|
|
210
|
+
function assertReplaceable(dest) {
|
|
211
|
+
if (!entryExists(dest)) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// A valid marker or a `SKILL.md` identifies a directory as a skill install.
|
|
215
|
+
// Anything else is unrelated content and must be left untouched.
|
|
216
|
+
if (readMarker(dest) || fs.existsSync(path.join(dest, "SKILL.md"))) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
throw new Error(`refusing to replace unrelated directory: ${dest}`);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Removes control and display-formatting characters from a value before
|
|
223
|
+
* printing it.
|
|
224
|
+
*
|
|
225
|
+
* The installed version is read back from disk, so it is untrusted input; the
|
|
226
|
+
* raw value could otherwise carry terminal escape sequences or bidirectional
|
|
227
|
+
* override characters into the output.
|
|
228
|
+
*
|
|
229
|
+
* @param value - Text to sanitize.
|
|
230
|
+
* @returns The text without control or display-formatting characters.
|
|
231
|
+
*/
|
|
232
|
+
export function sanitizeForDisplay(value) {
|
|
233
|
+
return value.replace(/[\u0000-\u001f\u007f-\u009f\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u2069\ufeff]/g, "");
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Installs the skill into one skills directory by atomically replacing
|
|
237
|
+
* `fluentui-design/`.
|
|
238
|
+
*
|
|
239
|
+
* The tree is first copied into a temp sibling, then renamed over the
|
|
240
|
+
* destination. An existing destination is moved aside as a backup and restored
|
|
241
|
+
* if the rename fails, so a failed install never leaves a partial skill.
|
|
242
|
+
*
|
|
243
|
+
* @param options - Install inputs.
|
|
244
|
+
* @returns A summary of the action.
|
|
245
|
+
* @throws When the source is not a skill or the destination is unrelated.
|
|
246
|
+
*/
|
|
247
|
+
export function installSkill(options) {
|
|
248
|
+
const { sourceDir, version, link = false, dryRun = false } = options;
|
|
249
|
+
const targetDir = path.resolve(options.targetDir);
|
|
250
|
+
const dest = path.join(targetDir, SKILL_DIR_NAME);
|
|
251
|
+
if (!fs.existsSync(path.join(sourceDir, "SKILL.md"))) {
|
|
252
|
+
throw new Error(`source is not a skill directory (missing SKILL.md): ${sourceDir}`);
|
|
253
|
+
}
|
|
254
|
+
if (dryRun) {
|
|
255
|
+
return { targetDir, dest, dryRun: true };
|
|
256
|
+
}
|
|
257
|
+
assertReplaceable(dest);
|
|
258
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
259
|
+
cleanLeftovers(targetDir);
|
|
260
|
+
if (link) {
|
|
261
|
+
const tmpLink = path.join(targetDir, `${TEMP_PREFIX}${process.pid}`);
|
|
262
|
+
const backup = path.join(targetDir, `${BACKUP_PREFIX}${process.pid}`);
|
|
263
|
+
try {
|
|
264
|
+
fs.symlinkSync(sourceDir, tmpLink, process.platform === "win32" ? "junction" : "dir");
|
|
265
|
+
if (entryExists(dest)) {
|
|
266
|
+
fs.renameSync(dest, backup);
|
|
267
|
+
}
|
|
268
|
+
fs.renameSync(tmpLink, dest);
|
|
269
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
fs.rmSync(tmpLink, { recursive: true, force: true });
|
|
273
|
+
if (entryExists(backup) && !entryExists(dest)) {
|
|
274
|
+
fs.renameSync(backup, dest);
|
|
275
|
+
}
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
return { targetDir, dest, linked: true };
|
|
279
|
+
}
|
|
280
|
+
const tmp = path.join(targetDir, `${TEMP_PREFIX}${process.pid}`);
|
|
281
|
+
const backup = path.join(targetDir, `${BACKUP_PREFIX}${process.pid}`);
|
|
282
|
+
try {
|
|
283
|
+
fs.cpSync(sourceDir, tmp, { recursive: true });
|
|
284
|
+
writeMarker(tmp, version);
|
|
285
|
+
if (entryExists(dest)) {
|
|
286
|
+
fs.renameSync(dest, backup);
|
|
287
|
+
}
|
|
288
|
+
fs.renameSync(tmp, dest);
|
|
289
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
293
|
+
if (entryExists(backup) && !entryExists(dest)) {
|
|
294
|
+
fs.renameSync(backup, dest);
|
|
295
|
+
}
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
return { targetDir, dest, installed: true };
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Removes the installed skill from one skills directory.
|
|
302
|
+
*
|
|
303
|
+
* Only the `fluentui-design/` directory is removed; any sibling skill is
|
|
304
|
+
* untouched.
|
|
305
|
+
*
|
|
306
|
+
* @param options - Uninstall inputs.
|
|
307
|
+
* @param options.targetDir - Skills directory.
|
|
308
|
+
* @param options.dryRun - Report only, write nothing.
|
|
309
|
+
* @returns A summary of the action.
|
|
310
|
+
*/
|
|
311
|
+
export function uninstallSkill(options) {
|
|
312
|
+
const targetDir = path.resolve(options.targetDir);
|
|
313
|
+
const dryRun = Boolean(options.dryRun);
|
|
314
|
+
const dest = path.join(targetDir, SKILL_DIR_NAME);
|
|
315
|
+
const existed = entryExists(dest);
|
|
316
|
+
if (!dryRun && existed) {
|
|
317
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
318
|
+
}
|
|
319
|
+
return { targetDir, dest, removed: existed, dryRun };
|
|
320
|
+
}
|
|
321
|
+
/** Prints the CLI help and the client table. */
|
|
322
|
+
function printUsage() {
|
|
323
|
+
console.log(`Install and update the Fluent UI design Agent Skill.
|
|
324
|
+
|
|
325
|
+
Usage:
|
|
326
|
+
fluentui-design skill install [options] Install or update the skill
|
|
327
|
+
fluentui-design skill status [options] Show the installed version
|
|
328
|
+
fluentui-design skill uninstall [options] Remove the installed skill
|
|
329
|
+
|
|
330
|
+
Options:
|
|
331
|
+
--all Install into every detected client
|
|
332
|
+
--target <dir> Install into a specific skills directory (repeatable)
|
|
333
|
+
--project Use project-level skill directories
|
|
334
|
+
--link Symlink to the source instead of copying
|
|
335
|
+
--dry-run Show what would happen without writing
|
|
336
|
+
-h, --help Show this help
|
|
337
|
+
|
|
338
|
+
Clients:
|
|
339
|
+
opencode ~/.config/opencode/skills .opencode/skills
|
|
340
|
+
claude ~/.claude/skills .claude/skills
|
|
341
|
+
codex ~/.codex/skills .codex/skills
|
|
342
|
+
agents ~/.agents/skills .agents/skills`);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Parses argv into a sub-command and options.
|
|
346
|
+
*
|
|
347
|
+
* @param argv - Arguments after `skill` (or the full argument list).
|
|
348
|
+
* @returns The parsed command and options, plus an error for invalid input.
|
|
349
|
+
*/
|
|
350
|
+
export function parseArgs(argv) {
|
|
351
|
+
const options = {
|
|
352
|
+
targets: [],
|
|
353
|
+
project: false,
|
|
354
|
+
link: false,
|
|
355
|
+
dryRun: false,
|
|
356
|
+
all: false,
|
|
357
|
+
};
|
|
358
|
+
const first = argv[0];
|
|
359
|
+
let command = "install";
|
|
360
|
+
let start = 0;
|
|
361
|
+
if (first === "install" || first === "status" || first === "uninstall") {
|
|
362
|
+
command = first;
|
|
363
|
+
start = 1;
|
|
364
|
+
}
|
|
365
|
+
let error;
|
|
366
|
+
for (let i = start; i < argv.length; i += 1) {
|
|
367
|
+
const arg = argv[i];
|
|
368
|
+
if (arg === undefined) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (arg === "--all")
|
|
372
|
+
options.all = true;
|
|
373
|
+
else if (arg === "--project")
|
|
374
|
+
options.project = true;
|
|
375
|
+
else if (arg === "--link")
|
|
376
|
+
options.link = true;
|
|
377
|
+
else if (arg === "--dry-run")
|
|
378
|
+
options.dryRun = true;
|
|
379
|
+
else if (arg === "--target") {
|
|
380
|
+
const value = argv[i + 1];
|
|
381
|
+
if (!value || value.startsWith("--")) {
|
|
382
|
+
error = `${arg} requires a directory argument`;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
options.targets.push(value);
|
|
386
|
+
i += 1;
|
|
387
|
+
}
|
|
388
|
+
else if (arg === "-h" || arg === "--help") {
|
|
389
|
+
return { command: "help", options };
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
error = `unknown argument '${arg}'`;
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (error) {
|
|
397
|
+
return { command: "install", options, error };
|
|
398
|
+
}
|
|
399
|
+
return { command, options };
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Reads the installer package's own version.
|
|
403
|
+
*
|
|
404
|
+
* @param moduleUrl - `import.meta.url` of this module.
|
|
405
|
+
* @returns The version, or `0.0.0` when it cannot be read.
|
|
406
|
+
*/
|
|
407
|
+
function readPackageVersion(moduleUrl) {
|
|
408
|
+
const moduleDir = path.dirname(fileURLToPath(moduleUrl));
|
|
409
|
+
try {
|
|
410
|
+
const raw = fs.readFileSync(path.join(moduleDir, "..", "..", "package.json"), "utf-8");
|
|
411
|
+
const parsed = JSON.parse(raw);
|
|
412
|
+
if (typeof parsed === "object" && parsed !== null && "version" in parsed) {
|
|
413
|
+
const { version } = parsed;
|
|
414
|
+
return typeof version === "string" ? version : "0.0.0";
|
|
415
|
+
}
|
|
416
|
+
return "0.0.0";
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
return "0.0.0";
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Prompts the user to choose among the detected clients.
|
|
424
|
+
*
|
|
425
|
+
* Only called on an interactive terminal. An empty answer selects every
|
|
426
|
+
* detected client, and an out-of-range answer falls back to all of them so the
|
|
427
|
+
* command never silently installs nothing.
|
|
428
|
+
*
|
|
429
|
+
* @param detected - Detected clients.
|
|
430
|
+
* @returns The chosen clients.
|
|
431
|
+
*/
|
|
432
|
+
async function promptSelection(detected) {
|
|
433
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
434
|
+
try {
|
|
435
|
+
console.log("Detected agent skill directories:");
|
|
436
|
+
detected.forEach((client, index) => {
|
|
437
|
+
console.log(` ${index + 1}. ${client.id} ${client.globalDir}`);
|
|
438
|
+
});
|
|
439
|
+
const answer = await rl.question("Install into which? (comma-separated numbers, empty = all): ");
|
|
440
|
+
const trimmed = answer.trim();
|
|
441
|
+
if (trimmed === "") {
|
|
442
|
+
return detected;
|
|
443
|
+
}
|
|
444
|
+
const chosen = trimmed
|
|
445
|
+
.split(",")
|
|
446
|
+
.map((part) => Number.parseInt(part.trim(), 10) - 1)
|
|
447
|
+
.filter((index) => index >= 0 && index < detected.length)
|
|
448
|
+
.map((index) => detected[index])
|
|
449
|
+
.filter((client) => client !== undefined);
|
|
450
|
+
return chosen.length > 0 ? chosen : detected;
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
rl.close();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Runs the installer CLI.
|
|
458
|
+
*
|
|
459
|
+
* @param argv - Arguments after `skill`.
|
|
460
|
+
* @param io - Injectable environment values.
|
|
461
|
+
* @returns Process exit code.
|
|
462
|
+
*/
|
|
463
|
+
export async function main(argv, io = {}) {
|
|
464
|
+
const home = io.home ?? homedir();
|
|
465
|
+
const cwd = io.cwd ?? process.cwd();
|
|
466
|
+
const isTTY = io.isTTY ?? Boolean(process.stdin.isTTY);
|
|
467
|
+
const version = io.version ?? readPackageVersion(import.meta.url);
|
|
468
|
+
const { command, options, error } = parseArgs(argv);
|
|
469
|
+
if (error) {
|
|
470
|
+
console.error(`error: ${error}`);
|
|
471
|
+
return 2;
|
|
472
|
+
}
|
|
473
|
+
if (command === "help") {
|
|
474
|
+
printUsage();
|
|
475
|
+
return 0;
|
|
476
|
+
}
|
|
477
|
+
const sourceDir = resolveSourceDir(import.meta.url, io.sourceDir);
|
|
478
|
+
const detected = detectClients({ home, cwd, exists: fs.existsSync });
|
|
479
|
+
if (detected.length === 0 && options.targets.length === 0) {
|
|
480
|
+
console.error("No known agent skill directories were found. Use --target <dir> to specify one.");
|
|
481
|
+
printUsage();
|
|
482
|
+
return 1;
|
|
483
|
+
}
|
|
484
|
+
let targets;
|
|
485
|
+
if (options.targets.length > 0 || options.project || options.all || !isTTY) {
|
|
486
|
+
targets = resolveTargets(options, detected);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
let chosen;
|
|
490
|
+
try {
|
|
491
|
+
chosen = await promptSelection(detected);
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
console.error("cancelled before any change was made.");
|
|
495
|
+
return 130;
|
|
496
|
+
}
|
|
497
|
+
targets = chosen.map((client) => client.globalDir);
|
|
498
|
+
}
|
|
499
|
+
if (targets.length === 0) {
|
|
500
|
+
console.error("No target directories were selected.");
|
|
501
|
+
return 1;
|
|
502
|
+
}
|
|
503
|
+
if (command === "status") {
|
|
504
|
+
let allInstalled = true;
|
|
505
|
+
for (const target of targets) {
|
|
506
|
+
const dest = path.join(path.resolve(target), SKILL_DIR_NAME);
|
|
507
|
+
const marker = readMarker(dest);
|
|
508
|
+
if (marker) {
|
|
509
|
+
console.log(`${dest}: installed ${sanitizeForDisplay(marker.version)}`);
|
|
510
|
+
}
|
|
511
|
+
else if (entryExists(dest)) {
|
|
512
|
+
console.log(`${dest}: installed (linked)`);
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
console.log(`${dest}: not installed`);
|
|
516
|
+
allInstalled = false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return allInstalled ? 0 : 1;
|
|
520
|
+
}
|
|
521
|
+
if (command === "uninstall") {
|
|
522
|
+
for (const target of targets) {
|
|
523
|
+
const result = uninstallSkill({ targetDir: target, dryRun: options.dryRun });
|
|
524
|
+
console.log(`${options.dryRun ? "would remove" : "removed"} ${result.dest}`);
|
|
525
|
+
}
|
|
526
|
+
return 0;
|
|
527
|
+
}
|
|
528
|
+
for (const target of targets) {
|
|
529
|
+
try {
|
|
530
|
+
const result = installSkill({
|
|
531
|
+
sourceDir,
|
|
532
|
+
targetDir: target,
|
|
533
|
+
version,
|
|
534
|
+
link: options.link,
|
|
535
|
+
dryRun: options.dryRun,
|
|
536
|
+
});
|
|
537
|
+
console.log(`${options.dryRun ? "would install" : "installed"} ${result.dest}`);
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
541
|
+
return 1;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return 0;
|
|
545
|
+
}
|
|
546
|
+
//# sourceMappingURL=install-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-skill.js","sourceRoot":"","sources":["../../src/skill/install-skill.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fluentui-design",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Evidence-backed Agent Skill for composing web applications with Fluent UI React v9",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"fluentui",
|
|
9
|
+
"react",
|
|
10
|
+
"agent-skill",
|
|
11
|
+
"design-system",
|
|
12
|
+
"accessibility"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/blendsdk/fluentui-design#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/blendsdk/fluentui-design.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/blendsdk/fluentui-design/issues"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"fluentui-design": "dist/bin.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist/",
|
|
30
|
+
"skills/fluentui-design/",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"CHANGELOG.md"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public",
|
|
37
|
+
"registry": "https://registry.npmjs.org/"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"lint": "eslint .",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"extract-facts": "tsx scripts/extract-facts.ts",
|
|
44
|
+
"validate:sources": "tsx scripts/validate-sources.ts",
|
|
45
|
+
"validate:rules": "tsx scripts/validate-rules.ts",
|
|
46
|
+
"validate:all": "npm run validate:sources && npm run validate:rules",
|
|
47
|
+
"lint:rules": "tsx scripts/lint-rules.ts",
|
|
48
|
+
"check:facts": "tsx scripts/check-facts.ts",
|
|
49
|
+
"check:version": "node scripts/check-version.mjs",
|
|
50
|
+
"generate": "tsx scripts/generate.ts",
|
|
51
|
+
"generate:check": "tsx scripts/generate.ts --check",
|
|
52
|
+
"check:refs": "tsx scripts/check-references.ts",
|
|
53
|
+
"check:evaluation": "tsx scripts/evaluate.ts",
|
|
54
|
+
"check:examples": "tsx scripts/check-examples.ts",
|
|
55
|
+
"scan:secrets": "tsx scripts/scan-secrets.ts",
|
|
56
|
+
"freshness": "tsx scripts/freshness.ts",
|
|
57
|
+
"build:cli": "tsc -p tsconfig.build.json",
|
|
58
|
+
"assemble": "tsx scripts/assemble.ts",
|
|
59
|
+
"clean": "node -e \"const fs=require('node:fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('skills',{recursive:true,force:true})\"",
|
|
60
|
+
"prepack": "npm run clean && npm run build:cli && npm run assemble",
|
|
61
|
+
"prepublishOnly": "npm run verify:static",
|
|
62
|
+
"dev": "vite",
|
|
63
|
+
"build": "vite build",
|
|
64
|
+
"preview": "vite preview",
|
|
65
|
+
"verify:static": "npm run typecheck && npm run lint && npm run test && npm run validate:all && npm run lint:rules && npm run check:facts && npm run check:version && npm run generate:check && npm run check:refs && npm run check:evaluation && npm run check:examples && npm run scan:secrets && npm run freshness -- --check",
|
|
66
|
+
"test:e2e": "npm run build && playwright test",
|
|
67
|
+
"verify": "npm run verify:static && npm run test:e2e"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@axe-core/playwright": "^4.13.0",
|
|
72
|
+
"@fluentui/react-components": "9.74.7",
|
|
73
|
+
"@fluentui/react-icons": "^2.0.341",
|
|
74
|
+
"@playwright/test": "^1.63.0",
|
|
75
|
+
"@types/node": "^22.20.4",
|
|
76
|
+
"@types/react": "18.3.31",
|
|
77
|
+
"@types/react-dom": "18.3.7",
|
|
78
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
79
|
+
"ajv": "^8.20.0",
|
|
80
|
+
"ajv-formats": "^3.0.1",
|
|
81
|
+
"eslint": "^10.11.0",
|
|
82
|
+
"react": "18.3.1",
|
|
83
|
+
"react-dom": "18.3.1",
|
|
84
|
+
"tsx": "^4.23.13",
|
|
85
|
+
"typescript": "5.9.3",
|
|
86
|
+
"typescript-eslint": "^8.70.0",
|
|
87
|
+
"vite": "^8.3.0",
|
|
88
|
+
"vitest": "^5.0.1"
|
|
89
|
+
}
|
|
90
|
+
}
|