workflow-agent-cli 2.17.0 → 2.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +464 -16
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -324,7 +324,7 @@ async function initCommand(options) {
|
|
|
324
324
|
scopes = presetModule.scopes || presetModule.default.scopes;
|
|
325
325
|
const spinner10 = p.spinner();
|
|
326
326
|
spinner10.start(`Loading ${presetModule.default?.name || preset} preset`);
|
|
327
|
-
await new Promise((
|
|
327
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
328
328
|
spinner10.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
|
|
329
329
|
} catch (error) {
|
|
330
330
|
console.log(
|
|
@@ -5235,8 +5235,7 @@ import {
|
|
|
5235
5235
|
TelemetryCollector as TelemetryCollector2,
|
|
5236
5236
|
FixPatternSchema,
|
|
5237
5237
|
BlueprintSchema,
|
|
5238
|
-
SolutionPatternSchema
|
|
5239
|
-
createDefaultMetrics
|
|
5238
|
+
SolutionPatternSchema
|
|
5240
5239
|
} from "@hawkinside_out/workflow-improvement-tracker";
|
|
5241
5240
|
|
|
5242
5241
|
// src/sync/registry-client.ts
|
|
@@ -5380,7 +5379,7 @@ var RegistryClient = class {
|
|
|
5380
5379
|
}
|
|
5381
5380
|
if (attempt < this.retries) {
|
|
5382
5381
|
await new Promise(
|
|
5383
|
-
(
|
|
5382
|
+
(resolve3) => setTimeout(resolve3, Math.pow(2, attempt) * 1e3)
|
|
5384
5383
|
);
|
|
5385
5384
|
}
|
|
5386
5385
|
}
|
|
@@ -5834,8 +5833,8 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5834
5833
|
chalk16.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
5835
5834
|
);
|
|
5836
5835
|
}
|
|
5837
|
-
const framework = options.framework ?? patternData.compatibility
|
|
5838
|
-
const version = options.version ?? patternData.compatibility
|
|
5836
|
+
const framework = options.framework ?? patternData.compatibility?.frameworks?.[0]?.name ?? "unknown";
|
|
5837
|
+
const version = options.version ?? patternData.compatibility?.frameworks?.[0]?.version ?? "0.0.0";
|
|
5839
5838
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
5840
5839
|
if (patternType === "fix") {
|
|
5841
5840
|
const fixPattern = patternData;
|
|
@@ -6723,6 +6722,457 @@ function tryAutoFix(data, type, issues) {
|
|
|
6723
6722
|
}
|
|
6724
6723
|
return { fixable: false };
|
|
6725
6724
|
}
|
|
6725
|
+
var LIBRARY_TAG_MAP = {
|
|
6726
|
+
// Frontend Frameworks
|
|
6727
|
+
"react": [{ category: "framework", name: "react" }],
|
|
6728
|
+
"react-dom": [{ category: "framework", name: "react" }],
|
|
6729
|
+
"next": [{ category: "framework", name: "next" }],
|
|
6730
|
+
"vue": [{ category: "framework", name: "vue" }],
|
|
6731
|
+
"nuxt": [{ category: "framework", name: "nuxt" }],
|
|
6732
|
+
"svelte": [{ category: "framework", name: "svelte" }],
|
|
6733
|
+
"@sveltejs/kit": [{ category: "framework", name: "sveltekit" }],
|
|
6734
|
+
"solid-js": [{ category: "framework", name: "solid" }],
|
|
6735
|
+
"@angular/core": [{ category: "framework", name: "angular" }],
|
|
6736
|
+
"astro": [{ category: "framework", name: "astro" }],
|
|
6737
|
+
"remix": [{ category: "framework", name: "remix" }],
|
|
6738
|
+
// Backend Frameworks
|
|
6739
|
+
"express": [{ category: "framework", name: "express" }],
|
|
6740
|
+
"fastify": [{ category: "framework", name: "fastify" }],
|
|
6741
|
+
"hono": [{ category: "framework", name: "hono" }],
|
|
6742
|
+
"koa": [{ category: "framework", name: "koa" }],
|
|
6743
|
+
"@nestjs/core": [{ category: "framework", name: "nestjs" }],
|
|
6744
|
+
"hapi": [{ category: "framework", name: "hapi" }],
|
|
6745
|
+
// Testing
|
|
6746
|
+
"vitest": [{ category: "tooling", name: "vitest" }, { category: "category", name: "testing" }],
|
|
6747
|
+
"jest": [{ category: "tooling", name: "jest" }, { category: "category", name: "testing" }],
|
|
6748
|
+
"@testing-library/react": [{ category: "tooling", name: "testing-library" }],
|
|
6749
|
+
"playwright": [{ category: "tooling", name: "playwright" }, { category: "category", name: "e2e" }],
|
|
6750
|
+
"cypress": [{ category: "tooling", name: "cypress" }, { category: "category", name: "e2e" }],
|
|
6751
|
+
// State Management
|
|
6752
|
+
"zustand": [{ category: "tooling", name: "zustand" }, { category: "category", name: "state" }],
|
|
6753
|
+
"redux": [{ category: "tooling", name: "redux" }, { category: "category", name: "state" }],
|
|
6754
|
+
"@reduxjs/toolkit": [{ category: "tooling", name: "redux-toolkit" }, { category: "category", name: "state" }],
|
|
6755
|
+
"jotai": [{ category: "tooling", name: "jotai" }, { category: "category", name: "state" }],
|
|
6756
|
+
"recoil": [{ category: "tooling", name: "recoil" }, { category: "category", name: "state" }],
|
|
6757
|
+
"mobx": [{ category: "tooling", name: "mobx" }, { category: "category", name: "state" }],
|
|
6758
|
+
"pinia": [{ category: "tooling", name: "pinia" }, { category: "category", name: "state" }],
|
|
6759
|
+
"xstate": [{ category: "tooling", name: "xstate" }, { category: "category", name: "state-machine" }],
|
|
6760
|
+
// Database & ORM
|
|
6761
|
+
"prisma": [{ category: "tooling", name: "prisma" }, { category: "category", name: "database" }],
|
|
6762
|
+
"@prisma/client": [{ category: "tooling", name: "prisma" }, { category: "category", name: "database" }],
|
|
6763
|
+
"drizzle-orm": [{ category: "tooling", name: "drizzle" }, { category: "category", name: "database" }],
|
|
6764
|
+
"typeorm": [{ category: "tooling", name: "typeorm" }, { category: "category", name: "database" }],
|
|
6765
|
+
"mongoose": [{ category: "tooling", name: "mongoose" }, { category: "category", name: "mongodb" }],
|
|
6766
|
+
"knex": [{ category: "tooling", name: "knex" }, { category: "category", name: "database" }],
|
|
6767
|
+
"sequelize": [{ category: "tooling", name: "sequelize" }, { category: "category", name: "database" }],
|
|
6768
|
+
// Authentication
|
|
6769
|
+
"next-auth": [{ category: "tooling", name: "next-auth" }, { category: "category", name: "auth" }],
|
|
6770
|
+
"@auth/core": [{ category: "tooling", name: "authjs" }, { category: "category", name: "auth" }],
|
|
6771
|
+
"passport": [{ category: "tooling", name: "passport" }, { category: "category", name: "auth" }],
|
|
6772
|
+
"lucia": [{ category: "tooling", name: "lucia" }, { category: "category", name: "auth" }],
|
|
6773
|
+
"@clerk/nextjs": [{ category: "tooling", name: "clerk" }, { category: "category", name: "auth" }],
|
|
6774
|
+
// UI Libraries
|
|
6775
|
+
"@radix-ui/react-dialog": [{ category: "tooling", name: "radix-ui" }],
|
|
6776
|
+
"@radix-ui/react-dropdown-menu": [{ category: "tooling", name: "radix-ui" }],
|
|
6777
|
+
"@shadcn/ui": [{ category: "tooling", name: "shadcn" }],
|
|
6778
|
+
"@chakra-ui/react": [{ category: "tooling", name: "chakra-ui" }],
|
|
6779
|
+
"@mantine/core": [{ category: "tooling", name: "mantine" }],
|
|
6780
|
+
"@headlessui/react": [{ category: "tooling", name: "headlessui" }],
|
|
6781
|
+
"antd": [{ category: "tooling", name: "antd" }],
|
|
6782
|
+
"@mui/material": [{ category: "tooling", name: "material-ui" }],
|
|
6783
|
+
// Styling
|
|
6784
|
+
"tailwindcss": [{ category: "tooling", name: "tailwind" }],
|
|
6785
|
+
"styled-components": [{ category: "tooling", name: "styled-components" }],
|
|
6786
|
+
"@emotion/react": [{ category: "tooling", name: "emotion" }],
|
|
6787
|
+
"sass": [{ category: "tooling", name: "sass" }],
|
|
6788
|
+
// API & Data Fetching
|
|
6789
|
+
"@tanstack/react-query": [{ category: "tooling", name: "tanstack-query" }, { category: "category", name: "data-fetching" }],
|
|
6790
|
+
"swr": [{ category: "tooling", name: "swr" }, { category: "category", name: "data-fetching" }],
|
|
6791
|
+
"@trpc/server": [{ category: "tooling", name: "trpc" }, { category: "category", name: "api" }],
|
|
6792
|
+
"@trpc/client": [{ category: "tooling", name: "trpc" }, { category: "category", name: "api" }],
|
|
6793
|
+
"graphql": [{ category: "tooling", name: "graphql" }, { category: "category", name: "api" }],
|
|
6794
|
+
"@apollo/client": [{ category: "tooling", name: "apollo" }, { category: "category", name: "graphql" }],
|
|
6795
|
+
"axios": [{ category: "tooling", name: "axios" }],
|
|
6796
|
+
// Form Libraries
|
|
6797
|
+
"react-hook-form": [{ category: "tooling", name: "react-hook-form" }, { category: "category", name: "forms" }],
|
|
6798
|
+
"formik": [{ category: "tooling", name: "formik" }, { category: "category", name: "forms" }],
|
|
6799
|
+
"@tanstack/react-form": [{ category: "tooling", name: "tanstack-form" }, { category: "category", name: "forms" }],
|
|
6800
|
+
// Validation
|
|
6801
|
+
"zod": [{ category: "tooling", name: "zod" }, { category: "category", name: "validation" }],
|
|
6802
|
+
"yup": [{ category: "tooling", name: "yup" }, { category: "category", name: "validation" }],
|
|
6803
|
+
"valibot": [{ category: "tooling", name: "valibot" }, { category: "category", name: "validation" }],
|
|
6804
|
+
// Build Tools
|
|
6805
|
+
"vite": [{ category: "tooling", name: "vite" }],
|
|
6806
|
+
"esbuild": [{ category: "tooling", name: "esbuild" }],
|
|
6807
|
+
"tsup": [{ category: "tooling", name: "tsup" }],
|
|
6808
|
+
"webpack": [{ category: "tooling", name: "webpack" }],
|
|
6809
|
+
"turbo": [{ category: "tooling", name: "turborepo" }],
|
|
6810
|
+
// Utilities
|
|
6811
|
+
"lodash": [{ category: "tooling", name: "lodash" }],
|
|
6812
|
+
"date-fns": [{ category: "tooling", name: "date-fns" }],
|
|
6813
|
+
"dayjs": [{ category: "tooling", name: "dayjs" }],
|
|
6814
|
+
"uuid": [{ category: "tooling", name: "uuid" }],
|
|
6815
|
+
"nanoid": [{ category: "tooling", name: "nanoid" }],
|
|
6816
|
+
// CLI & Developer Tools
|
|
6817
|
+
"commander": [{ category: "tooling", name: "commander" }, { category: "category", name: "cli" }],
|
|
6818
|
+
"yargs": [{ category: "tooling", name: "yargs" }, { category: "category", name: "cli" }],
|
|
6819
|
+
"@clack/prompts": [{ category: "tooling", name: "clack" }, { category: "category", name: "cli" }],
|
|
6820
|
+
"inquirer": [{ category: "tooling", name: "inquirer" }, { category: "category", name: "cli" }],
|
|
6821
|
+
"chalk": [{ category: "tooling", name: "chalk" }],
|
|
6822
|
+
// Runtime & Languages
|
|
6823
|
+
"typescript": [{ category: "language", name: "typescript" }]
|
|
6824
|
+
};
|
|
6825
|
+
function inferPatternName(filePaths) {
|
|
6826
|
+
if (filePaths.length === 1) {
|
|
6827
|
+
const fileName = path2.basename(filePaths[0]);
|
|
6828
|
+
const nameWithoutExt = fileName.replace(/\.[^.]+$/, "");
|
|
6829
|
+
return nameWithoutExt.replace(/[-_]/g, " ").replace(/([A-Z])/g, " $1").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
6830
|
+
}
|
|
6831
|
+
const dirs = filePaths.map((p13) => path2.dirname(p13));
|
|
6832
|
+
const uniqueDirs = [...new Set(dirs)];
|
|
6833
|
+
if (uniqueDirs.length === 1 && uniqueDirs[0] !== ".") {
|
|
6834
|
+
const dirName = path2.basename(uniqueDirs[0]);
|
|
6835
|
+
return dirName.replace(/[-_]/g, " ").replace(/([A-Z])/g, " $1").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ") + " Pattern";
|
|
6836
|
+
}
|
|
6837
|
+
const fileNames = filePaths.map((p13) => path2.basename(p13).replace(/\.[^.]+$/, ""));
|
|
6838
|
+
if (fileNames.length > 0) {
|
|
6839
|
+
let commonPrefix = fileNames[0];
|
|
6840
|
+
for (const name of fileNames.slice(1)) {
|
|
6841
|
+
while (!name.startsWith(commonPrefix) && commonPrefix.length > 0) {
|
|
6842
|
+
commonPrefix = commonPrefix.slice(0, -1);
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
if (commonPrefix.length > 2) {
|
|
6846
|
+
return commonPrefix.replace(/[-_]/g, " ").replace(/([A-Z])/g, " $1").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ") + " Pattern";
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6849
|
+
return `Multi-file Pattern (${filePaths.length} files)`;
|
|
6850
|
+
}
|
|
6851
|
+
async function inferTagsFromDependencies(cwd) {
|
|
6852
|
+
const tags = [];
|
|
6853
|
+
const seenTags = /* @__PURE__ */ new Set();
|
|
6854
|
+
const packageJsonPath = path2.join(cwd, "package.json");
|
|
6855
|
+
if (!fs2.existsSync(packageJsonPath)) {
|
|
6856
|
+
return tags;
|
|
6857
|
+
}
|
|
6858
|
+
try {
|
|
6859
|
+
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
|
|
6860
|
+
const allDeps = {
|
|
6861
|
+
...packageJson.dependencies,
|
|
6862
|
+
...packageJson.devDependencies
|
|
6863
|
+
};
|
|
6864
|
+
for (const dep of Object.keys(allDeps)) {
|
|
6865
|
+
const mappedTags = LIBRARY_TAG_MAP[dep];
|
|
6866
|
+
if (mappedTags) {
|
|
6867
|
+
for (const tag of mappedTags) {
|
|
6868
|
+
const key = `${tag.category}:${tag.name}`;
|
|
6869
|
+
if (!seenTags.has(key)) {
|
|
6870
|
+
seenTags.add(key);
|
|
6871
|
+
tags.push(tag);
|
|
6872
|
+
}
|
|
6873
|
+
}
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6876
|
+
} catch {
|
|
6877
|
+
}
|
|
6878
|
+
return tags;
|
|
6879
|
+
}
|
|
6880
|
+
function inferTagsFromContent(filePaths) {
|
|
6881
|
+
const tags = [];
|
|
6882
|
+
const seenTags = /* @__PURE__ */ new Set();
|
|
6883
|
+
const addTag = (category, name) => {
|
|
6884
|
+
const key = `${category}:${name}`;
|
|
6885
|
+
if (!seenTags.has(key)) {
|
|
6886
|
+
seenTags.add(key);
|
|
6887
|
+
tags.push({ category, name });
|
|
6888
|
+
}
|
|
6889
|
+
};
|
|
6890
|
+
for (const filePath of filePaths) {
|
|
6891
|
+
const ext = path2.extname(filePath).toLowerCase();
|
|
6892
|
+
const fileName = path2.basename(filePath).toLowerCase();
|
|
6893
|
+
if (ext === ".ts" || ext === ".tsx") {
|
|
6894
|
+
addTag("language", "typescript");
|
|
6895
|
+
} else if (ext === ".js" || ext === ".jsx" || ext === ".mjs" || ext === ".cjs") {
|
|
6896
|
+
addTag("language", "javascript");
|
|
6897
|
+
} else if (ext === ".py") {
|
|
6898
|
+
addTag("language", "python");
|
|
6899
|
+
} else if (ext === ".go") {
|
|
6900
|
+
addTag("language", "go");
|
|
6901
|
+
} else if (ext === ".rs") {
|
|
6902
|
+
addTag("language", "rust");
|
|
6903
|
+
} else if (ext === ".css" || ext === ".scss" || ext === ".sass") {
|
|
6904
|
+
addTag("tooling", "css");
|
|
6905
|
+
}
|
|
6906
|
+
if (ext === ".tsx" || ext === ".jsx") {
|
|
6907
|
+
addTag("framework", "react");
|
|
6908
|
+
}
|
|
6909
|
+
if (fileName.includes(".test.") || fileName.includes(".spec.") || fileName.startsWith("test_")) {
|
|
6910
|
+
addTag("category", "testing");
|
|
6911
|
+
}
|
|
6912
|
+
if (fileName.includes("config") || fileName.startsWith(".")) {
|
|
6913
|
+
addTag("category", "configuration");
|
|
6914
|
+
}
|
|
6915
|
+
if (filePath.includes("/components/") || filePath.includes("\\components\\")) {
|
|
6916
|
+
addTag("category", "component");
|
|
6917
|
+
}
|
|
6918
|
+
if (filePath.includes("/hooks/") || filePath.includes("\\hooks\\") || fileName.startsWith("use")) {
|
|
6919
|
+
addTag("category", "hooks");
|
|
6920
|
+
}
|
|
6921
|
+
if (filePath.includes("/api/") || filePath.includes("\\api\\") || filePath.includes("/routes/")) {
|
|
6922
|
+
addTag("category", "api");
|
|
6923
|
+
}
|
|
6924
|
+
if (filePath.includes("/utils/") || filePath.includes("\\utils\\") || filePath.includes("/lib/")) {
|
|
6925
|
+
addTag("category", "utilities");
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
return tags;
|
|
6929
|
+
}
|
|
6930
|
+
async function learnCaptureCommand(paths, options) {
|
|
6931
|
+
const cwd = getWorkspacePath();
|
|
6932
|
+
const store = new PatternStore2(cwd);
|
|
6933
|
+
console.log(chalk16.cyan("\n\u{1F4F8} Capture Files as Blueprint\n"));
|
|
6934
|
+
const resolvedPaths = [];
|
|
6935
|
+
const relativePaths = [];
|
|
6936
|
+
for (const inputPath of paths) {
|
|
6937
|
+
const absolutePath = path2.isAbsolute(inputPath) ? inputPath : path2.resolve(cwd, inputPath);
|
|
6938
|
+
if (!fs2.existsSync(absolutePath)) {
|
|
6939
|
+
console.log(chalk16.red(`\u2717 File not found: ${inputPath}`));
|
|
6940
|
+
process.exit(1);
|
|
6941
|
+
}
|
|
6942
|
+
const stat = fs2.statSync(absolutePath);
|
|
6943
|
+
if (stat.isDirectory()) {
|
|
6944
|
+
const files2 = getAllFilesInDir(absolutePath);
|
|
6945
|
+
for (const file of files2) {
|
|
6946
|
+
resolvedPaths.push(file);
|
|
6947
|
+
relativePaths.push(path2.relative(cwd, file));
|
|
6948
|
+
}
|
|
6949
|
+
} else {
|
|
6950
|
+
resolvedPaths.push(absolutePath);
|
|
6951
|
+
relativePaths.push(path2.relative(cwd, absolutePath));
|
|
6952
|
+
}
|
|
6953
|
+
}
|
|
6954
|
+
if (resolvedPaths.length === 0) {
|
|
6955
|
+
console.log(chalk16.red("\u2717 No files found to capture"));
|
|
6956
|
+
process.exit(1);
|
|
6957
|
+
}
|
|
6958
|
+
console.log(chalk16.dim(`Found ${resolvedPaths.length} file(s) to capture:
|
|
6959
|
+
`));
|
|
6960
|
+
for (const relPath of relativePaths.slice(0, 10)) {
|
|
6961
|
+
console.log(chalk16.dim(` \u2022 ${relPath}`));
|
|
6962
|
+
}
|
|
6963
|
+
if (relativePaths.length > 10) {
|
|
6964
|
+
console.log(chalk16.dim(` ... and ${relativePaths.length - 10} more`));
|
|
6965
|
+
}
|
|
6966
|
+
console.log();
|
|
6967
|
+
const depTags = await inferTagsFromDependencies(cwd);
|
|
6968
|
+
const contentTags = inferTagsFromContent(relativePaths);
|
|
6969
|
+
const allInferredTags = [...depTags, ...contentTags];
|
|
6970
|
+
const seenTagKeys = /* @__PURE__ */ new Set();
|
|
6971
|
+
const uniqueTags = [];
|
|
6972
|
+
for (const tag of allInferredTags) {
|
|
6973
|
+
const key = `${tag.category}:${tag.name}`;
|
|
6974
|
+
if (!seenTagKeys.has(key)) {
|
|
6975
|
+
seenTagKeys.add(key);
|
|
6976
|
+
uniqueTags.push(tag);
|
|
6977
|
+
}
|
|
6978
|
+
}
|
|
6979
|
+
if (options.tags) {
|
|
6980
|
+
const tagPairs = options.tags.split(",").map((t) => t.trim());
|
|
6981
|
+
for (const pair of tagPairs) {
|
|
6982
|
+
const [cat, val] = pair.split(":");
|
|
6983
|
+
if (cat && val) {
|
|
6984
|
+
const key = `${cat}:${val}`;
|
|
6985
|
+
if (!seenTagKeys.has(key)) {
|
|
6986
|
+
seenTagKeys.add(key);
|
|
6987
|
+
uniqueTags.push({
|
|
6988
|
+
category: cat,
|
|
6989
|
+
name: val
|
|
6990
|
+
});
|
|
6991
|
+
}
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
}
|
|
6995
|
+
let name = options.name;
|
|
6996
|
+
if (!name) {
|
|
6997
|
+
const inferredName = inferPatternName(relativePaths);
|
|
6998
|
+
console.log(chalk16.dim(`Inferred name: "${inferredName}"`));
|
|
6999
|
+
const nameInput = await p11.text({
|
|
7000
|
+
message: "Pattern name:",
|
|
7001
|
+
placeholder: inferredName,
|
|
7002
|
+
initialValue: inferredName,
|
|
7003
|
+
validate: (value) => {
|
|
7004
|
+
if (!value || value.length < 3) return "Name must be at least 3 characters";
|
|
7005
|
+
if (value.length > 100) return "Name must be less than 100 characters";
|
|
7006
|
+
return void 0;
|
|
7007
|
+
}
|
|
7008
|
+
});
|
|
7009
|
+
if (p11.isCancel(nameInput)) {
|
|
7010
|
+
p11.cancel("Capture cancelled");
|
|
7011
|
+
process.exit(0);
|
|
7012
|
+
}
|
|
7013
|
+
name = nameInput;
|
|
7014
|
+
}
|
|
7015
|
+
let description = options.description;
|
|
7016
|
+
if (!description) {
|
|
7017
|
+
const descInput = await p11.text({
|
|
7018
|
+
message: "Description:",
|
|
7019
|
+
placeholder: "What does this pattern provide?",
|
|
7020
|
+
validate: (value) => {
|
|
7021
|
+
if (!value || value.length < 10) return "Description must be at least 10 characters";
|
|
7022
|
+
if (value.length > 500) return "Description must be less than 500 characters";
|
|
7023
|
+
return void 0;
|
|
7024
|
+
}
|
|
7025
|
+
});
|
|
7026
|
+
if (p11.isCancel(descInput)) {
|
|
7027
|
+
p11.cancel("Capture cancelled");
|
|
7028
|
+
process.exit(0);
|
|
7029
|
+
}
|
|
7030
|
+
description = descInput;
|
|
7031
|
+
}
|
|
7032
|
+
let framework = options.framework;
|
|
7033
|
+
if (!framework) {
|
|
7034
|
+
const frameworkTag = uniqueTags.find((t) => t.category === "framework");
|
|
7035
|
+
framework = frameworkTag?.name || "general";
|
|
7036
|
+
}
|
|
7037
|
+
if (uniqueTags.length > 0) {
|
|
7038
|
+
console.log(chalk16.dim("\nInferred tags:"));
|
|
7039
|
+
console.log(chalk16.dim(` ${formatTags(uniqueTags)}`));
|
|
7040
|
+
}
|
|
7041
|
+
const files = [];
|
|
7042
|
+
for (let i = 0; i < resolvedPaths.length; i++) {
|
|
7043
|
+
const absolutePath = resolvedPaths[i];
|
|
7044
|
+
const relativePath = relativePaths[i];
|
|
7045
|
+
const content = fs2.readFileSync(absolutePath, "utf-8");
|
|
7046
|
+
const ext = path2.extname(relativePath).slice(1);
|
|
7047
|
+
const languageMap = {
|
|
7048
|
+
ts: "typescript",
|
|
7049
|
+
tsx: "typescript",
|
|
7050
|
+
js: "javascript",
|
|
7051
|
+
jsx: "javascript",
|
|
7052
|
+
mjs: "javascript",
|
|
7053
|
+
cjs: "javascript",
|
|
7054
|
+
py: "python",
|
|
7055
|
+
go: "go",
|
|
7056
|
+
rs: "rust",
|
|
7057
|
+
css: "css",
|
|
7058
|
+
scss: "scss",
|
|
7059
|
+
html: "html",
|
|
7060
|
+
json: "json",
|
|
7061
|
+
yaml: "yaml",
|
|
7062
|
+
yml: "yaml",
|
|
7063
|
+
md: "markdown",
|
|
7064
|
+
mdx: "mdx",
|
|
7065
|
+
sql: "sql",
|
|
7066
|
+
sh: "bash",
|
|
7067
|
+
bash: "bash",
|
|
7068
|
+
zsh: "bash"
|
|
7069
|
+
};
|
|
7070
|
+
files.push({
|
|
7071
|
+
path: relativePath,
|
|
7072
|
+
content,
|
|
7073
|
+
language: languageMap[ext] || ext || "text"
|
|
7074
|
+
});
|
|
7075
|
+
}
|
|
7076
|
+
const languageCounts = {};
|
|
7077
|
+
for (const file of files) {
|
|
7078
|
+
languageCounts[file.language] = (languageCounts[file.language] || 0) + 1;
|
|
7079
|
+
}
|
|
7080
|
+
const primaryLanguage = Object.entries(languageCounts).sort((a, b) => b[1] - a[1])[0]?.[0] || "typescript";
|
|
7081
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7082
|
+
const contributorManager = new ContributorManager2(cwd);
|
|
7083
|
+
const contributorResult = await contributorManager.getOrCreateId();
|
|
7084
|
+
const contributorId = contributorResult.success && contributorResult.data ? contributorResult.data : void 0;
|
|
7085
|
+
const keyFiles = files.map((f) => ({
|
|
7086
|
+
path: f.path,
|
|
7087
|
+
purpose: `${f.language} file`,
|
|
7088
|
+
content: f.content
|
|
7089
|
+
}));
|
|
7090
|
+
const blueprint = {
|
|
7091
|
+
id: crypto.randomUUID(),
|
|
7092
|
+
name,
|
|
7093
|
+
description,
|
|
7094
|
+
tags: uniqueTags,
|
|
7095
|
+
stack: {
|
|
7096
|
+
framework,
|
|
7097
|
+
language: primaryLanguage,
|
|
7098
|
+
runtime: "node",
|
|
7099
|
+
packageManager: "pnpm",
|
|
7100
|
+
dependencies: [],
|
|
7101
|
+
devDependencies: []
|
|
7102
|
+
},
|
|
7103
|
+
structure: {
|
|
7104
|
+
directories: [...new Set(files.map((f) => path2.dirname(f.path)).filter((d) => d !== "."))],
|
|
7105
|
+
keyFiles
|
|
7106
|
+
},
|
|
7107
|
+
setup: {
|
|
7108
|
+
prerequisites: [],
|
|
7109
|
+
steps: [],
|
|
7110
|
+
configs: []
|
|
7111
|
+
},
|
|
7112
|
+
compatibility: {
|
|
7113
|
+
framework,
|
|
7114
|
+
frameworkVersion: ">=1.0.0",
|
|
7115
|
+
runtime: "node",
|
|
7116
|
+
runtimeVersion: ">=18.0.0",
|
|
7117
|
+
dependencies: []
|
|
7118
|
+
},
|
|
7119
|
+
metrics: {
|
|
7120
|
+
applications: 0,
|
|
7121
|
+
successes: 0,
|
|
7122
|
+
failures: 0,
|
|
7123
|
+
successRate: 0
|
|
7124
|
+
},
|
|
7125
|
+
relatedPatterns: [],
|
|
7126
|
+
isPrivate: true,
|
|
7127
|
+
contributorId,
|
|
7128
|
+
createdAt: now,
|
|
7129
|
+
updatedAt: now
|
|
7130
|
+
};
|
|
7131
|
+
if (options.dryRun) {
|
|
7132
|
+
console.log(chalk16.yellow("\n\u{1F50D} Dry Run - Would capture:\n"));
|
|
7133
|
+
console.log(chalk16.bold(`Name: ${name}`));
|
|
7134
|
+
console.log(chalk16.dim(`Description: ${description}`));
|
|
7135
|
+
console.log(chalk16.dim(`Framework: ${framework}`));
|
|
7136
|
+
console.log(chalk16.dim(`Tags: ${formatTags(uniqueTags)}`));
|
|
7137
|
+
console.log(chalk16.dim(`Files: ${files.length}`));
|
|
7138
|
+
console.log(chalk16.dim(`ID: ${blueprint.id}`));
|
|
7139
|
+
console.log(chalk16.yellow("\n\u26A0\uFE0F No changes made (dry run)"));
|
|
7140
|
+
return;
|
|
7141
|
+
}
|
|
7142
|
+
const result = await store.saveBlueprint(blueprint);
|
|
7143
|
+
if (!result.success) {
|
|
7144
|
+
console.log(chalk16.red(`
|
|
7145
|
+
\u2717 Failed to save blueprint: ${result.error}`));
|
|
7146
|
+
process.exit(1);
|
|
7147
|
+
}
|
|
7148
|
+
console.log(chalk16.green("\n\u2713 Blueprint captured successfully!\n"));
|
|
7149
|
+
console.log(chalk16.bold(`ID: ${blueprint.id}`));
|
|
7150
|
+
console.log(chalk16.dim(`Name: ${name}`));
|
|
7151
|
+
console.log(chalk16.dim(`Files: ${files.length}`));
|
|
7152
|
+
console.log(chalk16.dim(`Tags: ${formatTags(uniqueTags)}`));
|
|
7153
|
+
console.log(chalk16.dim(`
|
|
7154
|
+
To apply this pattern:`));
|
|
7155
|
+
console.log(chalk16.cyan(` pnpm workflow:learn:apply ${blueprint.id}`));
|
|
7156
|
+
console.log(chalk16.dim(`
|
|
7157
|
+
To publish to registry:`));
|
|
7158
|
+
console.log(chalk16.cyan(` pnpm workflow:learn:publish ${blueprint.id}`));
|
|
7159
|
+
}
|
|
7160
|
+
function getAllFilesInDir(dirPath) {
|
|
7161
|
+
const files = [];
|
|
7162
|
+
const entries = fs2.readdirSync(dirPath, { withFileTypes: true });
|
|
7163
|
+
for (const entry of entries) {
|
|
7164
|
+
const fullPath = path2.join(dirPath, entry.name);
|
|
7165
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
7166
|
+
continue;
|
|
7167
|
+
}
|
|
7168
|
+
if (entry.isDirectory()) {
|
|
7169
|
+
files.push(...getAllFilesInDir(fullPath));
|
|
7170
|
+
} else {
|
|
7171
|
+
files.push(fullPath);
|
|
7172
|
+
}
|
|
7173
|
+
}
|
|
7174
|
+
return files;
|
|
7175
|
+
}
|
|
6726
7176
|
|
|
6727
7177
|
// src/cli/commands/solution.ts
|
|
6728
7178
|
import chalk17 from "chalk";
|
|
@@ -7172,14 +7622,11 @@ program.command("init").description("Initialize workflow in current project").op
|
|
|
7172
7622
|
"--preset <preset>",
|
|
7173
7623
|
"Preset to use (saas, library, api, ecommerce, cms, custom)"
|
|
7174
7624
|
).option("--name <name>", "Project name").option("-y, --yes", "Skip confirmation prompts").action(initCommand);
|
|
7175
|
-
program.command("validate <type>").description("Validate branch name, commit message, or PR title").
|
|
7176
|
-
"[value]",
|
|
7177
|
-
"Value to validate (defaults to current branch/HEAD commit)"
|
|
7178
|
-
).option(
|
|
7625
|
+
program.command("validate <type> [value]").description("Validate branch name, commit message, or PR title").option(
|
|
7179
7626
|
"--suggest-on-error",
|
|
7180
7627
|
"Offer improvement suggestions on validation errors"
|
|
7181
7628
|
).action(validateCommand);
|
|
7182
|
-
program.command("config <action>
|
|
7629
|
+
program.command("config <action> [key] [value]").description("Manage workflow configuration").action(configCommand);
|
|
7183
7630
|
program.command("config:fix").description("Automatically fix common configuration validation issues").action(async () => {
|
|
7184
7631
|
const chalk18 = (await import("chalk")).default;
|
|
7185
7632
|
const { autoFixConfigFile: autoFixConfigFile2 } = await import("../config/index.js");
|
|
@@ -7244,10 +7691,11 @@ program.command("learn:record").description("Record a new pattern from a success
|
|
|
7244
7691
|
"Category (migration, security, performance, etc.)"
|
|
7245
7692
|
).option("--framework <fw>", "Framework (next, react, vue, etc.)").option("--version <ver>", "Framework version range").option("--tags <tags>", "Comma-separated tags (category:value)").option("--type <type>", "Pattern type (fix, blueprint)").action(learnRecordCommand);
|
|
7246
7693
|
program.command("learn:list").description("List recorded learning patterns").option("--type <type>", "Filter by type (fix, blueprint, all)").option("--framework <fw>", "Filter by framework").option("--tag <tag>", "Filter by tag").option("--deprecated", "Include deprecated patterns").action(learnListCommand);
|
|
7247
|
-
program.command("learn:apply <patternId>").description("Apply a pattern to the current project").
|
|
7694
|
+
program.command("learn:apply <patternId>").description("Apply a pattern to the current project").option("--framework <fw>", "Override framework").option("--version <ver>", "Override version").option("--dry-run", "Preview without applying").action(learnApplyCommand);
|
|
7695
|
+
program.command("learn:capture <paths...>").description("Capture files as a blueprint pattern with auto-inferred metadata").option("--name <name>", "Pattern name (inferred from paths if omitted)").option("--description <desc>", "Pattern description").option("--framework <fw>", "Override inferred framework").option("--tags <tags>", "Additional tags (comma-separated, e.g., 'framework:react,language:typescript')").option("--dry-run", "Preview what would be captured without saving").action(learnCaptureCommand);
|
|
7248
7696
|
program.command("learn:sync").description("Sync patterns with remote registry").option("--push", "Push local patterns to registry").option("--pull", "Pull patterns from registry").option("--dry-run", "Preview without syncing").action(learnSyncCommand);
|
|
7249
7697
|
program.command("learn:config").description("Configure learning settings").option("--enable-sync", "Enable pattern sync").option("--disable-sync", "Disable pattern sync").option("--enable-telemetry", "Enable anonymous telemetry").option("--disable-telemetry", "Disable telemetry").option("--reset-id", "Reset contributor ID").option("--show", "Show current configuration").action(learnConfigCommand);
|
|
7250
|
-
program.command("learn:deprecate <patternId> <reason>").description("Deprecate an outdated pattern").
|
|
7698
|
+
program.command("learn:deprecate <patternId> <reason>").description("Deprecate an outdated pattern").action(learnDeprecateCommand);
|
|
7251
7699
|
program.command("learn:publish [patternId]").description("Mark pattern(s) as public for syncing").option("--private", "Mark as private instead of public").option("--all", "Apply to all patterns").option("-y, --yes", "Skip confirmation prompts").action(learnPublishCommand);
|
|
7252
7700
|
program.command("learn:stats").description("Show learning statistics").action(learnStatsCommand);
|
|
7253
7701
|
program.command("learn:validate").description("Validate pattern files and optionally auto-fix common issues").option(
|
|
@@ -7259,10 +7707,10 @@ program.command("solution:capture").description("Capture a solution pattern from
|
|
|
7259
7707
|
"--category <cat>",
|
|
7260
7708
|
"Category (auth, api, database, ui, testing, deployment, integration, performance, security, other)"
|
|
7261
7709
|
).option("--keywords <kw>", "Comma-separated keywords").option("--path <path>", "Path to the solution directory").option("--anonymize", "Anonymize sensitive data in code").action(solutionCaptureCommand);
|
|
7262
|
-
program.command("solution:search <query>").description("Search for solution patterns").
|
|
7710
|
+
program.command("solution:search <query>").description("Search for solution patterns").option("--category <cat>", "Filter by category").option("--framework <fw>", "Filter by framework").option("--limit <n>", "Maximum results", "10").action(solutionSearchCommand);
|
|
7263
7711
|
program.command("solution:list").description("List all solution patterns").option("--category <cat>", "Filter by category").option("--framework <fw>", "Filter by framework").option("--deprecated", "Include deprecated solutions").option("--limit <n>", "Maximum results", "20").action(solutionListCommand);
|
|
7264
|
-
program.command("solution:apply <solutionId>").description("Apply a solution pattern to the current project").
|
|
7265
|
-
program.command("solution:deprecate <solutionId> <reason>").description("Deprecate a solution pattern").
|
|
7712
|
+
program.command("solution:apply <solutionId>").description("Apply a solution pattern to the current project").option("--output <dir>", "Output directory").option("--dry-run", "Preview without applying").option("--include-tests", "Include test files").action(solutionApplyCommand);
|
|
7713
|
+
program.command("solution:deprecate <solutionId> <reason>").description("Deprecate a solution pattern").action(solutionDeprecateCommand);
|
|
7266
7714
|
program.command("solution:stats").description("Show solution pattern statistics").action(solutionStatsCommand);
|
|
7267
7715
|
program.parse();
|
|
7268
7716
|
//# sourceMappingURL=index.js.map
|