oh-my-agent 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.

Potentially problematic release.


This version of oh-my-agent might be problematic. Click here for more details.

Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/application/DiagnoseProjectUseCase.d.ts +17 -0
  4. package/dist/application/DiagnoseProjectUseCase.d.ts.map +1 -0
  5. package/dist/application/DiagnoseProjectUseCase.js +34 -0
  6. package/dist/application/DiagnoseProjectUseCase.js.map +1 -0
  7. package/dist/application/OrganizeSkillsUseCase.d.ts +24 -0
  8. package/dist/application/OrganizeSkillsUseCase.d.ts.map +1 -0
  9. package/dist/application/OrganizeSkillsUseCase.js +57 -0
  10. package/dist/application/OrganizeSkillsUseCase.js.map +1 -0
  11. package/dist/application/SetupSkillsUseCase.d.ts +25 -0
  12. package/dist/application/SetupSkillsUseCase.d.ts.map +1 -0
  13. package/dist/application/SetupSkillsUseCase.js +58 -0
  14. package/dist/application/SetupSkillsUseCase.js.map +1 -0
  15. package/dist/application/SyncClaudeMdUseCase.d.ts +19 -0
  16. package/dist/application/SyncClaudeMdUseCase.d.ts.map +1 -0
  17. package/dist/application/SyncClaudeMdUseCase.js +62 -0
  18. package/dist/application/SyncClaudeMdUseCase.js.map +1 -0
  19. package/dist/domain/project/Project.d.ts +8 -0
  20. package/dist/domain/project/Project.d.ts.map +1 -0
  21. package/dist/domain/project/Project.js +2 -0
  22. package/dist/domain/project/Project.js.map +1 -0
  23. package/dist/domain/project/ProjectAnalyzer.d.ts +8 -0
  24. package/dist/domain/project/ProjectAnalyzer.d.ts.map +1 -0
  25. package/dist/domain/project/ProjectAnalyzer.js +87 -0
  26. package/dist/domain/project/ProjectAnalyzer.js.map +1 -0
  27. package/dist/domain/skill/Skill.d.ts +12 -0
  28. package/dist/domain/skill/Skill.d.ts.map +1 -0
  29. package/dist/domain/skill/Skill.js +2 -0
  30. package/dist/domain/skill/Skill.js.map +1 -0
  31. package/dist/domain/skill/SkillClassifier.d.ts +12 -0
  32. package/dist/domain/skill/SkillClassifier.d.ts.map +1 -0
  33. package/dist/domain/skill/SkillClassifier.js +60 -0
  34. package/dist/domain/skill/SkillClassifier.js.map +1 -0
  35. package/dist/domain/skill/SkillDomain.d.ts +12 -0
  36. package/dist/domain/skill/SkillDomain.d.ts.map +1 -0
  37. package/dist/domain/skill/SkillDomain.js +142 -0
  38. package/dist/domain/skill/SkillDomain.js.map +1 -0
  39. package/dist/index.d.ts +3 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +125 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/infrastructure/config/PathResolver.d.ts +8 -0
  44. package/dist/infrastructure/config/PathResolver.d.ts.map +1 -0
  45. package/dist/infrastructure/config/PathResolver.js +24 -0
  46. package/dist/infrastructure/config/PathResolver.js.map +1 -0
  47. package/dist/infrastructure/fs/ClaudeMdUpdater.d.ts +21 -0
  48. package/dist/infrastructure/fs/ClaudeMdUpdater.d.ts.map +1 -0
  49. package/dist/infrastructure/fs/ClaudeMdUpdater.js +101 -0
  50. package/dist/infrastructure/fs/ClaudeMdUpdater.js.map +1 -0
  51. package/dist/infrastructure/fs/LibraryScanner.d.ts +19 -0
  52. package/dist/infrastructure/fs/LibraryScanner.d.ts.map +1 -0
  53. package/dist/infrastructure/fs/LibraryScanner.js +94 -0
  54. package/dist/infrastructure/fs/LibraryScanner.js.map +1 -0
  55. package/dist/infrastructure/fs/SymlinkManager.d.ts +12 -0
  56. package/dist/infrastructure/fs/SymlinkManager.d.ts.map +1 -0
  57. package/dist/infrastructure/fs/SymlinkManager.js +111 -0
  58. package/dist/infrastructure/fs/SymlinkManager.js.map +1 -0
  59. package/package.json +55 -0
@@ -0,0 +1,12 @@
1
+ import { type Domain } from "./SkillDomain.js";
2
+ export interface ClassificationResult {
3
+ predictedDomain: Domain | "unknown";
4
+ confidence: number;
5
+ scores: Record<string, number>;
6
+ }
7
+ export declare class SkillClassifier {
8
+ classify(skillName: string, content?: string): ClassificationResult;
9
+ private tokenize;
10
+ private countMatches;
11
+ }
12
+ //# sourceMappingURL=SkillClassifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillClassifier.d.ts","sourceRoot":"","sources":["../../../src/domain/skill/SkillClassifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,qBAAa,eAAe;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB;IAsDnE,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,YAAY;CAOrB"}
@@ -0,0 +1,60 @@
1
+ import { DOMAINS, DOMAIN_KEYWORDS } from "./SkillDomain.js";
2
+ export class SkillClassifier {
3
+ classify(skillName, content) {
4
+ const tokens = this.tokenize(skillName);
5
+ // frontmatter description 추출 (1.5× 가중치 적용)
6
+ let descriptionTokens = [];
7
+ if (content) {
8
+ const descMatch = content.match(/^description:\s*(.+)$/m);
9
+ if (descMatch) {
10
+ descriptionTokens = this.tokenize(descMatch[1]);
11
+ }
12
+ // 나머지 content 토큰 추가
13
+ tokens.push(...this.tokenize(content));
14
+ }
15
+ const scores = {};
16
+ let totalScore = 0;
17
+ for (const domain of DOMAINS) {
18
+ const keywords = DOMAIN_KEYWORDS[domain];
19
+ let score = 0;
20
+ for (const { keyword, weight } of keywords) {
21
+ const keyTokens = this.tokenize(keyword);
22
+ // 일반 토큰에서 매칭
23
+ const nameMatches = this.countMatches(tokens, keyTokens);
24
+ score += nameMatches * weight;
25
+ // description 토큰에서 매칭 (1.5× 가중치)
26
+ const descMatches = this.countMatches(descriptionTokens, keyTokens);
27
+ score += descMatches * weight * 1.5;
28
+ }
29
+ scores[domain] = score;
30
+ totalScore += score;
31
+ }
32
+ if (totalScore === 0) {
33
+ return { predictedDomain: "unknown", confidence: 0, scores };
34
+ }
35
+ const bestDomain = (Object.entries(scores).sort(([, a], [, b]) => b - a)[0][0]);
36
+ const bestScore = scores[bestDomain];
37
+ const confidence = bestScore / totalScore;
38
+ return {
39
+ predictedDomain: confidence >= 0.4 ? bestDomain : "unknown",
40
+ confidence,
41
+ scores,
42
+ };
43
+ }
44
+ tokenize(text) {
45
+ return text
46
+ .toLowerCase()
47
+ .replace(/[_\-./\\]/g, " ")
48
+ .split(/\s+/)
49
+ .filter((t) => t.length > 0);
50
+ }
51
+ countMatches(tokens, keywords) {
52
+ let count = 0;
53
+ for (const keyword of keywords) {
54
+ if (tokens.includes(keyword))
55
+ count++;
56
+ }
57
+ return count;
58
+ }
59
+ }
60
+ //# sourceMappingURL=SkillClassifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillClassifier.js","sourceRoot":"","sources":["../../../src/domain/skill/SkillClassifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare const DOMAINS: readonly ["frontend", "testing", "security", "backend", "devops", "manager"];
2
+ export type Domain = (typeof DOMAINS)[number];
3
+ export interface KeywordEntry {
4
+ keyword: string;
5
+ weight: 1 | 2 | 3;
6
+ }
7
+ export declare const DOMAIN_KEYWORDS: Record<Domain, KeywordEntry[]>;
8
+ export declare const STACK_TO_SKILL: Record<string, {
9
+ domain: string;
10
+ skillName: string;
11
+ }>;
12
+ //# sourceMappingURL=SkillDomain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillDomain.d.ts","sourceRoot":"","sources":["../../../src/domain/skill/SkillDomain.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,8EAOV,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACnB;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAgH1D,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAkBhF,CAAC"}
@@ -0,0 +1,142 @@
1
+ export const DOMAINS = [
2
+ "frontend",
3
+ "testing",
4
+ "security",
5
+ "backend",
6
+ "devops",
7
+ "manager",
8
+ ];
9
+ export const DOMAIN_KEYWORDS = {
10
+ frontend: [
11
+ // weight 3 — 프레임워크 정확 매칭
12
+ { keyword: "next", weight: 3 },
13
+ { keyword: "nextjs", weight: 3 },
14
+ { keyword: "react", weight: 3 },
15
+ { keyword: "vue", weight: 3 },
16
+ { keyword: "nuxt", weight: 3 },
17
+ { keyword: "svelte", weight: 3 },
18
+ { keyword: "angular", weight: 3 },
19
+ { keyword: "vite", weight: 3 },
20
+ // weight 2 — 도구/개념
21
+ { keyword: "tailwind", weight: 2 },
22
+ { keyword: "css", weight: 2 },
23
+ { keyword: "ui", weight: 2 },
24
+ { keyword: "component", weight: 2 },
25
+ { keyword: "storybook", weight: 2 },
26
+ { keyword: "webpack", weight: 2 },
27
+ { keyword: "typescript", weight: 2 },
28
+ // weight 1 — 일반 용어
29
+ { keyword: "web", weight: 1 },
30
+ { keyword: "html", weight: 1 },
31
+ { keyword: "spa", weight: 1 },
32
+ { keyword: "ssr", weight: 1 },
33
+ { keyword: "client", weight: 1 },
34
+ ],
35
+ testing: [
36
+ { keyword: "vitest", weight: 3 },
37
+ { keyword: "jest", weight: 3 },
38
+ { keyword: "cypress", weight: 3 },
39
+ { keyword: "playwright", weight: 3 },
40
+ { keyword: "testing-library", weight: 3 },
41
+ { keyword: "mocha", weight: 3 },
42
+ { keyword: "e2e", weight: 2 },
43
+ { keyword: "unit", weight: 2 },
44
+ { keyword: "mock", weight: 2 },
45
+ { keyword: "coverage", weight: 2 },
46
+ { keyword: "assertion", weight: 2 },
47
+ { keyword: "test", weight: 1 },
48
+ { keyword: "spec", weight: 1 },
49
+ { keyword: "qa", weight: 1 },
50
+ ],
51
+ security: [
52
+ { keyword: "owasp", weight: 3 },
53
+ { keyword: "jwt", weight: 3 },
54
+ { keyword: "jose", weight: 3 },
55
+ { keyword: "oauth", weight: 3 },
56
+ { keyword: "xss", weight: 3 },
57
+ { keyword: "csrf", weight: 3 },
58
+ { keyword: "cors", weight: 2 },
59
+ { keyword: "auth", weight: 2 },
60
+ { keyword: "authentication", weight: 2 },
61
+ { keyword: "authorization", weight: 2 },
62
+ { keyword: "ssl", weight: 2 },
63
+ { keyword: "tls", weight: 2 },
64
+ { keyword: "encryption", weight: 2 },
65
+ { keyword: "security", weight: 1 },
66
+ { keyword: "permission", weight: 1 },
67
+ { keyword: "role", weight: 1 },
68
+ ],
69
+ backend: [
70
+ { keyword: "prisma", weight: 3 },
71
+ { keyword: "express", weight: 3 },
72
+ { keyword: "trpc", weight: 3 },
73
+ { keyword: "fastify", weight: 3 },
74
+ { keyword: "nestjs", weight: 3 },
75
+ { keyword: "graphql", weight: 3 },
76
+ { keyword: "rest", weight: 2 },
77
+ { keyword: "api", weight: 2 },
78
+ { keyword: "database", weight: 2 },
79
+ { keyword: "postgresql", weight: 2 },
80
+ { keyword: "mysql", weight: 2 },
81
+ { keyword: "mongodb", weight: 2 },
82
+ { keyword: "orm", weight: 2 },
83
+ { keyword: "server", weight: 1 },
84
+ { keyword: "endpoint", weight: 1 },
85
+ { keyword: "http", weight: 1 },
86
+ { keyword: "middleware", weight: 1 },
87
+ ],
88
+ devops: [
89
+ { keyword: "docker", weight: 3 },
90
+ { keyword: "kubernetes", weight: 3 },
91
+ { keyword: "k8s", weight: 3 },
92
+ { keyword: "terraform", weight: 3 },
93
+ { keyword: "github-actions", weight: 3 },
94
+ { keyword: "ci", weight: 2 },
95
+ { keyword: "cd", weight: 2 },
96
+ { keyword: "pipeline", weight: 2 },
97
+ { keyword: "deploy", weight: 2 },
98
+ { keyword: "container", weight: 2 },
99
+ { keyword: "helm", weight: 2 },
100
+ { keyword: "aws", weight: 2 },
101
+ { keyword: "gcp", weight: 2 },
102
+ { keyword: "azure", weight: 2 },
103
+ { keyword: "infra", weight: 1 },
104
+ { keyword: "devops", weight: 1 },
105
+ { keyword: "monitoring", weight: 1 },
106
+ ],
107
+ manager: [
108
+ { keyword: "agile", weight: 3 },
109
+ { keyword: "scrum", weight: 3 },
110
+ { keyword: "kanban", weight: 3 },
111
+ { keyword: "sprint", weight: 2 },
112
+ { keyword: "roadmap", weight: 2 },
113
+ { keyword: "backlog", weight: 2 },
114
+ { keyword: "milestone", weight: 2 },
115
+ { keyword: "jira", weight: 2 },
116
+ { keyword: "project", weight: 1 },
117
+ { keyword: "planning", weight: 1 },
118
+ { keyword: "meeting", weight: 1 },
119
+ { keyword: "standup", weight: 1 },
120
+ ],
121
+ };
122
+ // 기술 스택 → 스킬 매핑 테이블
123
+ export const STACK_TO_SKILL = {
124
+ next: { domain: "frontend", skillName: "next-best-practices" },
125
+ nextjs: { domain: "frontend", skillName: "next-best-practices" },
126
+ react: { domain: "frontend", skillName: "vercel-react-best-practices" },
127
+ "react-native": { domain: "frontend", skillName: "vercel-react-native-skills" },
128
+ vue: { domain: "frontend", skillName: "vue-best-practices" },
129
+ vitest: { domain: "testing", skillName: "vitest-practices" },
130
+ jest: { domain: "testing", skillName: "jest-practices" },
131
+ cypress: { domain: "testing", skillName: "e2e-testing" },
132
+ playwright: { domain: "testing", skillName: "playwright-testing" },
133
+ prisma: { domain: "backend", skillName: "prisma-best-practices" },
134
+ express: { domain: "backend", skillName: "express-api-patterns" },
135
+ trpc: { domain: "backend", skillName: "trpc-patterns" },
136
+ graphql: { domain: "backend", skillName: "graphql-api-patterns" },
137
+ jsonwebtoken: { domain: "security", skillName: "jwt-auth-practices" },
138
+ jose: { domain: "security", skillName: "jwt-auth-practices" },
139
+ docker: { domain: "devops", skillName: "docker-deployment" },
140
+ kubernetes: { domain: "devops", skillName: "kubernetes-deployment" },
141
+ };
142
+ //# sourceMappingURL=SkillDomain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillDomain.js","sourceRoot":"","sources":["../../../src/domain/skill/SkillDomain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { DiagnoseProjectUseCase } from "./application/DiagnoseProjectUseCase.js";
6
+ import { SetupSkillsUseCase } from "./application/SetupSkillsUseCase.js";
7
+ import { OrganizeSkillsUseCase } from "./application/OrganizeSkillsUseCase.js";
8
+ import { SyncClaudeMdUseCase } from "./application/SyncClaudeMdUseCase.js";
9
+ const server = new McpServer({
10
+ name: "oh-my-agent",
11
+ version: "1.0.0",
12
+ });
13
+ // ─── diagnose_project ───────────────────────────────────────────────────────
14
+ server.tool("diagnose_project", "프로젝트의 기술 스택을 분석하고 추천 AI 스킬 목록을 반환합니다.", {
15
+ projectPath: z
16
+ .string()
17
+ .optional()
18
+ .describe("분석할 프로젝트 경로 (기본값: 현재 디렉토리)"),
19
+ includeDevDeps: z
20
+ .boolean()
21
+ .optional()
22
+ .describe("devDependencies 포함 여부 (기본값: true)"),
23
+ }, async ({ projectPath, includeDevDeps }) => {
24
+ const useCase = new DiagnoseProjectUseCase();
25
+ const result = await useCase.execute({ projectPath, includeDevDeps });
26
+ return {
27
+ content: [
28
+ {
29
+ type: "text",
30
+ text: JSON.stringify(result, null, 2),
31
+ },
32
+ ],
33
+ };
34
+ });
35
+ // ─── setup_skills ────────────────────────────────────────────────────────────
36
+ server.tool("setup_skills", "지정한 스킬을 라이브러리에서 프로젝트의 .claude/skills/ 에 심볼릭 링크로 배포하고 CLAUDE.md를 업데이트합니다.", {
37
+ projectPath: z.string().describe("대상 프로젝트 경로"),
38
+ skills: z
39
+ .array(z.object({
40
+ domain: z.string().describe("스킬 도메인 (예: frontend, testing)"),
41
+ skillName: z.string().describe("스킬 파일명 (확장자 제외)"),
42
+ }))
43
+ .describe("배포할 스킬 목록"),
44
+ updateClaudeMd: z
45
+ .boolean()
46
+ .optional()
47
+ .describe("CLAUDE.md 자동 업데이트 여부 (기본값: true)"),
48
+ dryRun: z
49
+ .boolean()
50
+ .optional()
51
+ .describe("실제 변경 없이 결과만 미리보기 (기본값: false)"),
52
+ }, async ({ projectPath, skills, updateClaudeMd, dryRun }) => {
53
+ const useCase = new SetupSkillsUseCase();
54
+ const result = await useCase.execute({
55
+ projectPath,
56
+ skills,
57
+ updateClaudeMd,
58
+ dryRun,
59
+ });
60
+ return {
61
+ content: [
62
+ {
63
+ type: "text",
64
+ text: JSON.stringify(result, null, 2),
65
+ },
66
+ ],
67
+ };
68
+ });
69
+ // ─── organize_skills ─────────────────────────────────────────────────────────
70
+ server.tool("organize_skills", "라이브러리 내 스킬 파일을 분석해 오분류된 스킬을 감지하고 선택적으로 자동 이동합니다.", {
71
+ libraryPath: z
72
+ .string()
73
+ .optional()
74
+ .describe("라이브러리 경로 (기본값: ~/oh-my-agent-library)"),
75
+ autoFix: z
76
+ .boolean()
77
+ .optional()
78
+ .describe("오분류 스킬 자동 이동 여부 (기본값: false)"),
79
+ targetDomain: z
80
+ .string()
81
+ .optional()
82
+ .describe("특정 도메인만 분석 (예: frontend)"),
83
+ }, async ({ libraryPath, autoFix, targetDomain }) => {
84
+ const useCase = new OrganizeSkillsUseCase();
85
+ const result = await useCase.execute({ libraryPath, autoFix, targetDomain });
86
+ return {
87
+ content: [
88
+ {
89
+ type: "text",
90
+ text: JSON.stringify(result, null, 2),
91
+ },
92
+ ],
93
+ };
94
+ });
95
+ // ─── sync_claude_md ───────────────────────────────────────────────────────────
96
+ server.tool("sync_claude_md", ".claude/skills/ 디렉토리를 스캔해 broken 링크를 감지하고 CLAUDE.md의 oh-my-agent 마커 섹션을 동기화합니다.", {
97
+ projectPath: z.string().describe("대상 프로젝트 경로"),
98
+ createIfMissing: z
99
+ .boolean()
100
+ .optional()
101
+ .describe("CLAUDE.md가 없을 때 생성 여부 (기본값: true)"),
102
+ templateStyle: z
103
+ .enum(["minimal", "full"])
104
+ .optional()
105
+ .describe("생성 시 템플릿 스타일 (기본값: full)"),
106
+ }, async ({ projectPath, createIfMissing, templateStyle }) => {
107
+ const useCase = new SyncClaudeMdUseCase();
108
+ const result = await useCase.execute({
109
+ projectPath,
110
+ createIfMissing,
111
+ templateStyle,
112
+ });
113
+ return {
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: JSON.stringify(result, null, 2),
118
+ },
119
+ ],
120
+ };
121
+ });
122
+ // ─── 서버 시작 ────────────────────────────────────────────────────────────────
123
+ const transport = new StdioServerTransport();
124
+ await server.connect(transport);
125
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare class PathResolver {
2
+ static resolveHome(inputPath: string): string;
3
+ static getLibraryPath(): string;
4
+ static getSkillsPath(projectPath: string): string;
5
+ static getClaudeMdPath(projectPath: string): string;
6
+ static normalize(inputPath: string): string;
7
+ }
8
+ //# sourceMappingURL=PathResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PathResolver.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/config/PathResolver.ts"],"names":[],"mappings":"AAGA,qBAAa,YAAY;IACvB,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAQ7C,MAAM,CAAC,cAAc,IAAI,MAAM;IAI/B,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAIjD,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAInD,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAG5C"}
@@ -0,0 +1,24 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ export class PathResolver {
4
+ static resolveHome(inputPath) {
5
+ if (inputPath.startsWith("~/") || inputPath === "~") {
6
+ const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
7
+ return path.join(home, inputPath.slice(2));
8
+ }
9
+ return inputPath;
10
+ }
11
+ static getLibraryPath() {
12
+ return this.resolveHome("~/oh-my-agent-library");
13
+ }
14
+ static getSkillsPath(projectPath) {
15
+ return path.join(projectPath, ".claude", "skills");
16
+ }
17
+ static getClaudeMdPath(projectPath) {
18
+ return path.join(projectPath, "CLAUDE.md");
19
+ }
20
+ static normalize(inputPath) {
21
+ return path.normalize(inputPath).replace(/\\/g, "/");
22
+ }
23
+ }
24
+ //# sourceMappingURL=PathResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PathResolver.js","sourceRoot":"","sources":["../../../src/infrastructure/config/PathResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,WAAW,CAAC,SAAiB;QAClC,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,WAAmB;QACtC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,WAAmB;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,SAAiB;QAChC,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ export interface InstalledSkill {
2
+ domain: string;
3
+ skillName: string;
4
+ description?: string;
5
+ }
6
+ export interface UpdateResult {
7
+ action: "created" | "updated" | "appended" | "no_change";
8
+ addedToMd: string[];
9
+ removedFromMd: string[];
10
+ }
11
+ export declare class ClaudeMdUpdater {
12
+ private claudeMdPath;
13
+ constructor(projectPath: string);
14
+ exists(): Promise<boolean>;
15
+ read(): Promise<string>;
16
+ private buildSection;
17
+ private extractCurrentSkills;
18
+ update(skills: InstalledSkill[], createIfMissing?: boolean): Promise<UpdateResult>;
19
+ getMarkerSection(): Promise<string | null>;
20
+ }
21
+ //# sourceMappingURL=ClaudeMdUpdater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeMdUpdater.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/fs/ClaudeMdUpdater.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IACzD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAS;gBAEjB,WAAW,EAAE,MAAM;IAIzB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ7B,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,oBAAoB;IAetB,MAAM,CACV,MAAM,EAAE,cAAc,EAAE,EACxB,eAAe,UAAO,GACrB,OAAO,CAAC,YAAY,CAAC;IAgDlB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAOjD"}
@@ -0,0 +1,101 @@
1
+ import fs from "fs/promises";
2
+ import fse from "fs-extra";
3
+ import path from "path";
4
+ const MARKER_START = "<!-- oh-my-agent:skills:start -->";
5
+ const MARKER_END = "<!-- oh-my-agent:skills:end -->";
6
+ export class ClaudeMdUpdater {
7
+ claudeMdPath;
8
+ constructor(projectPath) {
9
+ this.claudeMdPath = path.join(projectPath, "CLAUDE.md");
10
+ }
11
+ async exists() {
12
+ return fse.pathExists(this.claudeMdPath);
13
+ }
14
+ async read() {
15
+ try {
16
+ return await fs.readFile(this.claudeMdPath, "utf-8");
17
+ }
18
+ catch {
19
+ return "";
20
+ }
21
+ }
22
+ buildSection(skills) {
23
+ const now = new Date().toISOString();
24
+ const lines = skills.map((s) => {
25
+ const desc = s.description ? ` — ${s.description}` : "";
26
+ return `- **${s.domain}/${s.skillName}**${desc}`;
27
+ });
28
+ return [
29
+ MARKER_START,
30
+ "## Active Skills",
31
+ "",
32
+ ...lines,
33
+ "",
34
+ "> 이 섹션은 oh-my-agent가 자동 관리합니다.",
35
+ `> 마지막 동기화: ${now}`,
36
+ MARKER_END,
37
+ ].join("\n");
38
+ }
39
+ extractCurrentSkills(content) {
40
+ const startIdx = content.indexOf(MARKER_START);
41
+ const endIdx = content.indexOf(MARKER_END);
42
+ if (startIdx === -1 || endIdx === -1)
43
+ return [];
44
+ const section = content.slice(startIdx + MARKER_START.length, endIdx);
45
+ const skillPattern = /^- \*\*([^*]+)\*\*/gm;
46
+ const skills = [];
47
+ let match;
48
+ while ((match = skillPattern.exec(section)) !== null) {
49
+ skills.push(match[1]);
50
+ }
51
+ return skills;
52
+ }
53
+ async update(skills, createIfMissing = true) {
54
+ const newSection = this.buildSection(skills);
55
+ const newSkillNames = skills.map((s) => `${s.domain}/${s.skillName}`);
56
+ const fileExists = await this.exists();
57
+ if (!fileExists) {
58
+ if (!createIfMissing) {
59
+ return { action: "no_change", addedToMd: [], removedFromMd: [] };
60
+ }
61
+ await fse.ensureDir(path.dirname(this.claudeMdPath));
62
+ await fs.writeFile(this.claudeMdPath, `# Project Instructions\n\n${newSection}\n`, "utf-8");
63
+ return { action: "created", addedToMd: newSkillNames, removedFromMd: [] };
64
+ }
65
+ const content = await this.read();
66
+ const previousSkills = this.extractCurrentSkills(content);
67
+ const startIdx = content.indexOf(MARKER_START);
68
+ const endIdx = content.indexOf(MARKER_END);
69
+ let newContent;
70
+ let action;
71
+ if (startIdx !== -1 && endIdx !== -1) {
72
+ // 마커가 있으면 교체
73
+ newContent =
74
+ content.slice(0, startIdx) +
75
+ newSection +
76
+ content.slice(endIdx + MARKER_END.length);
77
+ action = "updated";
78
+ }
79
+ else {
80
+ // 마커가 없으면 끝에 추가
81
+ newContent = content.trimEnd() + "\n\n" + newSection + "\n";
82
+ action = "appended";
83
+ }
84
+ const addedToMd = newSkillNames.filter((s) => !previousSkills.includes(s));
85
+ const removedFromMd = previousSkills.filter((s) => !newSkillNames.includes(s));
86
+ if (newContent === content) {
87
+ return { action: "no_change", addedToMd: [], removedFromMd: [] };
88
+ }
89
+ await fs.writeFile(this.claudeMdPath, newContent, "utf-8");
90
+ return { action, addedToMd, removedFromMd };
91
+ }
92
+ async getMarkerSection() {
93
+ const content = await this.read();
94
+ const startIdx = content.indexOf(MARKER_START);
95
+ const endIdx = content.indexOf(MARKER_END);
96
+ if (startIdx === -1 || endIdx === -1)
97
+ return null;
98
+ return content.slice(startIdx, endIdx + MARKER_END.length);
99
+ }
100
+ }
101
+ //# sourceMappingURL=ClaudeMdUpdater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeMdUpdater.js","sourceRoot":"","sources":["../../../src/infrastructure/fs/ClaudeMdUpdater.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface SkillFile {
2
+ domain: string;
3
+ skillName: string;
4
+ filePath: string;
5
+ content?: string;
6
+ }
7
+ export declare class LibraryScanner {
8
+ private libraryPath;
9
+ constructor(libraryPath?: string);
10
+ exists(): Promise<boolean>;
11
+ getDomains(): Promise<string[]>;
12
+ scanAll(includeContent?: boolean): Promise<SkillFile[]>;
13
+ scanDomain(domain: string, includeContent?: boolean): Promise<SkillFile[]>;
14
+ getSkillPath(domain: string, skillName: string): Promise<string>;
15
+ skillExists(domain: string, skillName: string): Promise<boolean>;
16
+ readSkillContent(domain: string, skillName: string): Promise<string | null>;
17
+ getLibraryPath(): string;
18
+ }
19
+ //# sourceMappingURL=LibraryScanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibraryScanner.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/fs/LibraryScanner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,CAAC,EAAE,MAAM;IAI1B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAY/B,OAAO,CAAC,cAAc,UAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA2BrD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,UAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAwBxE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKhE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKhE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASjF,cAAc,IAAI,MAAM;CAGzB"}