@runecraft/grimoire 1.0.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/LICENSE +21 -0
- package/README.md +21 -0
- package/catalog.json +9 -0
- package/dist/grimoire.js +1758 -0
- package/package.json +54 -0
- package/references/definition-of-done.md +67 -0
- package/references/testing-patterns.md +260 -0
- package/skills/code-review-and-quality/README.md +13 -0
- package/skills/code-review-and-quality/SKILL.md +389 -0
- package/skills/code-simplification/README.md +13 -0
- package/skills/code-simplification/SKILL.md +338 -0
- package/skills/debugging-and-error-recovery/README.md +13 -0
- package/skills/debugging-and-error-recovery/SKILL.md +343 -0
- package/skills/debugging-and-error-recovery/scripts/__pycache__/triage_state.cpython-314.pyc +0 -0
- package/skills/debugging-and-error-recovery/scripts/triage_state.py +206 -0
- package/skills/deprecation-and-migration/README.md +13 -0
- package/skills/deprecation-and-migration/SKILL.md +248 -0
- package/skills/deprecation-and-migration/scripts/__pycache__/migration_tracker.cpython-314.pyc +0 -0
- package/skills/deprecation-and-migration/scripts/migration_tracker.py +237 -0
- package/skills/doubt-driven-development/README.md +13 -0
- package/skills/doubt-driven-development/SKILL.md +251 -0
- package/skills/git-commit-learning/.skill-meta.json +14 -0
- package/skills/git-commit-learning/README.md +205 -0
- package/skills/git-commit-learning/SKILL.md +435 -0
- package/skills/git-commit-learning/references/commit-patterns.md +595 -0
- package/skills/git-worktree/README.md +13 -0
- package/skills/git-worktree/SKILL.md +220 -0
- package/skills/idea-refine/README.md +13 -0
- package/skills/idea-refine/SKILL.md +186 -0
- package/skills/interview-me/README.md +13 -0
- package/skills/interview-me/SKILL.md +233 -0
- package/skills/linkedin-audit/SKILL.md +98 -0
- package/skills/linkedin-audit/references/dashboard-spec.md +43 -0
- package/skills/memory-management/README.md +13 -0
- package/skills/memory-management/SKILL.md +198 -0
- package/skills/security-and-hardening/README.md +13 -0
- package/skills/security-and-hardening/SKILL.md +472 -0
- package/skills/shipping-and-launch/README.md +13 -0
- package/skills/shipping-and-launch/SKILL.md +317 -0
- package/skills/skill-forge/README.md +153 -0
- package/skills/skill-forge/SKILL.md +291 -0
- package/skills/skill-forge/assets/SKILL.template.md +73 -0
- package/skills/skill-forge/references/authoring-patterns.md +249 -0
- package/skills/skill-forge/references/description-optimization.md +171 -0
- package/skills/skill-forge/references/output-evaluation.md +276 -0
- package/skills/skill-forge/references/scripts-guide.md +232 -0
- package/skills/skill-forge/references/spec.md +175 -0
- package/skills/skill-forge/scripts/validate.py +536 -0
- package/skills/spec-driven/.skill-meta.json +14 -0
- package/skills/spec-driven/README.md +335 -0
- package/skills/spec-driven/SKILL.md +174 -0
- package/skills/spec-driven/references/code-analysis.md +98 -0
- package/skills/spec-driven/references/coding-principles.md +56 -0
- package/skills/spec-driven/references/context-limits.md +31 -0
- package/skills/spec-driven/references/design.md +199 -0
- package/skills/spec-driven/references/discuss.md +136 -0
- package/skills/spec-driven/references/implement.md +425 -0
- package/skills/spec-driven/references/lessons.md +113 -0
- package/skills/spec-driven/references/memory.md +126 -0
- package/skills/spec-driven/references/specify.md +210 -0
- package/skills/spec-driven/references/sub-agents.md +96 -0
- package/skills/spec-driven/references/tasks.md +484 -0
- package/skills/spec-driven/references/validate.md +350 -0
- package/skills/spec-driven/scripts/__pycache__/lessons.cpython-314.pyc +0 -0
- package/skills/spec-driven/scripts/lessons.py +370 -0
- package/skills/spec-loop/README.md +36 -0
- package/skills/spec-loop/SKILL.md +61 -0
- package/skills/test-driven-development/README.md +13 -0
- package/skills/test-driven-development/SKILL.md +388 -0
- package/skills/typescript-patterns/README.md +13 -0
- package/skills/typescript-patterns/SKILL.md +346 -0
- package/skills/using-agent-skills/README.md +13 -0
- package/skills/using-agent-skills/SKILL.md +187 -0
package/dist/grimoire.js
ADDED
|
@@ -0,0 +1,1758 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
12
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
+
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
23
|
+
for (let key of __getOwnPropNames(mod))
|
|
24
|
+
if (!__hasOwnProp.call(to, key))
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (canCache)
|
|
31
|
+
cache.set(mod, to);
|
|
32
|
+
return to;
|
|
33
|
+
};
|
|
34
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
35
|
+
|
|
36
|
+
// ../../node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
37
|
+
var require_src = __commonJS(function(exports, module) {
|
|
38
|
+
var ESC2 = "\x1B";
|
|
39
|
+
var CSI2 = `${ESC2}[`;
|
|
40
|
+
var beep = "\x07";
|
|
41
|
+
var cursor = {
|
|
42
|
+
to(x, y) {
|
|
43
|
+
if (!y)
|
|
44
|
+
return `${CSI2}${x + 1}G`;
|
|
45
|
+
return `${CSI2}${y + 1};${x + 1}H`;
|
|
46
|
+
},
|
|
47
|
+
move(x, y) {
|
|
48
|
+
let ret = "";
|
|
49
|
+
if (x < 0)
|
|
50
|
+
ret += `${CSI2}${-x}D`;
|
|
51
|
+
else if (x > 0)
|
|
52
|
+
ret += `${CSI2}${x}C`;
|
|
53
|
+
if (y < 0)
|
|
54
|
+
ret += `${CSI2}${-y}A`;
|
|
55
|
+
else if (y > 0)
|
|
56
|
+
ret += `${CSI2}${y}B`;
|
|
57
|
+
return ret;
|
|
58
|
+
},
|
|
59
|
+
up: (count = 1) => `${CSI2}${count}A`,
|
|
60
|
+
down: (count = 1) => `${CSI2}${count}B`,
|
|
61
|
+
forward: (count = 1) => `${CSI2}${count}C`,
|
|
62
|
+
backward: (count = 1) => `${CSI2}${count}D`,
|
|
63
|
+
nextLine: (count = 1) => `${CSI2}E`.repeat(count),
|
|
64
|
+
prevLine: (count = 1) => `${CSI2}F`.repeat(count),
|
|
65
|
+
left: `${CSI2}G`,
|
|
66
|
+
hide: `${CSI2}?25l`,
|
|
67
|
+
show: `${CSI2}?25h`,
|
|
68
|
+
save: `${ESC2}7`,
|
|
69
|
+
restore: `${ESC2}8`
|
|
70
|
+
};
|
|
71
|
+
var scroll = {
|
|
72
|
+
up: (count = 1) => `${CSI2}S`.repeat(count),
|
|
73
|
+
down: (count = 1) => `${CSI2}T`.repeat(count)
|
|
74
|
+
};
|
|
75
|
+
var erase = {
|
|
76
|
+
screen: `${CSI2}2J`,
|
|
77
|
+
up: (count = 1) => `${CSI2}1J`.repeat(count),
|
|
78
|
+
down: (count = 1) => `${CSI2}J`.repeat(count),
|
|
79
|
+
line: `${CSI2}2K`,
|
|
80
|
+
lineEnd: `${CSI2}K`,
|
|
81
|
+
lineStart: `${CSI2}1K`,
|
|
82
|
+
lines(count) {
|
|
83
|
+
let clear = "";
|
|
84
|
+
for (let i = 0;i < count; i++)
|
|
85
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
86
|
+
if (count)
|
|
87
|
+
clear += cursor.left;
|
|
88
|
+
return clear;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// src/index.ts
|
|
95
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
|
|
96
|
+
import { homedir as homedir2 } from "node:os";
|
|
97
|
+
import { resolve as resolve4, join as join7 } from "node:path";
|
|
98
|
+
import { fileURLToPath } from "node:url";
|
|
99
|
+
|
|
100
|
+
// src/detect.ts
|
|
101
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
102
|
+
import { join } from "node:path";
|
|
103
|
+
var rules = [
|
|
104
|
+
["Next.js", ["next"], ["next.config.js", "next.config.mjs"], [{ name: "code-review-and-quality", reason: "Next.js projects benefit from consistent review and quality checks." }]],
|
|
105
|
+
["React", ["react", "react-dom"], ["vite.config.ts", "vite.config.js"], [{ name: "typescript-patterns", reason: "Typed UI projects benefit from reusable TypeScript patterns." }]],
|
|
106
|
+
["TypeScript", ["typescript"], ["tsconfig.json"], [{ name: "typescript-patterns", reason: "A TypeScript configuration was detected." }]],
|
|
107
|
+
["Git", [], [".gitignore"], [{ name: "git-worktree", reason: "Git projects can use safer isolated worktrees." }]]
|
|
108
|
+
];
|
|
109
|
+
function detectStack(projectDir, catalog) {
|
|
110
|
+
let packages = {};
|
|
111
|
+
try {
|
|
112
|
+
const pkg = JSON.parse(readFileSync(join(projectDir, "package.json"), "utf8"));
|
|
113
|
+
packages = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
114
|
+
} catch {}
|
|
115
|
+
const stack = [];
|
|
116
|
+
const recommendations = [];
|
|
117
|
+
for (const [name, deps, files, suggested] of rules)
|
|
118
|
+
if (deps.some((dep) => (dep in packages)) || files.some((file) => existsSync(join(projectDir, file)))) {
|
|
119
|
+
stack.push(name);
|
|
120
|
+
recommendations.push(...suggested);
|
|
121
|
+
}
|
|
122
|
+
const available = catalog ? new Set(catalog.map((s) => s.name)) : undefined;
|
|
123
|
+
const unique = recommendations.filter((r, i, all) => (!available || available.has(r.name)) && all.findIndex((x) => x.name === r.name) === i);
|
|
124
|
+
return { stack, recommendations: unique, skills: unique.map((r) => r.name) };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/install.ts
|
|
128
|
+
import { createHash } from "node:crypto";
|
|
129
|
+
import { cpSync, existsSync as existsSync2, lstatSync, mkdirSync, readdirSync, readFileSync as readFileSync2, realpathSync, rmSync } from "node:fs";
|
|
130
|
+
import { join as join3, relative, resolve as resolve2, sep } from "node:path";
|
|
131
|
+
|
|
132
|
+
// src/agents.ts
|
|
133
|
+
import { isAbsolute, join as join2, resolve } from "node:path";
|
|
134
|
+
function safeSkillName(name) {
|
|
135
|
+
return name.length > 0 && name !== "." && name !== ".." && !isAbsolute(name) && !name.includes("/") && !name.includes("\\");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/install.ts
|
|
139
|
+
function assertNoSymlinks(path) {
|
|
140
|
+
const absolute = resolve2(path);
|
|
141
|
+
let current = absolute.startsWith(sep) ? sep : "";
|
|
142
|
+
for (const part of absolute.slice(current.length).split(sep).filter(Boolean)) {
|
|
143
|
+
current = join3(current, part);
|
|
144
|
+
if (lstatSync(current, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
145
|
+
throw new Error("target path cannot contain symlinks");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function assertTarget(dir) {
|
|
149
|
+
const target = resolve2(dir);
|
|
150
|
+
assertNoSymlinks(target);
|
|
151
|
+
mkdirSync(target, { recursive: true });
|
|
152
|
+
if (realpathSync(target) !== target)
|
|
153
|
+
throw new Error("target path cannot contain symlinks");
|
|
154
|
+
return target;
|
|
155
|
+
}
|
|
156
|
+
function assertCatalog(dir, name) {
|
|
157
|
+
if (!lstatSync(dir, { throwIfNoEntry: false })?.isDirectory())
|
|
158
|
+
throw new Error(`invalid catalog entry: ${name}`);
|
|
159
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
160
|
+
if (e.isSymbolicLink())
|
|
161
|
+
throw new Error(`catalog skill cannot contain symlinks: ${name}`);
|
|
162
|
+
if (e.isDirectory())
|
|
163
|
+
assertCatalog(join3(dir, e.name), name);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function skillHash(dir) {
|
|
167
|
+
const hash = createHash("sha256");
|
|
168
|
+
const walk = (current) => {
|
|
169
|
+
for (const e of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
170
|
+
const path = join3(current, e.name);
|
|
171
|
+
if (e.isDirectory())
|
|
172
|
+
walk(path);
|
|
173
|
+
else {
|
|
174
|
+
hash.update(relative(dir, path));
|
|
175
|
+
hash.update(readFileSync2(path));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
walk(dir);
|
|
180
|
+
return `sha256:${hash.digest("hex")}`;
|
|
181
|
+
}
|
|
182
|
+
function findConflicts(targetDir, names) {
|
|
183
|
+
return names.filter((name) => existsSync2(join3(targetDir, name)));
|
|
184
|
+
}
|
|
185
|
+
function installSkills(opts) {
|
|
186
|
+
const result = { installed: [], overwritten: [], skipped: [], failed: [] };
|
|
187
|
+
const target = assertTarget(opts.targetDir);
|
|
188
|
+
for (const name of opts.names) {
|
|
189
|
+
opts.onStatus?.(name);
|
|
190
|
+
try {
|
|
191
|
+
if (!safeSkillName(name))
|
|
192
|
+
throw new Error(`unsafe skill name: ${name}`);
|
|
193
|
+
const src = join3(opts.catalogDir, name);
|
|
194
|
+
if (!lstatSync(src, { throwIfNoEntry: false })?.isDirectory())
|
|
195
|
+
throw new Error(`not found in catalog: ${name}`);
|
|
196
|
+
assertCatalog(src, name);
|
|
197
|
+
const dest = resolve2(target, name);
|
|
198
|
+
if (!dest.startsWith(target + sep))
|
|
199
|
+
throw new Error("skill destination escapes target directory");
|
|
200
|
+
if (lstatSync(dest, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
201
|
+
throw new Error("skill destination cannot be a symlink");
|
|
202
|
+
const exists = existsSync2(dest);
|
|
203
|
+
if (exists && !lstatSync(dest).isDirectory())
|
|
204
|
+
throw new Error("skill destination must be a directory");
|
|
205
|
+
if (exists && !opts.overwrite) {
|
|
206
|
+
result.skipped.push(name);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (exists)
|
|
210
|
+
rmSync(dest, { recursive: true, force: true });
|
|
211
|
+
cpSync(src, dest, { recursive: true });
|
|
212
|
+
(exists ? result.overwritten : result.installed).push(name);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
result.failed.push({ name, error: error instanceof Error ? error.message : String(error) });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/registry.ts
|
|
221
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
222
|
+
import { join as join4 } from "node:path";
|
|
223
|
+
function frontmatter(raw) {
|
|
224
|
+
const body = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw)?.[1] ?? "";
|
|
225
|
+
const value = (key) => body.match(new RegExp(`^${key}:\\s*(.+)$`, "m"))?.[1].trim().replace(/^['"]|['"]$/g, "");
|
|
226
|
+
const description = body.match(/^description:\s*>[+-]?\s*([\s\S]*?)(?=^\S|$)/m)?.[1]?.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ");
|
|
227
|
+
return { name: value("name"), description: description ?? value("description") };
|
|
228
|
+
}
|
|
229
|
+
function categoryMap(catalogDir) {
|
|
230
|
+
try {
|
|
231
|
+
const raw = JSON.parse(readFileSync3(join4(catalogDir, "..", "catalog.json"), "utf8"));
|
|
232
|
+
const map = new Map;
|
|
233
|
+
for (const [category, names] of Object.entries(raw.categories ?? {}))
|
|
234
|
+
for (const name of names)
|
|
235
|
+
map.set(name, category);
|
|
236
|
+
return map;
|
|
237
|
+
} catch {
|
|
238
|
+
return new Map;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function readRegistry(catalogDir) {
|
|
242
|
+
if (!existsSync3(catalogDir))
|
|
243
|
+
return [];
|
|
244
|
+
const categories = categoryMap(catalogDir);
|
|
245
|
+
return readdirSync2(catalogDir, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync3(join4(catalogDir, e.name, "SKILL.md"))).map((e) => {
|
|
246
|
+
const dir = join4(catalogDir, e.name);
|
|
247
|
+
let meta = {};
|
|
248
|
+
try {
|
|
249
|
+
meta = JSON.parse(readFileSync3(join4(dir, ".skill-meta.json"), "utf8"));
|
|
250
|
+
} catch {}
|
|
251
|
+
const front = frontmatter(readFileSync3(join4(dir, "SKILL.md"), "utf8"));
|
|
252
|
+
return { name: meta.name ?? front.name ?? e.name, description: meta.description ?? front.description ?? "", version: meta.version ?? "0.1.0", dir, category: categories.get(e.name) ?? "Other" };
|
|
253
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
254
|
+
}
|
|
255
|
+
var listSkills = readRegistry;
|
|
256
|
+
function categories(registry) {
|
|
257
|
+
const grouped = new Map;
|
|
258
|
+
for (const skill of registry) {
|
|
259
|
+
const category = skill.category ?? "Other";
|
|
260
|
+
grouped.set(category, [...grouped.get(category) ?? [], skill]);
|
|
261
|
+
}
|
|
262
|
+
return [...grouped].sort(([a], [b]) => a.localeCompare(b)).map(([name, skills]) => ({ name, skills }));
|
|
263
|
+
}
|
|
264
|
+
function findSkill(catalogDir, name) {
|
|
265
|
+
return readRegistry(catalogDir).find((skill) => skill.name === name);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/lockfile.ts
|
|
269
|
+
import { existsSync as existsSync4, lstatSync as lstatSync2, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
270
|
+
import { join as join5 } from "node:path";
|
|
271
|
+
function lockPath(projectDir) {
|
|
272
|
+
return join5(projectDir, ".grimoire-lock.json");
|
|
273
|
+
}
|
|
274
|
+
function assertLockfilePath(projectDir) {
|
|
275
|
+
const path = lockPath(projectDir);
|
|
276
|
+
if (lstatSync2(path, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
277
|
+
throw new Error("lockfile cannot be a symlink");
|
|
278
|
+
return path;
|
|
279
|
+
}
|
|
280
|
+
function readLockfile(projectDir) {
|
|
281
|
+
const path = assertLockfilePath(projectDir);
|
|
282
|
+
try {
|
|
283
|
+
const lock = JSON.parse(readFileSync4(path, "utf8"));
|
|
284
|
+
if (lock.version === 1 && lock.skills)
|
|
285
|
+
return lock;
|
|
286
|
+
} catch {}
|
|
287
|
+
return { version: 1, generated: new Date().toISOString(), registry: "runecraftai/grimoire", skills: {} };
|
|
288
|
+
}
|
|
289
|
+
function writeLockfile(projectDir, lock) {
|
|
290
|
+
writeFileSync(assertLockfilePath(projectDir), `${JSON.stringify(lock, null, 2)}
|
|
291
|
+
`);
|
|
292
|
+
}
|
|
293
|
+
function updateLock(lock, name, entry) {
|
|
294
|
+
const existing = lock.skills[name];
|
|
295
|
+
lock.generated = new Date().toISOString();
|
|
296
|
+
lock.skills[name] = existing ? { ...entry, agents: [...new Set([...existing.agents, ...entry.agents])] } : entry;
|
|
297
|
+
return lock;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// src/targets.ts
|
|
301
|
+
import { homedir } from "node:os";
|
|
302
|
+
import { join as join6 } from "node:path";
|
|
303
|
+
var TARGETS = [
|
|
304
|
+
{ id: "pi", label: "pi", description: "pi coding agent — ~/.pi/agent/skills" },
|
|
305
|
+
{ id: "claude", label: "Claude Code", description: "~/.claude/skills" },
|
|
306
|
+
{ id: "codex", label: "Codex CLI", description: "~/.codex/skills" },
|
|
307
|
+
{ id: "opencode", label: "OpenCode", description: "~/.config/opencode/skills" }
|
|
308
|
+
];
|
|
309
|
+
function isTargetId(value) {
|
|
310
|
+
return TARGETS.some((t) => t.id === value);
|
|
311
|
+
}
|
|
312
|
+
function resolveSkillsDir(id, ctx = {}) {
|
|
313
|
+
const home = ctx.home ?? homedir();
|
|
314
|
+
const env = ctx.env ?? process.env;
|
|
315
|
+
if (ctx.global === false) {
|
|
316
|
+
const projectPaths = { pi: ".pi/skills", claude: ".claude/skills", codex: ".codex/skills", opencode: ".opencode/skills" };
|
|
317
|
+
return join6(ctx.projectDir ?? process.cwd(), projectPaths[id]);
|
|
318
|
+
}
|
|
319
|
+
switch (id) {
|
|
320
|
+
case "pi":
|
|
321
|
+
return join6(env.PI_HOME ?? join6(home, ".pi"), "agent", "skills");
|
|
322
|
+
case "claude":
|
|
323
|
+
return join6(env.CLAUDE_CONFIG_DIR ?? join6(home, ".claude"), "skills");
|
|
324
|
+
case "codex":
|
|
325
|
+
return join6(env.CODEX_HOME ?? join6(home, ".codex"), "skills");
|
|
326
|
+
case "opencode": {
|
|
327
|
+
const xdg = env.XDG_CONFIG_HOME ?? join6(home, ".config");
|
|
328
|
+
return join6(xdg, "opencode", "skills");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function displayPath(path, home = homedir()) {
|
|
333
|
+
const root = home.replace(/\/+$/, "");
|
|
334
|
+
if (path === root)
|
|
335
|
+
return "~";
|
|
336
|
+
if (path.startsWith(root + "/"))
|
|
337
|
+
return "~" + path.slice(root.length);
|
|
338
|
+
return path;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ../../node_modules/.bun/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
342
|
+
import { styleText } from "node:util";
|
|
343
|
+
import { stdout, stdin } from "node:process";
|
|
344
|
+
import * as l from "node:readline";
|
|
345
|
+
import l__default from "node:readline";
|
|
346
|
+
|
|
347
|
+
// ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
348
|
+
var getCodePointsLength = (() => {
|
|
349
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
350
|
+
return (input) => {
|
|
351
|
+
let surrogatePairsNr = 0;
|
|
352
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
353
|
+
while (SURROGATE_PAIR_RE.test(input)) {
|
|
354
|
+
surrogatePairsNr += 1;
|
|
355
|
+
}
|
|
356
|
+
return input.length - surrogatePairsNr;
|
|
357
|
+
};
|
|
358
|
+
})();
|
|
359
|
+
var isFullWidth = (x) => {
|
|
360
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
361
|
+
};
|
|
362
|
+
var isWideNotCJKTNotEmoji = (x) => {
|
|
363
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
367
|
+
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
368
|
+
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
369
|
+
var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
370
|
+
var TAB_RE = /\t{1,1000}/y;
|
|
371
|
+
var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
|
|
372
|
+
var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
373
|
+
var MODIFIER_RE = /\p{M}+/gu;
|
|
374
|
+
var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
375
|
+
var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
376
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
377
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
378
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
379
|
+
const ANSI_WIDTH = 0;
|
|
380
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
381
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
382
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
383
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
384
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
385
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
386
|
+
const PARSE_BLOCKS = [
|
|
387
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
388
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
389
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
390
|
+
[TAB_RE, TAB_WIDTH],
|
|
391
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
392
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
393
|
+
];
|
|
394
|
+
let indexPrev = 0;
|
|
395
|
+
let index = 0;
|
|
396
|
+
let length = input.length;
|
|
397
|
+
let lengthExtra = 0;
|
|
398
|
+
let truncationEnabled = false;
|
|
399
|
+
let truncationIndex = length;
|
|
400
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
401
|
+
let unmatchedStart = 0;
|
|
402
|
+
let unmatchedEnd = 0;
|
|
403
|
+
let width = 0;
|
|
404
|
+
let widthExtra = 0;
|
|
405
|
+
outer:
|
|
406
|
+
while (true) {
|
|
407
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
408
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
409
|
+
lengthExtra = 0;
|
|
410
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
411
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
412
|
+
if (isFullWidth(codePoint)) {
|
|
413
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
414
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
415
|
+
widthExtra = WIDE_WIDTH;
|
|
416
|
+
} else {
|
|
417
|
+
widthExtra = REGULAR_WIDTH;
|
|
418
|
+
}
|
|
419
|
+
if (width + widthExtra > truncationLimit) {
|
|
420
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
421
|
+
}
|
|
422
|
+
if (width + widthExtra > LIMIT) {
|
|
423
|
+
truncationEnabled = true;
|
|
424
|
+
break outer;
|
|
425
|
+
}
|
|
426
|
+
lengthExtra += char.length;
|
|
427
|
+
width += widthExtra;
|
|
428
|
+
}
|
|
429
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
430
|
+
}
|
|
431
|
+
if (index >= length) {
|
|
432
|
+
break outer;
|
|
433
|
+
}
|
|
434
|
+
for (let i = 0, l = PARSE_BLOCKS.length;i < l; i++) {
|
|
435
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
436
|
+
BLOCK_RE.lastIndex = index;
|
|
437
|
+
if (BLOCK_RE.test(input)) {
|
|
438
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
439
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
440
|
+
if (width + widthExtra > truncationLimit) {
|
|
441
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
442
|
+
}
|
|
443
|
+
if (width + widthExtra > LIMIT) {
|
|
444
|
+
truncationEnabled = true;
|
|
445
|
+
break outer;
|
|
446
|
+
}
|
|
447
|
+
width += widthExtra;
|
|
448
|
+
unmatchedStart = indexPrev;
|
|
449
|
+
unmatchedEnd = index;
|
|
450
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
451
|
+
continue outer;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
index += 1;
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
458
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
459
|
+
truncated: truncationEnabled,
|
|
460
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
var dist_default = getStringTruncatedWidth;
|
|
464
|
+
|
|
465
|
+
// ../../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
466
|
+
var NO_TRUNCATION2 = {
|
|
467
|
+
limit: Infinity,
|
|
468
|
+
ellipsis: "",
|
|
469
|
+
ellipsisWidth: 0
|
|
470
|
+
};
|
|
471
|
+
var fastStringWidth = (input, options = {}) => {
|
|
472
|
+
return dist_default(input, NO_TRUNCATION2, options).width;
|
|
473
|
+
};
|
|
474
|
+
var dist_default2 = fastStringWidth;
|
|
475
|
+
|
|
476
|
+
// ../../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
477
|
+
var ESC = "\x1B";
|
|
478
|
+
var CSI = "";
|
|
479
|
+
var END_CODE = 39;
|
|
480
|
+
var ANSI_ESCAPE_BELL = "\x07";
|
|
481
|
+
var ANSI_CSI = "[";
|
|
482
|
+
var ANSI_OSC = "]";
|
|
483
|
+
var ANSI_SGR_TERMINATOR = "m";
|
|
484
|
+
var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
485
|
+
var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
486
|
+
var getClosingCode = (openingCode) => {
|
|
487
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
488
|
+
return 39;
|
|
489
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
490
|
+
return 39;
|
|
491
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
492
|
+
return 49;
|
|
493
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
494
|
+
return 49;
|
|
495
|
+
if (openingCode === 1 || openingCode === 2)
|
|
496
|
+
return 22;
|
|
497
|
+
if (openingCode === 3)
|
|
498
|
+
return 23;
|
|
499
|
+
if (openingCode === 4)
|
|
500
|
+
return 24;
|
|
501
|
+
if (openingCode === 7)
|
|
502
|
+
return 27;
|
|
503
|
+
if (openingCode === 8)
|
|
504
|
+
return 28;
|
|
505
|
+
if (openingCode === 9)
|
|
506
|
+
return 29;
|
|
507
|
+
if (openingCode === 0)
|
|
508
|
+
return 0;
|
|
509
|
+
return;
|
|
510
|
+
};
|
|
511
|
+
var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
512
|
+
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
513
|
+
var wrapWord = (rows, word, columns) => {
|
|
514
|
+
const characters = word[Symbol.iterator]();
|
|
515
|
+
let isInsideEscape = false;
|
|
516
|
+
let isInsideLinkEscape = false;
|
|
517
|
+
let lastRow = rows.at(-1);
|
|
518
|
+
let visible = lastRow === undefined ? 0 : dist_default2(lastRow);
|
|
519
|
+
let currentCharacter = characters.next();
|
|
520
|
+
let nextCharacter = characters.next();
|
|
521
|
+
let rawCharacterIndex = 0;
|
|
522
|
+
while (!currentCharacter.done) {
|
|
523
|
+
const character = currentCharacter.value;
|
|
524
|
+
const characterLength = dist_default2(character);
|
|
525
|
+
if (visible + characterLength <= columns) {
|
|
526
|
+
rows[rows.length - 1] += character;
|
|
527
|
+
} else {
|
|
528
|
+
rows.push(character);
|
|
529
|
+
visible = 0;
|
|
530
|
+
}
|
|
531
|
+
if (character === ESC || character === CSI) {
|
|
532
|
+
isInsideEscape = true;
|
|
533
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
534
|
+
}
|
|
535
|
+
if (isInsideEscape) {
|
|
536
|
+
if (isInsideLinkEscape) {
|
|
537
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
538
|
+
isInsideEscape = false;
|
|
539
|
+
isInsideLinkEscape = false;
|
|
540
|
+
}
|
|
541
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
542
|
+
isInsideEscape = false;
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
visible += characterLength;
|
|
546
|
+
if (visible === columns && !nextCharacter.done) {
|
|
547
|
+
rows.push("");
|
|
548
|
+
visible = 0;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
currentCharacter = nextCharacter;
|
|
552
|
+
nextCharacter = characters.next();
|
|
553
|
+
rawCharacterIndex += character.length;
|
|
554
|
+
}
|
|
555
|
+
lastRow = rows.at(-1);
|
|
556
|
+
if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
|
|
557
|
+
rows[rows.length - 2] += rows.pop();
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
var stringVisibleTrimSpacesRight = (string) => {
|
|
561
|
+
const words = string.split(" ");
|
|
562
|
+
let last = words.length;
|
|
563
|
+
while (last) {
|
|
564
|
+
if (dist_default2(words[last - 1])) {
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
last--;
|
|
568
|
+
}
|
|
569
|
+
if (last === words.length) {
|
|
570
|
+
return string;
|
|
571
|
+
}
|
|
572
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
573
|
+
};
|
|
574
|
+
var exec = (string, columns, options = {}) => {
|
|
575
|
+
if (options.trim !== false && string.trim() === "") {
|
|
576
|
+
return "";
|
|
577
|
+
}
|
|
578
|
+
let returnValue = "";
|
|
579
|
+
let escapeCode;
|
|
580
|
+
let escapeUrl;
|
|
581
|
+
const words = string.split(" ");
|
|
582
|
+
let rows = [""];
|
|
583
|
+
let rowLength = 0;
|
|
584
|
+
for (let index = 0;index < words.length; index++) {
|
|
585
|
+
const word = words[index];
|
|
586
|
+
if (options.trim !== false) {
|
|
587
|
+
const row = rows.at(-1) ?? "";
|
|
588
|
+
const trimmed = row.trimStart();
|
|
589
|
+
if (row.length !== trimmed.length) {
|
|
590
|
+
rows[rows.length - 1] = trimmed;
|
|
591
|
+
rowLength = dist_default2(trimmed);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (index !== 0) {
|
|
595
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
596
|
+
rows.push("");
|
|
597
|
+
rowLength = 0;
|
|
598
|
+
}
|
|
599
|
+
if (rowLength || options.trim === false) {
|
|
600
|
+
rows[rows.length - 1] += " ";
|
|
601
|
+
rowLength++;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
const wordLength = dist_default2(word);
|
|
605
|
+
if (options.hard && wordLength > columns) {
|
|
606
|
+
const remainingColumns = columns - rowLength;
|
|
607
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
608
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
609
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
610
|
+
rows.push("");
|
|
611
|
+
}
|
|
612
|
+
wrapWord(rows, word, columns);
|
|
613
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
617
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
618
|
+
wrapWord(rows, word, columns);
|
|
619
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
rows.push("");
|
|
623
|
+
rowLength = 0;
|
|
624
|
+
}
|
|
625
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
626
|
+
wrapWord(rows, word, columns);
|
|
627
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
rows[rows.length - 1] += word;
|
|
631
|
+
rowLength += wordLength;
|
|
632
|
+
}
|
|
633
|
+
if (options.trim !== false) {
|
|
634
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
635
|
+
}
|
|
636
|
+
const preString = rows.join(`
|
|
637
|
+
`);
|
|
638
|
+
let inSurrogate = false;
|
|
639
|
+
for (let i = 0;i < preString.length; i++) {
|
|
640
|
+
const character = preString[i];
|
|
641
|
+
returnValue += character;
|
|
642
|
+
if (!inSurrogate) {
|
|
643
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
644
|
+
if (inSurrogate) {
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
} else {
|
|
648
|
+
inSurrogate = false;
|
|
649
|
+
}
|
|
650
|
+
if (character === ESC || character === CSI) {
|
|
651
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
652
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
653
|
+
const groups = groupsResult?.groups;
|
|
654
|
+
if (groups?.code !== undefined) {
|
|
655
|
+
const code = Number.parseFloat(groups.code);
|
|
656
|
+
escapeCode = code === END_CODE ? undefined : code;
|
|
657
|
+
} else if (groups?.uri !== undefined) {
|
|
658
|
+
escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (preString[i + 1] === `
|
|
662
|
+
`) {
|
|
663
|
+
if (escapeUrl) {
|
|
664
|
+
returnValue += wrapAnsiHyperlink("");
|
|
665
|
+
}
|
|
666
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
|
|
667
|
+
if (escapeCode && closingCode) {
|
|
668
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
669
|
+
}
|
|
670
|
+
} else if (character === `
|
|
671
|
+
`) {
|
|
672
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
673
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
674
|
+
}
|
|
675
|
+
if (escapeUrl) {
|
|
676
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return returnValue;
|
|
681
|
+
};
|
|
682
|
+
var CRLF_OR_LF = /\r?\n/;
|
|
683
|
+
function wrapAnsi(string, columns, options) {
|
|
684
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join(`
|
|
685
|
+
`);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// ../../node_modules/.bun/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
689
|
+
var import_sisteransi = __toESM(require_src(), 1);
|
|
690
|
+
import { ReadStream } from "node:tty";
|
|
691
|
+
function findCursor(s, o, l2) {
|
|
692
|
+
if (!l2.some((r) => !r.disabled))
|
|
693
|
+
return s;
|
|
694
|
+
const t = s + o, n = Math.max(l2.length - 1, 0), e = t < 0 ? n : t > n ? 0 : t;
|
|
695
|
+
return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
|
|
696
|
+
}
|
|
697
|
+
var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
698
|
+
var t = [
|
|
699
|
+
"January",
|
|
700
|
+
"February",
|
|
701
|
+
"March",
|
|
702
|
+
"April",
|
|
703
|
+
"May",
|
|
704
|
+
"June",
|
|
705
|
+
"July",
|
|
706
|
+
"August",
|
|
707
|
+
"September",
|
|
708
|
+
"October",
|
|
709
|
+
"November",
|
|
710
|
+
"December"
|
|
711
|
+
];
|
|
712
|
+
var settings = {
|
|
713
|
+
actions: new Set(a$1),
|
|
714
|
+
aliases: /* @__PURE__ */ new Map([
|
|
715
|
+
["k", "up"],
|
|
716
|
+
["j", "down"],
|
|
717
|
+
["h", "left"],
|
|
718
|
+
["l", "right"],
|
|
719
|
+
["\x03", "cancel"],
|
|
720
|
+
["escape", "cancel"]
|
|
721
|
+
]),
|
|
722
|
+
messages: {
|
|
723
|
+
cancel: "Canceled",
|
|
724
|
+
error: "Something went wrong"
|
|
725
|
+
},
|
|
726
|
+
withGuide: true,
|
|
727
|
+
date: {
|
|
728
|
+
monthNames: [...t],
|
|
729
|
+
messages: {
|
|
730
|
+
required: "Please enter a valid date",
|
|
731
|
+
invalidMonth: "There are only 12 months in a year",
|
|
732
|
+
invalidDay: (n, e) => `There are only ${n} days in ${e}`,
|
|
733
|
+
afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
|
|
734
|
+
beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
function isActionKey(n, e) {
|
|
739
|
+
if (typeof n == "string")
|
|
740
|
+
return settings.aliases.get(n) === e;
|
|
741
|
+
for (const s of n)
|
|
742
|
+
if (s !== undefined && isActionKey(s, e))
|
|
743
|
+
return true;
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
function diffLines(i, s) {
|
|
747
|
+
if (i === s)
|
|
748
|
+
return;
|
|
749
|
+
const e = i.split(`
|
|
750
|
+
`), t2 = s.split(`
|
|
751
|
+
`), r = Math.max(e.length, t2.length), f = [];
|
|
752
|
+
for (let n = 0;n < r; n++)
|
|
753
|
+
e[n] !== t2[n] && f.push(n);
|
|
754
|
+
return {
|
|
755
|
+
lines: f,
|
|
756
|
+
numLinesBefore: e.length,
|
|
757
|
+
numLinesAfter: t2.length,
|
|
758
|
+
numLines: r
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
var R = globalThis.process.platform.startsWith("win");
|
|
762
|
+
var CANCEL_SYMBOL = Symbol("clack:cancel");
|
|
763
|
+
function isCancel(e) {
|
|
764
|
+
return e === CANCEL_SYMBOL;
|
|
765
|
+
}
|
|
766
|
+
function setRawMode(e, r) {
|
|
767
|
+
const o = e;
|
|
768
|
+
o.isTTY && o.setRawMode(r);
|
|
769
|
+
}
|
|
770
|
+
function block({
|
|
771
|
+
input: e = stdin,
|
|
772
|
+
output: r = stdout,
|
|
773
|
+
overwrite: o = true,
|
|
774
|
+
hideCursor: t2 = true
|
|
775
|
+
} = {}) {
|
|
776
|
+
const s = l.createInterface({
|
|
777
|
+
input: e,
|
|
778
|
+
output: r,
|
|
779
|
+
prompt: "",
|
|
780
|
+
tabSize: 1
|
|
781
|
+
});
|
|
782
|
+
l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
|
|
783
|
+
const n = (f, { name: a, sequence: p }) => {
|
|
784
|
+
const c = String(f);
|
|
785
|
+
if (isActionKey([c, a, p], "cancel")) {
|
|
786
|
+
t2 && r.write(import_sisteransi.cursor.show), process.exit(0);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (!o)
|
|
790
|
+
return;
|
|
791
|
+
const i = a === "return" ? 0 : -1, m = a === "return" ? -1 : 0;
|
|
792
|
+
l.moveCursor(r, i, m, () => {
|
|
793
|
+
l.clearLine(r, 1, () => {
|
|
794
|
+
e.once("keypress", n);
|
|
795
|
+
});
|
|
796
|
+
});
|
|
797
|
+
};
|
|
798
|
+
return t2 && r.write(import_sisteransi.cursor.hide), e.once("keypress", n), () => {
|
|
799
|
+
e.off("keypress", n), t2 && r.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
var getColumns = (e) => ("columns" in e) && typeof e.columns == "number" ? e.columns : 80;
|
|
803
|
+
var getRows = (e) => ("rows" in e) && typeof e.rows == "number" ? e.rows : 20;
|
|
804
|
+
function wrapTextWithPrefix(e, r, o, t2 = o, s = o, n) {
|
|
805
|
+
const f = getColumns(e ?? stdout);
|
|
806
|
+
return wrapAnsi(r, f - o.length, {
|
|
807
|
+
hard: true,
|
|
808
|
+
trim: false
|
|
809
|
+
}).split(`
|
|
810
|
+
`).map((c, i, m) => {
|
|
811
|
+
const d = n ? n(c, i) : c;
|
|
812
|
+
return i === 0 ? `${t2}${d}` : i === m.length - 1 ? `${s}${d}` : `${o}${d}`;
|
|
813
|
+
}).join(`
|
|
814
|
+
`);
|
|
815
|
+
}
|
|
816
|
+
function runValidation(e, n) {
|
|
817
|
+
if ("~standard" in e) {
|
|
818
|
+
const a = e["~standard"].validate(n);
|
|
819
|
+
if (a instanceof Promise)
|
|
820
|
+
throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
|
|
821
|
+
return a.issues?.at(0)?.message;
|
|
822
|
+
}
|
|
823
|
+
return e(n);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
class V {
|
|
827
|
+
input;
|
|
828
|
+
output;
|
|
829
|
+
_abortSignal;
|
|
830
|
+
rl;
|
|
831
|
+
opts;
|
|
832
|
+
_render;
|
|
833
|
+
_track = false;
|
|
834
|
+
_prevFrame = "";
|
|
835
|
+
_subscribers = /* @__PURE__ */ new Map;
|
|
836
|
+
_cursor = 0;
|
|
837
|
+
state = "initial";
|
|
838
|
+
error = "";
|
|
839
|
+
value;
|
|
840
|
+
userInput = "";
|
|
841
|
+
constructor(t2, e = true) {
|
|
842
|
+
const { input: i = stdin, output: n = stdout, render: s, signal: r, ...o } = t2;
|
|
843
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r, this.input = i, this.output = n;
|
|
844
|
+
}
|
|
845
|
+
unsubscribe() {
|
|
846
|
+
this._subscribers.clear();
|
|
847
|
+
}
|
|
848
|
+
setSubscriber(t2, e) {
|
|
849
|
+
const i = this._subscribers.get(t2) ?? [];
|
|
850
|
+
i.push(e), this._subscribers.set(t2, i);
|
|
851
|
+
}
|
|
852
|
+
on(t2, e) {
|
|
853
|
+
this.setSubscriber(t2, { cb: e });
|
|
854
|
+
}
|
|
855
|
+
once(t2, e) {
|
|
856
|
+
this.setSubscriber(t2, { cb: e, once: true });
|
|
857
|
+
}
|
|
858
|
+
emit(t2, ...e) {
|
|
859
|
+
const i = this._subscribers.get(t2) ?? [], n = [];
|
|
860
|
+
for (const s of i)
|
|
861
|
+
s.cb(...e), s.once && n.push(() => i.splice(i.indexOf(s), 1));
|
|
862
|
+
for (const s of n)
|
|
863
|
+
s();
|
|
864
|
+
}
|
|
865
|
+
prompt() {
|
|
866
|
+
return new Promise((t2) => {
|
|
867
|
+
if (this._abortSignal) {
|
|
868
|
+
if (this._abortSignal.aborted)
|
|
869
|
+
return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
|
|
870
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
871
|
+
this.state = "cancel", this.close();
|
|
872
|
+
}, { once: true });
|
|
873
|
+
}
|
|
874
|
+
this.rl = l__default.createInterface({
|
|
875
|
+
input: this.input,
|
|
876
|
+
tabSize: 2,
|
|
877
|
+
prompt: "",
|
|
878
|
+
escapeCodeTimeout: 50,
|
|
879
|
+
terminal: true
|
|
880
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== undefined && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
881
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
|
|
882
|
+
}), this.once("cancel", () => {
|
|
883
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
|
|
884
|
+
});
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
_isActionKey(t2, e) {
|
|
888
|
+
return t2 === "\t";
|
|
889
|
+
}
|
|
890
|
+
_shouldSubmit(t2, e) {
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
_setValue(t2) {
|
|
894
|
+
this.value = t2, this.emit("value", this.value);
|
|
895
|
+
}
|
|
896
|
+
_setUserInput(t2, e) {
|
|
897
|
+
this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
898
|
+
}
|
|
899
|
+
_clearUserInput() {
|
|
900
|
+
this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
|
|
901
|
+
}
|
|
902
|
+
onKeypress(t2, e) {
|
|
903
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
|
|
904
|
+
if (this.opts.validate) {
|
|
905
|
+
const i = runValidation(this.opts.validate, this.value);
|
|
906
|
+
i && (this.error = i instanceof Error ? i.message : i, this.state = "error", this.rl?.write(this.userInput));
|
|
907
|
+
}
|
|
908
|
+
this.state !== "error" && (this.state = "submit");
|
|
909
|
+
}
|
|
910
|
+
isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
911
|
+
}
|
|
912
|
+
close() {
|
|
913
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
914
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
915
|
+
}
|
|
916
|
+
restoreCursor() {
|
|
917
|
+
const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
|
|
918
|
+
`).length - 1;
|
|
919
|
+
this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
|
|
920
|
+
}
|
|
921
|
+
render() {
|
|
922
|
+
const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
923
|
+
hard: true,
|
|
924
|
+
trim: false
|
|
925
|
+
});
|
|
926
|
+
if (t2 !== this._prevFrame) {
|
|
927
|
+
if (this.state === "initial")
|
|
928
|
+
this.output.write(import_sisteransi.cursor.hide);
|
|
929
|
+
else {
|
|
930
|
+
const e = diffLines(this._prevFrame, t2), i = getRows(this.output);
|
|
931
|
+
if (this.restoreCursor(), e) {
|
|
932
|
+
const n = Math.max(0, e.numLinesAfter - i), s = Math.max(0, e.numLinesBefore - i);
|
|
933
|
+
let r = e.lines.find((o) => o >= n);
|
|
934
|
+
if (r === undefined) {
|
|
935
|
+
this._prevFrame = t2;
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
if (e.lines.length === 1) {
|
|
939
|
+
this.output.write(import_sisteransi.cursor.move(0, r - s)), this.output.write(import_sisteransi.erase.lines(1));
|
|
940
|
+
const o = t2.split(`
|
|
941
|
+
`);
|
|
942
|
+
this.output.write(o[r]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - r - 1));
|
|
943
|
+
return;
|
|
944
|
+
} else if (e.lines.length > 1) {
|
|
945
|
+
if (n < s)
|
|
946
|
+
r = n;
|
|
947
|
+
else {
|
|
948
|
+
const h = r - s;
|
|
949
|
+
h > 0 && this.output.write(import_sisteransi.cursor.move(0, h));
|
|
950
|
+
}
|
|
951
|
+
this.output.write(import_sisteransi.erase.down());
|
|
952
|
+
const f = t2.split(`
|
|
953
|
+
`).slice(r);
|
|
954
|
+
this.output.write(f.join(`
|
|
955
|
+
`)), this._prevFrame = t2;
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
this.output.write(import_sisteransi.erase.down());
|
|
960
|
+
}
|
|
961
|
+
this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
class a extends V {
|
|
966
|
+
options;
|
|
967
|
+
cursor = 0;
|
|
968
|
+
get _value() {
|
|
969
|
+
return this.options[this.cursor]?.value;
|
|
970
|
+
}
|
|
971
|
+
get _enabledOptions() {
|
|
972
|
+
return this.options.filter((e) => e.disabled !== true);
|
|
973
|
+
}
|
|
974
|
+
toggleAll() {
|
|
975
|
+
const e = this._enabledOptions, i = this.value !== undefined && this.value.length === e.length;
|
|
976
|
+
this.value = i ? [] : e.map((t2) => t2.value);
|
|
977
|
+
}
|
|
978
|
+
toggleInvert() {
|
|
979
|
+
const e = this.value;
|
|
980
|
+
if (!e)
|
|
981
|
+
return;
|
|
982
|
+
const i = this._enabledOptions.filter((t2) => !e.includes(t2.value));
|
|
983
|
+
this.value = i.map((t2) => t2.value);
|
|
984
|
+
}
|
|
985
|
+
toggleValue() {
|
|
986
|
+
this.value === undefined && (this.value = []);
|
|
987
|
+
const e = this.value.includes(this._value);
|
|
988
|
+
this.value = e ? this.value.filter((i) => i !== this._value) : [...this.value, this._value];
|
|
989
|
+
}
|
|
990
|
+
constructor(e) {
|
|
991
|
+
super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
|
|
992
|
+
const i = Math.max(this.options.findIndex(({ value: t2 }) => t2 === e.cursorAt), 0);
|
|
993
|
+
this.cursor = this.options[i]?.disabled ? findCursor(i, 1, this.options) : i, this.on("key", (t2, l2) => {
|
|
994
|
+
l2.name === "a" && this.toggleAll(), l2.name === "i" && this.toggleInvert();
|
|
995
|
+
}), this.on("cursor", (t2) => {
|
|
996
|
+
switch (t2) {
|
|
997
|
+
case "left":
|
|
998
|
+
case "up":
|
|
999
|
+
this.cursor = findCursor(this.cursor, -1, this.options);
|
|
1000
|
+
break;
|
|
1001
|
+
case "down":
|
|
1002
|
+
case "right":
|
|
1003
|
+
this.cursor = findCursor(this.cursor, 1, this.options);
|
|
1004
|
+
break;
|
|
1005
|
+
case "space":
|
|
1006
|
+
this.toggleValue();
|
|
1007
|
+
break;
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
var n$1 = class n extends V {
|
|
1013
|
+
options;
|
|
1014
|
+
cursor = 0;
|
|
1015
|
+
get _selectedValue() {
|
|
1016
|
+
return this.options[this.cursor];
|
|
1017
|
+
}
|
|
1018
|
+
changeValue() {
|
|
1019
|
+
const e = this._selectedValue;
|
|
1020
|
+
this.value = e === undefined ? undefined : e.value;
|
|
1021
|
+
}
|
|
1022
|
+
constructor(e) {
|
|
1023
|
+
super(e, false), this.options = e.options;
|
|
1024
|
+
const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o === -1 ? 0 : o;
|
|
1025
|
+
this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
|
|
1026
|
+
switch (s) {
|
|
1027
|
+
case "left":
|
|
1028
|
+
case "up":
|
|
1029
|
+
this.cursor = findCursor(this.cursor, -1, this.options);
|
|
1030
|
+
break;
|
|
1031
|
+
case "down":
|
|
1032
|
+
case "right":
|
|
1033
|
+
this.cursor = findCursor(this.cursor, 1, this.options);
|
|
1034
|
+
break;
|
|
1035
|
+
}
|
|
1036
|
+
this.changeValue();
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
class n2 extends V {
|
|
1041
|
+
get userInputWithCursor() {
|
|
1042
|
+
if (this.state === "submit")
|
|
1043
|
+
return this.userInput;
|
|
1044
|
+
const t2 = this.userInput;
|
|
1045
|
+
if (this.cursor >= t2.length)
|
|
1046
|
+
return `${this.userInput}█`;
|
|
1047
|
+
const r = t2.slice(0, this.cursor), s = t2.slice(this.cursor, this.cursor + 1), e = t2.slice(this.cursor + 1);
|
|
1048
|
+
return `${r}${styleText("inverse", s)}${e}`;
|
|
1049
|
+
}
|
|
1050
|
+
get cursor() {
|
|
1051
|
+
return this._cursor;
|
|
1052
|
+
}
|
|
1053
|
+
constructor(t2) {
|
|
1054
|
+
super({
|
|
1055
|
+
...t2,
|
|
1056
|
+
initialUserInput: t2.initialUserInput ?? t2.initialValue
|
|
1057
|
+
}), this.on("userInput", (r) => {
|
|
1058
|
+
this._setValue(r);
|
|
1059
|
+
}), this.on("finalize", () => {
|
|
1060
|
+
this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// ../../node_modules/.bun/@clack+prompts@1.7.0/node_modules/@clack/prompts/dist/index.mjs
|
|
1066
|
+
import { styleText as styleText2, stripVTControlCharacters } from "node:util";
|
|
1067
|
+
import process$1 from "node:process";
|
|
1068
|
+
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
1069
|
+
function isUnicodeSupported() {
|
|
1070
|
+
if (process$1.platform !== "win32") {
|
|
1071
|
+
return process$1.env.TERM !== "linux";
|
|
1072
|
+
}
|
|
1073
|
+
return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
1074
|
+
}
|
|
1075
|
+
var unicode = isUnicodeSupported();
|
|
1076
|
+
var isCI = () => process.env.CI === "true";
|
|
1077
|
+
var unicodeOr = (o, e) => unicode ? o : e;
|
|
1078
|
+
var S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
1079
|
+
var S_STEP_CANCEL = unicodeOr("■", "x");
|
|
1080
|
+
var S_STEP_ERROR = unicodeOr("▲", "x");
|
|
1081
|
+
var S_STEP_SUBMIT = unicodeOr("◇", "o");
|
|
1082
|
+
var S_BAR_START = unicodeOr("┌", "T");
|
|
1083
|
+
var S_BAR = unicodeOr("│", "|");
|
|
1084
|
+
var S_BAR_END = unicodeOr("└", "—");
|
|
1085
|
+
var S_BAR_START_RIGHT = unicodeOr("┐", "T");
|
|
1086
|
+
var S_BAR_END_RIGHT = unicodeOr("┘", "—");
|
|
1087
|
+
var S_RADIO_ACTIVE = unicodeOr("●", ">");
|
|
1088
|
+
var S_RADIO_INACTIVE = unicodeOr("○", " ");
|
|
1089
|
+
var S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
|
|
1090
|
+
var S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
|
|
1091
|
+
var S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
|
|
1092
|
+
var S_PASSWORD_MASK = unicodeOr("▪", "•");
|
|
1093
|
+
var S_BAR_H = unicodeOr("─", "-");
|
|
1094
|
+
var S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
|
|
1095
|
+
var S_CONNECT_LEFT = unicodeOr("├", "+");
|
|
1096
|
+
var S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
|
|
1097
|
+
var S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
|
|
1098
|
+
var S_CORNER_TOP_LEFT = unicodeOr("╭", "+");
|
|
1099
|
+
var S_INFO = unicodeOr("●", "•");
|
|
1100
|
+
var S_SUCCESS = unicodeOr("◆", "*");
|
|
1101
|
+
var S_WARN = unicodeOr("▲", "!");
|
|
1102
|
+
var S_ERROR = unicodeOr("■", "x");
|
|
1103
|
+
var symbol = (o) => {
|
|
1104
|
+
switch (o) {
|
|
1105
|
+
case "initial":
|
|
1106
|
+
case "active":
|
|
1107
|
+
return styleText2("cyan", S_STEP_ACTIVE);
|
|
1108
|
+
case "cancel":
|
|
1109
|
+
return styleText2("red", S_STEP_CANCEL);
|
|
1110
|
+
case "error":
|
|
1111
|
+
return styleText2("yellow", S_STEP_ERROR);
|
|
1112
|
+
case "submit":
|
|
1113
|
+
return styleText2("green", S_STEP_SUBMIT);
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
var symbolBar = (o) => {
|
|
1117
|
+
switch (o) {
|
|
1118
|
+
case "initial":
|
|
1119
|
+
case "active":
|
|
1120
|
+
return styleText2("cyan", S_BAR);
|
|
1121
|
+
case "cancel":
|
|
1122
|
+
return styleText2("red", S_BAR);
|
|
1123
|
+
case "error":
|
|
1124
|
+
return styleText2("yellow", S_BAR);
|
|
1125
|
+
case "submit":
|
|
1126
|
+
return styleText2("green", S_BAR);
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
function formatInstructionFooter(o, e) {
|
|
1130
|
+
const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o.join(" • ")}`];
|
|
1131
|
+
return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
|
|
1132
|
+
}
|
|
1133
|
+
var I = (l2, e, w, p, b, C = false) => {
|
|
1134
|
+
let r2 = e, O = 0;
|
|
1135
|
+
if (C)
|
|
1136
|
+
for (let i = p - 1;i >= w; i--) {
|
|
1137
|
+
const m = l2[i];
|
|
1138
|
+
if (m && (r2 -= m.length), O++, r2 <= b)
|
|
1139
|
+
break;
|
|
1140
|
+
}
|
|
1141
|
+
else
|
|
1142
|
+
for (let i = w;i < p; i++) {
|
|
1143
|
+
const m = l2[i];
|
|
1144
|
+
if (m && (r2 -= m.length), O++, r2 <= b)
|
|
1145
|
+
break;
|
|
1146
|
+
}
|
|
1147
|
+
return { lineCount: r2, removals: O };
|
|
1148
|
+
};
|
|
1149
|
+
var limitOptions = ({
|
|
1150
|
+
cursor: l2,
|
|
1151
|
+
options: e,
|
|
1152
|
+
style: w,
|
|
1153
|
+
output: p = process.stdout,
|
|
1154
|
+
maxItems: b = Number.POSITIVE_INFINITY,
|
|
1155
|
+
columnPadding: C = 0,
|
|
1156
|
+
rowPadding: r2 = 4
|
|
1157
|
+
}) => {
|
|
1158
|
+
const i = getColumns(p) - C, m = getRows(p), M = styleText2("dim", "..."), v = Math.max(m - r2, 0), a2 = Math.max(Math.min(b, v), 5);
|
|
1159
|
+
let f = 0;
|
|
1160
|
+
l2 >= a2 - 3 && (f = Math.max(Math.min(l2 - a2 + 3, e.length - a2), 0));
|
|
1161
|
+
let d = a2 < e.length && f > 0, c = a2 < e.length && f + a2 < e.length;
|
|
1162
|
+
const W = Math.min(f + a2, e.length), s = [];
|
|
1163
|
+
let g = 0;
|
|
1164
|
+
d && g++, c && g++;
|
|
1165
|
+
const T = f + (d ? 1 : 0), y = W - (c ? 1 : 0);
|
|
1166
|
+
for (let t2 = T;t2 < y; t2++) {
|
|
1167
|
+
const n3 = e[t2], o = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o, i, {
|
|
1168
|
+
hard: true,
|
|
1169
|
+
trim: false
|
|
1170
|
+
}).split(`
|
|
1171
|
+
`);
|
|
1172
|
+
s.push(h2), g += h2.length;
|
|
1173
|
+
}
|
|
1174
|
+
if (g > v) {
|
|
1175
|
+
let t2 = 0, n3 = 0, o = g;
|
|
1176
|
+
const h2 = l2 - T;
|
|
1177
|
+
let u2 = v;
|
|
1178
|
+
const L = () => I(s, o, 0, h2, u2), E = () => I(s, o, h2 + 1, s.length, u2, true);
|
|
1179
|
+
d ? ({ lineCount: o, removals: t2 } = L(), o > u2 && (c || (u2 -= 1), { lineCount: o, removals: n3 } = E())) : (c || (u2 -= 1), { lineCount: o, removals: n3 } = E(), o > u2 && (u2 -= 1, { lineCount: o, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c = true, s.splice(s.length - n3, n3));
|
|
1180
|
+
}
|
|
1181
|
+
const x = [];
|
|
1182
|
+
d && x.push(M);
|
|
1183
|
+
for (const t2 of s)
|
|
1184
|
+
for (const n3 of t2)
|
|
1185
|
+
x.push(n3);
|
|
1186
|
+
return c && x.push(M), x;
|
|
1187
|
+
};
|
|
1188
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
1189
|
+
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1190
|
+
`${styleText2("dim", "Space:")} select`,
|
|
1191
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1192
|
+
];
|
|
1193
|
+
var m = (i, u2) => i.split(`
|
|
1194
|
+
`).map((d) => u2(d)).join(`
|
|
1195
|
+
`);
|
|
1196
|
+
var multiselect = (i) => {
|
|
1197
|
+
const u2 = (t2, a2) => {
|
|
1198
|
+
const r2 = t2.label ?? String(t2.value);
|
|
1199
|
+
return a2 === "disabled" ? `${styleText2("gray", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText2(["strikethrough", "gray"], o))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a2 === "active" ? `${styleText2("cyan", S_CHECKBOX_ACTIVE)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${m(r2, (o) => styleText2("dim", o))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "cancelled" ? `${m(r2, (o) => styleText2(["strikethrough", "dim"], o))}` : a2 === "active-selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a2 === "submitted" ? `${m(r2, (o) => styleText2("dim", o))}` : `${styleText2("dim", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText2("dim", o))}`;
|
|
1200
|
+
}, d = i.required ?? true, v = i.showInstructions ?? true;
|
|
1201
|
+
return new a({
|
|
1202
|
+
options: i.options,
|
|
1203
|
+
signal: i.signal,
|
|
1204
|
+
input: i.input,
|
|
1205
|
+
output: i.output,
|
|
1206
|
+
initialValues: i.initialValues,
|
|
1207
|
+
required: d,
|
|
1208
|
+
cursorAt: i.cursorAt,
|
|
1209
|
+
validate(t2) {
|
|
1210
|
+
if (d && (t2 === undefined || t2.length === 0))
|
|
1211
|
+
return `Please select at least one option.
|
|
1212
|
+
${styleText2("reset", styleText2("dim", `Press ${styleText2(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText2("gray", styleText2("bgWhite", styleText2("inverse", " enter ")))} to submit`))}`;
|
|
1213
|
+
},
|
|
1214
|
+
render() {
|
|
1215
|
+
const t2 = i.withGuide ?? settings.withGuide, a2 = wrapTextWithPrefix(i.output, i.message, t2 ? `${symbolBar(this.state)} ` : "", `${symbol(this.state)} `), r2 = `${t2 ? `${styleText2("gray", S_BAR)}
|
|
1216
|
+
` : ""}${a2}
|
|
1217
|
+
`, o = this.value ?? [], p = (n3, l2) => {
|
|
1218
|
+
if (n3.disabled)
|
|
1219
|
+
return u2(n3, "disabled");
|
|
1220
|
+
const s = o.includes(n3.value);
|
|
1221
|
+
return l2 && s ? u2(n3, "active-selected") : s ? u2(n3, "selected") : u2(n3, l2 ? "active" : "inactive");
|
|
1222
|
+
};
|
|
1223
|
+
switch (this.state) {
|
|
1224
|
+
case "submit": {
|
|
1225
|
+
const n3 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u2(s, "submitted")).join(styleText2("dim", ", ")) || styleText2("dim", "none"), l2 = wrapTextWithPrefix(i.output, n3, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
1226
|
+
return `${r2}${l2}`;
|
|
1227
|
+
}
|
|
1228
|
+
case "cancel": {
|
|
1229
|
+
const n3 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u2(s, "cancelled")).join(styleText2("dim", ", "));
|
|
1230
|
+
if (n3.trim() === "")
|
|
1231
|
+
return `${r2}${styleText2("gray", S_BAR)}`;
|
|
1232
|
+
const l2 = wrapTextWithPrefix(i.output, n3, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
1233
|
+
return `${r2}${l2}${t2 ? `
|
|
1234
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1235
|
+
}
|
|
1236
|
+
case "error": {
|
|
1237
|
+
const n3 = t2 ? `${styleText2("yellow", S_BAR)} ` : "", l2 = this.error.split(`
|
|
1238
|
+
`).map(($, C) => C === 0 ? `${t2 ? `${styleText2("yellow", S_BAR_END)} ` : ""}${styleText2("yellow", $)}` : ` ${$}`).join(`
|
|
1239
|
+
`), s = r2.split(`
|
|
1240
|
+
`).length, h2 = l2.split(`
|
|
1241
|
+
`).length + 1;
|
|
1242
|
+
return `${r2}${n3}${limitOptions({
|
|
1243
|
+
output: i.output,
|
|
1244
|
+
options: this.options,
|
|
1245
|
+
cursor: this.cursor,
|
|
1246
|
+
maxItems: i.maxItems,
|
|
1247
|
+
columnPadding: n3.length,
|
|
1248
|
+
rowPadding: s + h2,
|
|
1249
|
+
style: p
|
|
1250
|
+
}).join(`
|
|
1251
|
+
${n3}`)}
|
|
1252
|
+
${l2}
|
|
1253
|
+
`;
|
|
1254
|
+
}
|
|
1255
|
+
default: {
|
|
1256
|
+
const n3 = t2 ? `${styleText2("cyan", S_BAR)} ` : "", l2 = r2.split(`
|
|
1257
|
+
`).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2) : t2 ? [styleText2("cyan", S_BAR_END)] : [], h2 = s.join(`
|
|
1258
|
+
`), $ = s.length + 1;
|
|
1259
|
+
return `${r2}${n3}${limitOptions({
|
|
1260
|
+
output: i.output,
|
|
1261
|
+
options: this.options,
|
|
1262
|
+
cursor: this.cursor,
|
|
1263
|
+
maxItems: i.maxItems,
|
|
1264
|
+
columnPadding: n3.length,
|
|
1265
|
+
rowPadding: l2 + $,
|
|
1266
|
+
style: p
|
|
1267
|
+
}).join(`
|
|
1268
|
+
${n3}`)}
|
|
1269
|
+
${h2}
|
|
1270
|
+
`;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
}).prompt();
|
|
1275
|
+
};
|
|
1276
|
+
var log = {
|
|
1277
|
+
message: (s = [], {
|
|
1278
|
+
symbol: e = styleText2("gray", S_BAR),
|
|
1279
|
+
secondarySymbol: r2 = styleText2("gray", S_BAR),
|
|
1280
|
+
output: m2 = process.stdout,
|
|
1281
|
+
spacing: l2 = 1,
|
|
1282
|
+
withGuide: c
|
|
1283
|
+
} = {}) => {
|
|
1284
|
+
const t2 = [], o = c ?? settings.withGuide, f = o ? r2 : "", O = o ? `${e} ` : "", u2 = o ? `${r2} ` : "";
|
|
1285
|
+
for (let i = 0;i < l2; i++)
|
|
1286
|
+
t2.push(f);
|
|
1287
|
+
const g = Array.isArray(s) ? s : s.split(`
|
|
1288
|
+
`);
|
|
1289
|
+
if (g.length > 0) {
|
|
1290
|
+
const [i, ...y] = g;
|
|
1291
|
+
i.length > 0 ? t2.push(`${O}${i}`) : t2.push(o ? e : "");
|
|
1292
|
+
for (const p of y)
|
|
1293
|
+
p.length > 0 ? t2.push(`${u2}${p}`) : t2.push(o ? r2 : "");
|
|
1294
|
+
}
|
|
1295
|
+
m2.write(`${t2.join(`
|
|
1296
|
+
`)}
|
|
1297
|
+
`);
|
|
1298
|
+
},
|
|
1299
|
+
info: (s, e) => {
|
|
1300
|
+
log.message(s, { ...e, symbol: styleText2("blue", S_INFO) });
|
|
1301
|
+
},
|
|
1302
|
+
success: (s, e) => {
|
|
1303
|
+
log.message(s, { ...e, symbol: styleText2("green", S_SUCCESS) });
|
|
1304
|
+
},
|
|
1305
|
+
step: (s, e) => {
|
|
1306
|
+
log.message(s, { ...e, symbol: styleText2("green", S_STEP_SUBMIT) });
|
|
1307
|
+
},
|
|
1308
|
+
warn: (s, e) => {
|
|
1309
|
+
log.message(s, { ...e, symbol: styleText2("yellow", S_WARN) });
|
|
1310
|
+
},
|
|
1311
|
+
warning: (s, e) => {
|
|
1312
|
+
log.warn(s, e);
|
|
1313
|
+
},
|
|
1314
|
+
error: (s, e) => {
|
|
1315
|
+
log.message(s, { ...e, symbol: styleText2("red", S_ERROR) });
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
var cancel = (o = "", t2) => {
|
|
1319
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
|
|
1320
|
+
i.write(`${e}${styleText2("red", o)}
|
|
1321
|
+
|
|
1322
|
+
`);
|
|
1323
|
+
};
|
|
1324
|
+
var intro = (o = "", t2) => {
|
|
1325
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1326
|
+
i.write(`${e}${o}
|
|
1327
|
+
`);
|
|
1328
|
+
};
|
|
1329
|
+
var outro = (o = "", t2) => {
|
|
1330
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1331
|
+
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1332
|
+
i.write(`${e}${o}
|
|
1333
|
+
|
|
1334
|
+
`);
|
|
1335
|
+
};
|
|
1336
|
+
var W$1 = (o) => o;
|
|
1337
|
+
var C = (o, e, s) => {
|
|
1338
|
+
const a2 = {
|
|
1339
|
+
hard: true,
|
|
1340
|
+
trim: false
|
|
1341
|
+
}, i = wrapAnsi(o, e, a2).split(`
|
|
1342
|
+
`), c = i.reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), u2 = i.map(s).reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), g = e - (u2 - c);
|
|
1343
|
+
return wrapAnsi(o, g, a2);
|
|
1344
|
+
};
|
|
1345
|
+
var note = (o = "", e = "", s) => {
|
|
1346
|
+
const a2 = s?.output ?? process$1.stdout, i = s?.withGuide ?? settings.withGuide, c = s?.format ?? W$1, g = ["", ...C(o, getColumns(a2) - 6, c).split(`
|
|
1347
|
+
`).map(c), ""], n3 = dist_default2(e), t2 = Math.max(g.reduce((m2, F) => {
|
|
1348
|
+
const O = dist_default2(F);
|
|
1349
|
+
return O > m2 ? O : m2;
|
|
1350
|
+
}, 0), n3) + 2, h2 = g.map((m2) => `${styleText2("gray", S_BAR)} ${m2}${" ".repeat(t2 - dist_default2(m2))}${styleText2("gray", S_BAR)}`).join(`
|
|
1351
|
+
`), T = i ? `${styleText2("gray", S_BAR)}
|
|
1352
|
+
` : "", l$1 = i ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
1353
|
+
a2.write(`${T}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2("gray", S_BAR_H.repeat(Math.max(t2 - n3 - 1, 1)) + S_CORNER_TOP_RIGHT)}
|
|
1354
|
+
${h2}
|
|
1355
|
+
${styleText2("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
1356
|
+
`);
|
|
1357
|
+
};
|
|
1358
|
+
var W = (l2) => styleText2("magenta", l2);
|
|
1359
|
+
var spinner = ({
|
|
1360
|
+
indicator: l2 = "dots",
|
|
1361
|
+
onCancel: h2,
|
|
1362
|
+
output: n3 = process.stdout,
|
|
1363
|
+
cancelMessage: G,
|
|
1364
|
+
errorMessage: O,
|
|
1365
|
+
frames: E = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
|
|
1366
|
+
delay: F = unicode ? 80 : 120,
|
|
1367
|
+
signal: m2,
|
|
1368
|
+
...I2
|
|
1369
|
+
} = {}) => {
|
|
1370
|
+
const u2 = isCI();
|
|
1371
|
+
let M, T, d = false, S = false, s = "", p, w = performance.now();
|
|
1372
|
+
const x = getColumns(n3), k = I2?.styleFrame ?? W, g = (e) => {
|
|
1373
|
+
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
1374
|
+
S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
|
|
1375
|
+
}, f = () => g(2), i = () => g(1), A = () => {
|
|
1376
|
+
process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g), m2 && m2.addEventListener("abort", i);
|
|
1377
|
+
}, H = () => {
|
|
1378
|
+
process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g), m2 && m2.removeEventListener("abort", i);
|
|
1379
|
+
}, y = () => {
|
|
1380
|
+
if (p === undefined)
|
|
1381
|
+
return;
|
|
1382
|
+
u2 && n3.write(`
|
|
1383
|
+
`);
|
|
1384
|
+
const r2 = wrapAnsi(p, x, {
|
|
1385
|
+
hard: true,
|
|
1386
|
+
trim: false
|
|
1387
|
+
}).split(`
|
|
1388
|
+
`);
|
|
1389
|
+
r2.length > 1 && n3.write(import_sisteransi2.cursor.up(r2.length - 1)), n3.write(import_sisteransi2.cursor.to(0)), n3.write(import_sisteransi2.erase.down());
|
|
1390
|
+
}, C2 = (e) => e.replace(/\.+$/, ""), _ = (e) => {
|
|
1391
|
+
const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o = Math.floor(r2 % 60);
|
|
1392
|
+
return t2 > 0 ? `[${t2}m ${o}s]` : `[${o}s]`;
|
|
1393
|
+
}, N = I2.withGuide ?? settings.withGuide, P = (e = "") => {
|
|
1394
|
+
d = true, M = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
|
|
1395
|
+
`);
|
|
1396
|
+
let r2 = 0, t2 = 0;
|
|
1397
|
+
A(), T = setInterval(() => {
|
|
1398
|
+
if (u2 && s === p)
|
|
1399
|
+
return;
|
|
1400
|
+
y(), p = s;
|
|
1401
|
+
const o = k(E[r2]);
|
|
1402
|
+
let v;
|
|
1403
|
+
if (u2)
|
|
1404
|
+
v = `${o} ${s}...`;
|
|
1405
|
+
else if (l2 === "timer")
|
|
1406
|
+
v = `${o} ${s} ${_(w)}`;
|
|
1407
|
+
else {
|
|
1408
|
+
const B = ".".repeat(Math.floor(t2)).slice(0, 3);
|
|
1409
|
+
v = `${o} ${s}${B}`;
|
|
1410
|
+
}
|
|
1411
|
+
const j = wrapAnsi(v, x, {
|
|
1412
|
+
hard: true,
|
|
1413
|
+
trim: false
|
|
1414
|
+
});
|
|
1415
|
+
n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
1416
|
+
}, F);
|
|
1417
|
+
}, a2 = (e = "", r2 = 0, t2 = false) => {
|
|
1418
|
+
if (!d)
|
|
1419
|
+
return;
|
|
1420
|
+
d = false, clearInterval(T), y();
|
|
1421
|
+
const o = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
1422
|
+
s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o} ${s} ${_(w)}
|
|
1423
|
+
`) : n3.write(`${o} ${s}
|
|
1424
|
+
`)), H(), M();
|
|
1425
|
+
};
|
|
1426
|
+
return {
|
|
1427
|
+
start: P,
|
|
1428
|
+
stop: (e = "") => a2(e, 0),
|
|
1429
|
+
message: (e = "") => {
|
|
1430
|
+
s = C2(e ?? s);
|
|
1431
|
+
},
|
|
1432
|
+
cancel: (e = "") => a2(e, 1),
|
|
1433
|
+
error: (e = "") => a2(e, 2),
|
|
1434
|
+
clear: () => a2("", 0, true),
|
|
1435
|
+
get isCancelled() {
|
|
1436
|
+
return S;
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
};
|
|
1440
|
+
var u2 = {
|
|
1441
|
+
light: unicodeOr("─", "-"),
|
|
1442
|
+
heavy: unicodeOr("━", "="),
|
|
1443
|
+
block: unicodeOr("█", "#")
|
|
1444
|
+
};
|
|
1445
|
+
var SELECT_INSTRUCTIONS = [
|
|
1446
|
+
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1447
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1448
|
+
];
|
|
1449
|
+
var c = (t2, o) => t2.includes(`
|
|
1450
|
+
`) ? t2.split(`
|
|
1451
|
+
`).map((d) => o(d)).join(`
|
|
1452
|
+
`) : o(t2);
|
|
1453
|
+
var select = (t2) => {
|
|
1454
|
+
const o = (n3, m2) => {
|
|
1455
|
+
if (n3 === undefined)
|
|
1456
|
+
return "";
|
|
1457
|
+
const s = n3.label ?? String(n3.value);
|
|
1458
|
+
switch (m2) {
|
|
1459
|
+
case "disabled":
|
|
1460
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (i) => styleText2("gray", i))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
|
|
1461
|
+
case "selected":
|
|
1462
|
+
return `${c(s, (i) => styleText2("dim", i))}`;
|
|
1463
|
+
case "active":
|
|
1464
|
+
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
|
|
1465
|
+
case "cancelled":
|
|
1466
|
+
return `${c(s, (i) => styleText2(["strikethrough", "dim"], i))}`;
|
|
1467
|
+
default:
|
|
1468
|
+
return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s, (i) => styleText2("dim", i))}`;
|
|
1469
|
+
}
|
|
1470
|
+
}, d = t2.showInstructions ?? true;
|
|
1471
|
+
return new n$1({
|
|
1472
|
+
options: t2.options,
|
|
1473
|
+
signal: t2.signal,
|
|
1474
|
+
input: t2.input,
|
|
1475
|
+
output: t2.output,
|
|
1476
|
+
initialValue: t2.initialValue,
|
|
1477
|
+
render() {
|
|
1478
|
+
const n3 = t2.withGuide ?? settings.withGuide, m2 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i = wrapTextWithPrefix(t2.output, t2.message, s, m2), u3 = `${n3 ? `${styleText2("gray", S_BAR)}
|
|
1479
|
+
` : ""}${i}
|
|
1480
|
+
`;
|
|
1481
|
+
switch (this.state) {
|
|
1482
|
+
case "submit": {
|
|
1483
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(t2.output, o(this.options[this.cursor], "selected"), r2);
|
|
1484
|
+
return `${u3}${a2}`;
|
|
1485
|
+
}
|
|
1486
|
+
case "cancel": {
|
|
1487
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(t2.output, o(this.options[this.cursor], "cancelled"), r2);
|
|
1488
|
+
return `${u3}${a2}${n3 ? `
|
|
1489
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1490
|
+
}
|
|
1491
|
+
default: {
|
|
1492
|
+
const r2 = n3 ? `${styleText2("cyan", S_BAR)} ` : "", a2 = u3.split(`
|
|
1493
|
+
`).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n3) : n3 ? [styleText2("cyan", S_BAR_END)] : [], b = p.join(`
|
|
1494
|
+
`), f = p.length + 1;
|
|
1495
|
+
return `${u3}${r2}${limitOptions({
|
|
1496
|
+
output: t2.output,
|
|
1497
|
+
cursor: this.cursor,
|
|
1498
|
+
options: this.options,
|
|
1499
|
+
maxItems: t2.maxItems,
|
|
1500
|
+
columnPadding: r2.length,
|
|
1501
|
+
rowPadding: a2 + f,
|
|
1502
|
+
style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
|
|
1503
|
+
}).join(`
|
|
1504
|
+
${r2}`)}
|
|
1505
|
+
${b}
|
|
1506
|
+
`;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}).prompt();
|
|
1511
|
+
};
|
|
1512
|
+
var i = `${styleText2("gray", S_BAR)} `;
|
|
1513
|
+
var text = (e) => new n2({
|
|
1514
|
+
validate: e.validate,
|
|
1515
|
+
placeholder: e.placeholder,
|
|
1516
|
+
defaultValue: e.defaultValue,
|
|
1517
|
+
initialValue: e.initialValue,
|
|
1518
|
+
output: e.output,
|
|
1519
|
+
signal: e.signal,
|
|
1520
|
+
input: e.input,
|
|
1521
|
+
render() {
|
|
1522
|
+
const i2 = e?.withGuide ?? settings.withGuide, s = `${`${i2 ? `${styleText2("gray", S_BAR)}
|
|
1523
|
+
` : ""}${symbol(this.state)} `}${e.message}
|
|
1524
|
+
`, c2 = e.placeholder && e.placeholder.length > 0 ? styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1)) : styleText2(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : c2, l2 = this.value ?? "";
|
|
1525
|
+
switch (this.state) {
|
|
1526
|
+
case "error": {
|
|
1527
|
+
const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
|
|
1528
|
+
return `${s.trim()}
|
|
1529
|
+
${r2}${o}
|
|
1530
|
+
${d}${n3}
|
|
1531
|
+
`;
|
|
1532
|
+
}
|
|
1533
|
+
case "submit": {
|
|
1534
|
+
const n3 = l2 ? ` ${styleText2("dim", l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1535
|
+
return `${s}${r2}${n3}`;
|
|
1536
|
+
}
|
|
1537
|
+
case "cancel": {
|
|
1538
|
+
const n3 = l2 ? ` ${styleText2(["strikethrough", "dim"], l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1539
|
+
return `${s}${r2}${n3}${l2.trim() ? `
|
|
1540
|
+
${r2}` : ""}`;
|
|
1541
|
+
}
|
|
1542
|
+
default: {
|
|
1543
|
+
const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "";
|
|
1544
|
+
return `${s}${n3}${o}
|
|
1545
|
+
${r2}
|
|
1546
|
+
`;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
}).prompt();
|
|
1551
|
+
|
|
1552
|
+
// src/ui.ts
|
|
1553
|
+
import { resolve as resolve3 } from "node:path";
|
|
1554
|
+
var hint = (s) => s.replace(/\s+/g, " ").trim().slice(0, 90);
|
|
1555
|
+
var cancelled = () => {
|
|
1556
|
+
cancel("Installation cancelled.");
|
|
1557
|
+
return 1;
|
|
1558
|
+
};
|
|
1559
|
+
function report(result, target, home) {
|
|
1560
|
+
if (result.installed.length)
|
|
1561
|
+
log.success(`Installed: ${result.installed.join(", ")}`);
|
|
1562
|
+
if (result.overwritten.length)
|
|
1563
|
+
log.info(`Overwritten: ${result.overwritten.join(", ")}`);
|
|
1564
|
+
if (result.skipped.length)
|
|
1565
|
+
log.warn(`Skipped (already installed): ${result.skipped.join(", ")}`);
|
|
1566
|
+
for (const f of result.failed)
|
|
1567
|
+
log.error(`${f.name}: ${f.error}`);
|
|
1568
|
+
note(`Install target: ${displayPath(target, home)}`, "Done");
|
|
1569
|
+
}
|
|
1570
|
+
async function runInteractive(ctx) {
|
|
1571
|
+
intro("Grimoire");
|
|
1572
|
+
const registry = listSkills(ctx.catalogDir);
|
|
1573
|
+
if (!registry.length) {
|
|
1574
|
+
log.error("No skills found in the catalog.");
|
|
1575
|
+
return 1;
|
|
1576
|
+
}
|
|
1577
|
+
const grouped = categories(registry);
|
|
1578
|
+
const root = await select({ message: "What would you like to do?", options: [
|
|
1579
|
+
...grouped.map((c2) => ({ value: `category:${c2.name}`, label: c2.name, hint: `${c2.skills.length} skill(s)` })),
|
|
1580
|
+
{ value: "detect", label: "Detect project skills", hint: "Analyze this project and recommend relevant skills" },
|
|
1581
|
+
{ value: "search", label: "Search all skills", hint: "Find a skill by name or description" }
|
|
1582
|
+
] });
|
|
1583
|
+
if (isCancel(root))
|
|
1584
|
+
return cancelled();
|
|
1585
|
+
let selected;
|
|
1586
|
+
if (root === "detect") {
|
|
1587
|
+
const detection = detectStack(ctx.projectDir ?? process.cwd(), registry);
|
|
1588
|
+
if (!detection.recommendations.length)
|
|
1589
|
+
log.info("No matching recommendations found; browse a category instead.");
|
|
1590
|
+
else
|
|
1591
|
+
note(detection.recommendations.map((r2) => `${r2.name}: ${r2.reason}`).join(`
|
|
1592
|
+
`), `Detected ${detection.stack.join(", ") || "no known stack"}`);
|
|
1593
|
+
const picked = await multiselect({ message: "Review recommendations (add or remove skills)", options: registry.map((s) => ({ value: s.name, label: s.name, hint: hint(s.description), initialValue: detection.skills.includes(s.name) })), required: true });
|
|
1594
|
+
if (isCancel(picked))
|
|
1595
|
+
return cancelled();
|
|
1596
|
+
selected = picked;
|
|
1597
|
+
} else {
|
|
1598
|
+
let options;
|
|
1599
|
+
if (root === "search") {
|
|
1600
|
+
const query = await text({ message: "Search skills" });
|
|
1601
|
+
if (isCancel(query))
|
|
1602
|
+
return cancelled();
|
|
1603
|
+
const needle = String(query).toLowerCase();
|
|
1604
|
+
options = registry.filter((s) => `${s.name} ${s.description} ${s.category}`.toLowerCase().includes(needle));
|
|
1605
|
+
if (!options.length) {
|
|
1606
|
+
log.error("No matching skills.");
|
|
1607
|
+
return 1;
|
|
1608
|
+
}
|
|
1609
|
+
} else
|
|
1610
|
+
options = grouped.find((c2) => c2.name === String(root).slice(9))?.skills ?? registry;
|
|
1611
|
+
const picked = await multiselect({ message: "Select skills (space to toggle, enter to continue)", options: options.map((s) => ({ value: s.name, label: s.name, hint: hint(s.description) })), required: true });
|
|
1612
|
+
if (isCancel(picked))
|
|
1613
|
+
return cancelled();
|
|
1614
|
+
selected = picked;
|
|
1615
|
+
}
|
|
1616
|
+
const review = await multiselect({ message: `Review selection: ${selected.length} skill(s)`, options: registry.map((s) => ({ value: s.name, label: s.name, hint: s.category })), initialValues: selected, required: true });
|
|
1617
|
+
if (isCancel(review))
|
|
1618
|
+
return cancelled();
|
|
1619
|
+
selected = review;
|
|
1620
|
+
const target = ctx.targetDirOverride ? undefined : await select({ message: "Which destination agent should receive them?", options: TARGETS.map((t2) => ({ value: t2.id, label: t2.label, hint: displayPath(resolveSkillsDir(t2.id, { home: ctx.home, env: ctx.env, projectDir: ctx.projectDir, global: ctx.global }), ctx.home) })) });
|
|
1621
|
+
if (target !== undefined && isCancel(target))
|
|
1622
|
+
return cancelled();
|
|
1623
|
+
const targetDir = ctx.targetDirOverride ?? resolveSkillsDir(target, { home: ctx.home, env: ctx.env, projectDir: ctx.projectDir, global: ctx.global });
|
|
1624
|
+
let overwrite = ctx.overwrite ?? false;
|
|
1625
|
+
const conflicts = findConflicts(targetDir, selected);
|
|
1626
|
+
if (conflicts.length && !overwrite) {
|
|
1627
|
+
const mode = await select({ message: "Some selected skills already exist. How should Grimoire proceed?", options: [{ value: "skip", label: "Keep existing copies" }, { value: "overwrite", label: "Overwrite existing copies" }, { value: "cancel", label: "Cancel" }] });
|
|
1628
|
+
if (isCancel(mode) || mode === "cancel")
|
|
1629
|
+
return cancelled();
|
|
1630
|
+
overwrite = mode === "overwrite";
|
|
1631
|
+
}
|
|
1632
|
+
const confirmed = await select({ message: `Install ${selected.length} skill(s) to ${displayPath(targetDir, ctx.home)}?`, options: [{ value: "confirm", label: "Confirm installation" }, { value: "cancel", label: "Cancel" }] });
|
|
1633
|
+
if (isCancel(confirmed) || confirmed !== "confirm")
|
|
1634
|
+
return cancelled();
|
|
1635
|
+
const spin = spinner();
|
|
1636
|
+
spin.start("Installing");
|
|
1637
|
+
const result = installSkills({ catalogDir: ctx.catalogDir, targetDir, names: selected, overwrite, onStatus: (name) => spin.message(`Installing ${name}`) });
|
|
1638
|
+
spin.stop("Installation complete");
|
|
1639
|
+
if (!ctx.global && (result.installed.length || result.overwritten.length)) {
|
|
1640
|
+
const projectDir = resolve3(ctx.projectDir ?? process.cwd());
|
|
1641
|
+
const lock = readLockfile(projectDir);
|
|
1642
|
+
for (const name of [...result.installed, ...result.overwritten]) {
|
|
1643
|
+
const skill = findSkill(ctx.catalogDir, name);
|
|
1644
|
+
if (skill)
|
|
1645
|
+
updateLock(lock, name, { version: skill.version, hash: skillHash(skill.dir), installed: new Date().toISOString(), agents: [target ? String(target) : "custom"] });
|
|
1646
|
+
}
|
|
1647
|
+
writeLockfile(projectDir, lock);
|
|
1648
|
+
}
|
|
1649
|
+
report(result, targetDir, ctx.home);
|
|
1650
|
+
outro("Ready");
|
|
1651
|
+
return result.failed.length ? 1 : 0;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
// src/index.ts
|
|
1655
|
+
var packageRoot = resolve4(fileURLToPath(new URL("..", import.meta.url)));
|
|
1656
|
+
var catalogDir = existsSync5(join7(packageRoot, "skills")) ? join7(packageRoot, "skills") : resolve4(packageRoot, "../../skills/skills");
|
|
1657
|
+
var usage = `grimoire — browse and install agent skills
|
|
1658
|
+
|
|
1659
|
+
Usage:
|
|
1660
|
+
grimoire interactive catalog (default)
|
|
1661
|
+
grimoire install -s <skill> -t <agent> noninteractive install
|
|
1662
|
+
grimoire list|search [query] browse the catalog
|
|
1663
|
+
grimoire detect recommend skills for this project
|
|
1664
|
+
grimoire status show project lockfile
|
|
1665
|
+
|
|
1666
|
+
Agents: ${TARGETS.map((t2) => t2.id).join(", ")}
|
|
1667
|
+
Options: --global --target-dir <dir> --overwrite --help --version`;
|
|
1668
|
+
function value(args, flag) {
|
|
1669
|
+
const i2 = args.indexOf(flag);
|
|
1670
|
+
return i2 < 0 ? undefined : args[i2 + 1];
|
|
1671
|
+
}
|
|
1672
|
+
function print(skills, query = "") {
|
|
1673
|
+
for (const s of skills.filter((s2) => !query || `${s2.name} ${s2.description} ${s2.category}`.toLowerCase().includes(query.toLowerCase())))
|
|
1674
|
+
console.log(`${s.name} [${s.category}] — ${s.description.split(`
|
|
1675
|
+
`)[0]}`);
|
|
1676
|
+
}
|
|
1677
|
+
function version() {
|
|
1678
|
+
try {
|
|
1679
|
+
return JSON.parse(readFileSync5(join7(packageRoot, "package.json"), "utf8")).version;
|
|
1680
|
+
} catch {
|
|
1681
|
+
return "0.0.0";
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
async function main() {
|
|
1685
|
+
const args = process.argv.slice(2);
|
|
1686
|
+
if (!args.length || args[0] === "--global")
|
|
1687
|
+
return runInteractive({ catalogDir, home: homedir2(), projectDir: resolve4(process.cwd()), global: args.includes("--global") });
|
|
1688
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
1689
|
+
console.log(usage);
|
|
1690
|
+
return 0;
|
|
1691
|
+
}
|
|
1692
|
+
if (args.includes("--version")) {
|
|
1693
|
+
console.log(version());
|
|
1694
|
+
return 0;
|
|
1695
|
+
}
|
|
1696
|
+
const registry = readRegistry(catalogDir);
|
|
1697
|
+
const command = args[0];
|
|
1698
|
+
if (command === "list" || command === "search") {
|
|
1699
|
+
print(registry, command === "search" ? args[1] ?? "" : "");
|
|
1700
|
+
return 0;
|
|
1701
|
+
}
|
|
1702
|
+
if (command === "detect") {
|
|
1703
|
+
const d = detectStack(resolve4(process.cwd()), registry);
|
|
1704
|
+
console.log(`Detected: ${d.stack.join(", ") || "no known stack"}`);
|
|
1705
|
+
for (const r2 of d.recommendations)
|
|
1706
|
+
console.log(` ${r2.name} — ${r2.reason}`);
|
|
1707
|
+
return 0;
|
|
1708
|
+
}
|
|
1709
|
+
if (command === "status") {
|
|
1710
|
+
const lock = readLockfile(resolve4(process.cwd()));
|
|
1711
|
+
const entries = Object.entries(lock.skills);
|
|
1712
|
+
if (!entries.length) {
|
|
1713
|
+
console.log("No tracked project installations.");
|
|
1714
|
+
return 0;
|
|
1715
|
+
}
|
|
1716
|
+
for (const [name, entry] of entries)
|
|
1717
|
+
console.log(`${name} [${entry.agents.join(", ")}] ${entry.hash}`);
|
|
1718
|
+
return 0;
|
|
1719
|
+
}
|
|
1720
|
+
if (command !== "install")
|
|
1721
|
+
throw new Error(`unknown command: ${command}`);
|
|
1722
|
+
const names = args.flatMap((a2, i2) => a2 === "-s" || a2 === "--skill" ? [args[i2 + 1]] : []).filter(Boolean);
|
|
1723
|
+
const target = value(args, "-t") ?? value(args, "--target");
|
|
1724
|
+
if (!names.length || !target || !isTargetId(target))
|
|
1725
|
+
throw new Error(`noninteractive install requires --skill and --target (${TARGETS.map((t2) => t2.id).join(", ")})`);
|
|
1726
|
+
const unknown = names.filter((n3) => !findSkill(catalogDir, n3));
|
|
1727
|
+
if (unknown.length)
|
|
1728
|
+
throw new Error(`unknown skill(s): ${unknown.join(", ")}`);
|
|
1729
|
+
const global = args.includes("--global");
|
|
1730
|
+
const projectDir = resolve4(process.cwd());
|
|
1731
|
+
const dir = value(args, "--target-dir") ?? resolveSkillsDir(target, { home: homedir2(), projectDir, global });
|
|
1732
|
+
const result = installSkills({ catalogDir, targetDir: resolve4(dir), names, overwrite: args.includes("--overwrite") });
|
|
1733
|
+
if (!global) {
|
|
1734
|
+
const lock = readLockfile(projectDir);
|
|
1735
|
+
for (const name of [...result.installed, ...result.overwritten]) {
|
|
1736
|
+
const skill = findSkill(catalogDir, name);
|
|
1737
|
+
if (skill)
|
|
1738
|
+
updateLock(lock, name, { version: skill.version, hash: skillHash(skill.dir), installed: new Date().toISOString(), agents: [target] });
|
|
1739
|
+
}
|
|
1740
|
+
if (result.installed.length || result.overwritten.length)
|
|
1741
|
+
writeLockfile(projectDir, lock);
|
|
1742
|
+
}
|
|
1743
|
+
if (result.installed.length)
|
|
1744
|
+
console.log(`installed: ${result.installed.join(", ")}`);
|
|
1745
|
+
if (result.overwritten.length)
|
|
1746
|
+
console.log(`overwritten: ${result.overwritten.join(", ")}`);
|
|
1747
|
+
if (result.skipped.length)
|
|
1748
|
+
console.log(`already installed, skipped: ${result.skipped.join(", ")}`);
|
|
1749
|
+
if (result.failed.length)
|
|
1750
|
+
throw new Error(result.failed.map((f) => `${f.name}: ${f.error}`).join("; "));
|
|
1751
|
+
return 0;
|
|
1752
|
+
}
|
|
1753
|
+
main().then((code) => {
|
|
1754
|
+
process.exitCode = code;
|
|
1755
|
+
}).catch((error) => {
|
|
1756
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
1757
|
+
process.exitCode = 1;
|
|
1758
|
+
});
|