add-ai-tools 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +71 -6
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -214,8 +214,10 @@ const BITBUCKET_URL_REGEX = /^https?:\/\/(?:[^@]+@)?(?:www\.)?bitbucket\.org\/([
214
214
  * GitHub shorthand 매칭 정규식
215
215
  * 예: owner/repo
216
216
  * vercel-labs/agent-skills
217
+ * khw1031/core/skills
218
+ * owner/repo/deep/nested/path
217
219
  */
218
- const GITHUB_SHORTHAND_REGEX = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/;
220
+ const GITHUB_SHORTHAND_REGEX = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(?:\/(.+))?$/;
219
221
  /**
220
222
  * Git URL 매칭 정규식 (SSH 또는 git:// 프로토콜)
221
223
  * 예: git@github.com:owner/repo.git
@@ -308,12 +310,13 @@ function parseSource(input) {
308
310
  }
309
311
  const shorthandMatch = trimmed.match(GITHUB_SHORTHAND_REGEX);
310
312
  if (shorthandMatch) {
311
- const [, owner, repo] = shorthandMatch;
313
+ const [, owner, repo, subpath] = shorthandMatch;
312
314
  return {
313
315
  type: "github",
314
316
  url: `https://github.com/${owner}/${repo}`,
315
317
  owner,
316
318
  repo,
319
+ subpath: subpath || void 0,
317
320
  raw: input
318
321
  };
319
322
  }
@@ -987,12 +990,22 @@ const bitbucketFetcher = new BitbucketFetcher();
987
990
 
988
991
  //#endregion
989
992
  //#region src/prompts/InteractivePrompt.ts
993
+ const FILTER_THRESHOLD$1 = 15;
990
994
  /**
991
995
  * InteractivePrompt - 외부 소스 기반 설치 플로우
992
996
  *
993
997
  * 플로우: Agent → Source URL → Type 선택 → Resources 선택 → Scope → Confirm
994
998
  */
995
- var InteractivePrompt = class {
999
+ var InteractivePrompt = class InteractivePrompt {
1000
+ /**
1001
+ * 키워드로 리소스 필터링 (name, type, description, metadata.category 대상, 대소문자 무시)
1002
+ */
1003
+ static filterByKeyword(resources, keyword) {
1004
+ const lower = keyword.toLowerCase();
1005
+ return resources.filter((r) => {
1006
+ return r.name.toLowerCase().includes(lower) || r.type.toLowerCase().includes(lower) || r.description.toLowerCase().includes(lower) || r.metadata.category && r.metadata.category.toLowerCase().includes(lower);
1007
+ });
1008
+ }
996
1009
  /**
997
1010
  * Interactive 플로우 실행
998
1011
  */
@@ -1113,14 +1126,35 @@ var InteractivePrompt = class {
1113
1126
  return firstLine;
1114
1127
  }
1115
1128
  /**
1129
+ * 리소스가 많을 때 키워드 필터링 프롬프트 표시
1130
+ */
1131
+ async filterResourcesIfNeeded(resources) {
1132
+ if (resources.length <= FILTER_THRESHOLD$1) return resources;
1133
+ const { keyword } = await inquirer.prompt([{
1134
+ type: "input",
1135
+ name: "keyword",
1136
+ message: `${resources.length} resources found. Enter keyword to filter (press Enter to show all):`
1137
+ }]);
1138
+ const trimmed = keyword.trim();
1139
+ if (!trimmed) return resources;
1140
+ const filtered = InteractivePrompt.filterByKeyword(resources, trimmed);
1141
+ if (filtered.length === 0) {
1142
+ console.log(`No resources matched "${trimmed}". Showing all resources.`);
1143
+ return resources;
1144
+ }
1145
+ console.log(`Filtered to ${filtered.length} resource(s).`);
1146
+ return filtered;
1147
+ }
1148
+ /**
1116
1149
  * 리소스 선택 (가져온 리소스 목록에서)
1117
1150
  */
1118
1151
  async selectResources(availableResources, types) {
1119
- const filteredResources = availableResources.filter((r) => types.includes(r.type));
1152
+ let filteredResources = availableResources.filter((r) => types.includes(r.type));
1120
1153
  if (filteredResources.length === 0) {
1121
1154
  console.log("\nNo resources found for selected types.");
1122
1155
  return [];
1123
1156
  }
1157
+ filteredResources = await this.filterResourcesIfNeeded(filteredResources);
1124
1158
  const { resources } = await inquirer.prompt([{
1125
1159
  type: "checkbox",
1126
1160
  name: "resources",
@@ -1887,12 +1921,13 @@ const commandHandler = new CommandHandler();
1887
1921
 
1888
1922
  //#endregion
1889
1923
  //#region src/prompts/ZipPrompt.ts
1924
+ const FILTER_THRESHOLD = 15;
1890
1925
  /**
1891
1926
  * ZipPrompt - ZIP 내보내기용 선택 플로우
1892
1927
  *
1893
1928
  * 플로우: Types → Resources → Confirm
1894
1929
  */
1895
- var ZipPrompt = class {
1930
+ var ZipPrompt = class ZipPrompt {
1896
1931
  /**
1897
1932
  * ZIP 플로우 실행
1898
1933
  */
@@ -1937,14 +1972,44 @@ var ZipPrompt = class {
1937
1972
  return selected;
1938
1973
  }
1939
1974
  /**
1975
+ * 키워드로 리소스 필터링 (name, type, description, metadata.category 대상, 대소문자 무시)
1976
+ */
1977
+ static filterByKeyword(resources, keyword) {
1978
+ const lower = keyword.toLowerCase();
1979
+ return resources.filter((r) => {
1980
+ return r.name.toLowerCase().includes(lower) || r.type.toLowerCase().includes(lower) || r.description.toLowerCase().includes(lower) || r.metadata.category && r.metadata.category.toLowerCase().includes(lower);
1981
+ });
1982
+ }
1983
+ /**
1984
+ * 리소스가 많을 때 키워드 필터링 프롬프트 표시
1985
+ */
1986
+ async filterResourcesIfNeeded(resources) {
1987
+ if (resources.length <= FILTER_THRESHOLD) return resources;
1988
+ const { keyword } = await inquirer.prompt([{
1989
+ type: "input",
1990
+ name: "keyword",
1991
+ message: `${resources.length} resources found. Enter keyword to filter (press Enter to show all):`
1992
+ }]);
1993
+ const trimmed = keyword.trim();
1994
+ if (!trimmed) return resources;
1995
+ const filtered = ZipPrompt.filterByKeyword(resources, trimmed);
1996
+ if (filtered.length === 0) {
1997
+ console.log(`No resources matched "${trimmed}". Showing all resources.`);
1998
+ return resources;
1999
+ }
2000
+ console.log(`Filtered to ${filtered.length} resource(s).`);
2001
+ return filtered;
2002
+ }
2003
+ /**
1940
2004
  * 리소스 복수 선택
1941
2005
  */
1942
2006
  async selectResources(availableResources, types) {
1943
- const filteredResources = availableResources.filter((r) => types.includes(r.type));
2007
+ let filteredResources = availableResources.filter((r) => types.includes(r.type));
1944
2008
  if (filteredResources.length === 0) {
1945
2009
  console.log("\nNo resources found for selected types.");
1946
2010
  return [];
1947
2011
  }
2012
+ filteredResources = await this.filterResourcesIfNeeded(filteredResources);
1948
2013
  const { selected } = await inquirer.prompt([{
1949
2014
  type: "checkbox",
1950
2015
  name: "selected",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-ai-tools",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Universal AI agent resource installer CLI",
5
5
  "type": "module",
6
6
  "bin": {