@haema/cli 0.8.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.
Files changed (54) hide show
  1. package/README.md +258 -0
  2. package/dist/auth.js +30 -0
  3. package/dist/auth.js.map +1 -0
  4. package/dist/discoverClaudeFiles.js +132 -0
  5. package/dist/discoverClaudeFiles.js.map +1 -0
  6. package/dist/index.js +29 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/mcp/install.js +353 -0
  9. package/dist/mcp/install.js.map +1 -0
  10. package/dist/mcp/mcpClient.js +55 -0
  11. package/dist/mcp/mcpClient.js.map +1 -0
  12. package/dist/mcp/resolveProjectId.js +27 -0
  13. package/dist/mcp/resolveProjectId.js.map +1 -0
  14. package/dist/mcp/server.js +344 -0
  15. package/dist/mcp/server.js.map +1 -0
  16. package/dist/mcp/tools/addTask.js +15 -0
  17. package/dist/mcp/tools/addTask.js.map +1 -0
  18. package/dist/mcp/tools/applyHooks.js +110 -0
  19. package/dist/mcp/tools/applyHooks.js.map +1 -0
  20. package/dist/mcp/tools/brief.js +166 -0
  21. package/dist/mcp/tools/brief.js.map +1 -0
  22. package/dist/mcp/tools/createFolder.js +11 -0
  23. package/dist/mcp/tools/createFolder.js.map +1 -0
  24. package/dist/mcp/tools/finishTask.js +16 -0
  25. package/dist/mcp/tools/finishTask.js.map +1 -0
  26. package/dist/mcp/tools/getTask.js +31 -0
  27. package/dist/mcp/tools/getTask.js.map +1 -0
  28. package/dist/mcp/tools/listTasks.js +27 -0
  29. package/dist/mcp/tools/listTasks.js.map +1 -0
  30. package/dist/mcp/tools/loadSkill.js +8 -0
  31. package/dist/mcp/tools/loadSkill.js.map +1 -0
  32. package/dist/mcp/tools/logSession.js +13 -0
  33. package/dist/mcp/tools/logSession.js.map +1 -0
  34. package/dist/mcp/tools/recall.js +23 -0
  35. package/dist/mcp/tools/recall.js.map +1 -0
  36. package/dist/mcp/tools/signin.js +111 -0
  37. package/dist/mcp/tools/signin.js.map +1 -0
  38. package/dist/mcp/tools/signout.js +11 -0
  39. package/dist/mcp/tools/signout.js.map +1 -0
  40. package/dist/mcp/tools/startTask.js +21 -0
  41. package/dist/mcp/tools/startTask.js.map +1 -0
  42. package/dist/mcp/tools/updateTask.js +9 -0
  43. package/dist/mcp/tools/updateTask.js.map +1 -0
  44. package/dist/mcp/tools/uploadPrompt.js +32 -0
  45. package/dist/mcp/tools/uploadPrompt.js.map +1 -0
  46. package/dist/mcp/tools/whoami.js +13 -0
  47. package/dist/mcp/tools/whoami.js.map +1 -0
  48. package/dist/openBrowser.js +15 -0
  49. package/dist/openBrowser.js.map +1 -0
  50. package/dist/readClaudeFile.js +16 -0
  51. package/dist/readClaudeFile.js.map +1 -0
  52. package/dist/scanLimits.js +15 -0
  53. package/dist/scanLimits.js.map +1 -0
  54. package/package.json +36 -0
@@ -0,0 +1,166 @@
1
+ import { execSync } from "node:child_process";
2
+ import { mcpGet } from "../mcpClient.js";
3
+ export async function handleBrief(projectId, config) {
4
+ const data = await mcpGet(config, "/api/memory/brief", { projectId });
5
+ if (!data.ok)
6
+ throw new Error(data.error);
7
+ const b = data.brief;
8
+ const commits = b.cwd ? getRecentCommits(b.cwd) : [];
9
+ const lines = [];
10
+ // 폴더 id → name 맵 (add_task 시 참조용)
11
+ const folderMap = new Map((b.folders ?? []).map((f) => [f.id, f.name]));
12
+ // 최근 작업 흐름: AI 요약 + 완료 태스크 + 커밋 → Claude가 bullet 3개로 합성
13
+ const flowContext = [];
14
+ if (b.aiSummary?.summary) {
15
+ flowContext.push(`프로젝트 AI 요약: ${b.aiSummary.summary}`);
16
+ }
17
+ const recentDoneForFlow = b.recentlyDone.slice(0, 3);
18
+ if (recentDoneForFlow.length > 0) {
19
+ flowContext.push("최근 완료 태스크: " + recentDoneForFlow.map((t) => t.title).join(", "));
20
+ }
21
+ if (commits.length > 0) {
22
+ flowContext.push("최근 커밋: " + commits.map((c) => c.replace(/^[a-f0-9]+ /, "")).join(" / "));
23
+ }
24
+ if (flowContext.length > 0) {
25
+ lines.push(`[다음 정보를 바탕으로 "최근 작업 흐름:" bullet 3개를 작성하세요]`);
26
+ lines.push(...flowContext);
27
+ lines.push("");
28
+ }
29
+ // 프로젝트 상태 요약
30
+ const statusCtx = [];
31
+ const recentDone = b.recentlyDone.slice(0, 3);
32
+ if (recentDone.length > 0) {
33
+ statusCtx.push(`최근 완료: ${recentDone.map((t) => t.title).join(", ")}`);
34
+ const withDecisions = recentDone.filter((t) => t.keyDecisions.length > 0);
35
+ for (const t of withDecisions) {
36
+ statusCtx.push(` #${t.seq} 핵심 결정: ${t.keyDecisions.join(" / ")}`);
37
+ }
38
+ }
39
+ if (b.aiSummary?.warnings?.length) {
40
+ statusCtx.push(`주의: ${b.aiSummary.warnings.join(", ")}`);
41
+ }
42
+ const activeFolders = (b.folders ?? []).filter((f) => f.taskCount > 0);
43
+ if (activeFolders.length > 0) {
44
+ statusCtx.push(`폴더: ${activeFolders.map((f) => `${f.name}(${f.taskCount}개)`).join(", ")}`);
45
+ }
46
+ lines.push(`[아래 태스크 정보를 바탕으로 현재 프로젝트 상태를 2~3줄 bullet으로 요약하세요 (각 줄 "- " 로 시작)]`);
47
+ lines.push(...statusCtx);
48
+ lines.push("");
49
+ // 진행 중·대기 태스크 목록 (에이전트가 현재 상태 파악용)
50
+ if (b.inProgressTasks.length > 0) {
51
+ lines.push(`진행 중인 태스크:`);
52
+ for (const t of b.inProgressTasks) {
53
+ const folder = t.folderId ? folderMap.get(t.folderId) : null;
54
+ lines.push(`- #${t.seq} ${t.title}${t.module ? ` [${t.module}]` : ""}${folder ? ` (${folder})` : ""}`);
55
+ }
56
+ lines.push("");
57
+ }
58
+ if (b.pendingTasks.length > 0) {
59
+ lines.push(`대기 중인 태스크:`);
60
+ for (const t of b.pendingTasks) {
61
+ const folder = t.folderId ? folderMap.get(t.folderId) : null;
62
+ lines.push(`- #${t.seq} ${t.title}${t.module ? ` [${t.module}]` : ""}${folder ? ` (${folder})` : ""}`);
63
+ }
64
+ lines.push("");
65
+ }
66
+ // 폴더 목록 (add_task 시 folderId 참조용)
67
+ if (activeFolders.length > 0) {
68
+ lines.push(`폴더 목록 (add_task 시 folderId 사용):`);
69
+ for (const f of activeFolders) {
70
+ lines.push(`- ${f.name} (id: ${f.id}, 태스크 ${f.taskCount}개)`);
71
+ }
72
+ lines.push("");
73
+ }
74
+ lines.push(`추천 태스크:`);
75
+ // DB AI 추천 최대 3개 먼저 출력
76
+ const aiRecs = b.recommendedNextTasks ?? [];
77
+ let recNum = 1;
78
+ for (const rec of aiRecs.slice(0, 3)) {
79
+ lines.push(`${recNum}) ${rec.title}${rec.reason ? ` — ${rec.reason}` : ""}`);
80
+ recNum++;
81
+ }
82
+ // DB 추천이 3개 미만이면 대기 태스크·커밋 컨텍스트로 나머지 채우도록 지시
83
+ if (recNum <= 3) {
84
+ const recContext = [];
85
+ if (b.pendingTasks.length > 0) {
86
+ recContext.push("대기 중인 태스크: " + b.pendingTasks.slice(0, 5).map((t) => `#${t.seq} ${t.title}`).join(", "));
87
+ }
88
+ if (recentDone.length > 0) {
89
+ recContext.push("최근 완료 태스크: " + recentDone.map((t) => t.title).join(", "));
90
+ }
91
+ if (commits.length > 0) {
92
+ recContext.push("최근 커밋: " + commits.map((c) => c.replace(/^[a-f0-9]+ /, "")).join(" / "));
93
+ }
94
+ if (recContext.length > 0) {
95
+ lines.push(`[위 정보를 바탕으로 ${recNum})~3) 추천 태스크를 "N) 태스크명" 형식으로 각 한 줄씩 추가하세요]`);
96
+ lines.push(...recContext);
97
+ }
98
+ else if (recNum === 1) {
99
+ lines.push("등록된 태스크나 이전 작업이 없어요. 하려는 작업을 말씀해주세요.");
100
+ }
101
+ }
102
+ // AI 프로젝트 맥락 (성장형 plain text 기억)
103
+ if (b.memoryContext) {
104
+ lines.push(`\nAI 프로젝트 맥락 (자기학습 기억):\n${b.memoryContext}`);
105
+ }
106
+ // 장기 기억 (LONG_TERM) 태스크
107
+ if (b.longTermTasks && b.longTermTasks.length > 0) {
108
+ lines.push(`\n장기 기억 (영구 보존):`);
109
+ for (const t of b.longTermTasks) {
110
+ const ago = t.lastAccessedAt ? daysAgo(t.lastAccessedAt) : null;
111
+ lines.push(`- #${t.seq} ${t.title}${ago !== null ? ` [${ago}일 전 접근]` : ""}`);
112
+ }
113
+ }
114
+ // 최근 AI 메모리 인사이트
115
+ if (b.latestReflection) {
116
+ const r = b.latestReflection;
117
+ if (r.contextSummary || (r.insights && r.insights.length > 0)) {
118
+ lines.push(`\nAI 메모리 분석:`);
119
+ if (r.contextSummary)
120
+ lines.push(`프로젝트 맥락: ${r.contextSummary}`);
121
+ for (const ins of (r.insights ?? []).slice(0, 3)) {
122
+ const label = ins.type === "pattern" ? "패턴" : ins.type === "risk" ? "위험" : "인사이트";
123
+ lines.push(`- [${label}] ${ins.text}`);
124
+ }
125
+ }
126
+ }
127
+ // 프로젝트 스킬 (folder별 그룹핑)
128
+ if (b.customSkills && b.customSkills.length > 0) {
129
+ const byFolder = new Map();
130
+ for (const s of b.customSkills) {
131
+ const arr = byFolder.get(s.folder) ?? [];
132
+ arr.push(s);
133
+ byFolder.set(s.folder, arr);
134
+ }
135
+ lines.push(`\n프로젝트 커스텀 스킬 (load_skill로 로드):`);
136
+ for (const [folder, skills] of byFolder) {
137
+ lines.push(`[${folder}]`);
138
+ for (const s of skills) {
139
+ lines.push(`- ${s.slug}: ${s.name} — ${s.contextHint}`);
140
+ }
141
+ }
142
+ }
143
+ // 스킬 제안 (패턴 감지됨)
144
+ if (b.skillSuggestions && b.skillSuggestions.length > 0) {
145
+ lines.push(`\n💡 스킬 제안 (반복 패턴 감지됨):`);
146
+ for (const s of b.skillSuggestions) {
147
+ lines.push(`- "${s.name}": ${s.description} [폴더: ${s.folder}]`);
148
+ lines.push(` 근거: ${s.patternSummary}`);
149
+ lines.push(` → propose_skill(name="${s.name}", folder="${s.folder}", ...)로 등록하세요.`);
150
+ }
151
+ }
152
+ return lines.join("\n");
153
+ }
154
+ function daysAgo(isoDate) {
155
+ return Math.floor((Date.now() - new Date(isoDate).getTime()) / (1000 * 60 * 60 * 24));
156
+ }
157
+ function getRecentCommits(cwd) {
158
+ try {
159
+ const out = execSync("git log --oneline --no-merges -10", { cwd, encoding: "utf8", timeout: 3000 });
160
+ return out.trim().split("\n").filter(Boolean);
161
+ }
162
+ catch {
163
+ return [];
164
+ }
165
+ }
166
+ //# sourceMappingURL=brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brief.js","sourceRoot":"","sources":["../../../src/mcp/tools/brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { mcpPost } from "../mcpClient.js";
2
+ export async function handleCreateFolder(args, projectId, config) {
3
+ const data = await mcpPost(config, "/api/memory/folders", {
4
+ projectId,
5
+ name: args.name,
6
+ });
7
+ if (!data.ok)
8
+ throw new Error(data.error);
9
+ return `폴더 생성됨: "${data.folder.name}" (id: ${data.folder.id})`;
10
+ }
11
+ //# sourceMappingURL=createFolder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFolder.js","sourceRoot":"","sources":["../../../src/mcp/tools/createFolder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAsB,EACtB,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAuB,MAAM,EAAE,qBAAqB,EAAE;QAC9E,SAAS;QACT,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,YAAY,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC;AACjE,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { mcpPost } from "../mcpClient.js";
2
+ export async function handleFinishTask(args, projectId, config) {
3
+ const data = await mcpPost(config, `/api/memory/tasks/${args.taskSeq}/finish`, {
4
+ projectId,
5
+ summary: args.summary,
6
+ aiTool: args.aiTool,
7
+ keyDecisions: args.keyDecisions,
8
+ outcome: args.outcome,
9
+ });
10
+ if (!data.ok)
11
+ throw new Error(data.error);
12
+ const decisionsNote = args.keyDecisions?.length ? ` 핵심 결정 ${args.keyDecisions.length}개 저장됨.` : "";
13
+ const outcomeNote = args.outcome ? " outcome 저장됨." : "";
14
+ return `태스크 완료: #${data.task.seq} "${data.task.title}" → DONE${decisionsNote}${outcomeNote}`;
15
+ }
16
+ //# sourceMappingURL=finishTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finishTask.js","sourceRoot":"","sources":["../../../src/mcp/tools/finishTask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAsG,EACtG,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAqB,MAAM,EAAE,qBAAqB,IAAI,CAAC,OAAO,SAAS,EAAE;QACjG,SAAS;QACT,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,YAAY,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAClG,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,OAAO,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,WAAW,aAAa,GAAG,WAAW,EAAE,CAAC;AAC/F,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { mcpGet } from "../mcpClient.js";
2
+ const STATUS_LABEL = {
3
+ PENDING: "대기",
4
+ IN_PROGRESS: "진행 중",
5
+ DONE: "완료",
6
+ CANCELLED: "취소됨",
7
+ };
8
+ export async function handleGetTask(args, projectId, config) {
9
+ const data = await mcpGet(config, `/api/memory/tasks/${args.taskSeq}`, { projectId });
10
+ if (!data.ok)
11
+ throw new Error(data.error);
12
+ const t = data.task;
13
+ const lines = [
14
+ `#${t.seq} ${t.title}`,
15
+ `상태: ${STATUS_LABEL[t.status] ?? t.status}`,
16
+ ];
17
+ if (t.module)
18
+ lines.push(`모듈: ${t.module}`);
19
+ if (t.priority)
20
+ lines.push(`우선순위: ${t.priority}`);
21
+ if (t.folderId)
22
+ lines.push(`폴더: ${t.folderId}`);
23
+ if (t.description)
24
+ lines.push(`\n설명:\n${t.description}`);
25
+ if (t.outcome)
26
+ lines.push(`\n결과:\n${t.outcome}`);
27
+ if (t.keyDecisions.length > 0)
28
+ lines.push(`\n핵심 결정:\n${t.keyDecisions.map((d) => `- ${d}`).join("\n")}`);
29
+ return lines.join("\n");
30
+ }
31
+ //# sourceMappingURL=getTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTask.js","sourceRoot":"","sources":["../../../src/mcp/tools/getTask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAkBzC,MAAM,YAAY,GAA2B;IAC3C,OAAO,EAAE,IAAI;IACb,WAAW,EAAE,MAAM;IACnB,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,KAAK;CACjB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAyB,EACzB,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAc,MAAM,EAAE,qBAAqB,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACnG,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IACpB,MAAM,KAAK,GAAa;QACtB,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE;QACtB,OAAO,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;KAC5C,CAAC;IACF,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEzG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { mcpGet } from "../mcpClient.js";
2
+ const STATUS_EMOJI = {
3
+ PENDING: "📋",
4
+ IN_PROGRESS: "🔄",
5
+ DONE: "✅",
6
+ CANCELLED: "❌",
7
+ };
8
+ export async function handleListTasks(args, projectId, config) {
9
+ const params = { projectId };
10
+ if (args.status)
11
+ params.status = args.status;
12
+ if (args.module)
13
+ params.module = args.module;
14
+ const data = await mcpGet(config, "/api/memory/tasks", params);
15
+ if (!data.ok)
16
+ throw new Error(data.error);
17
+ if (data.tasks.length === 0)
18
+ return "태스크가 없어요.";
19
+ const lines = data.tasks.map((t) => {
20
+ const emoji = STATUS_EMOJI[t.status] ?? "•";
21
+ const mod = t.module ? ` [${t.module}]` : "";
22
+ const desc = t.description ? `\n ${t.description}` : "";
23
+ return `${emoji} #${t.seq} ${t.title}${mod} (priority: ${t.priority})${desc}`;
24
+ });
25
+ return `태스크 목록 (${data.tasks.length}개):\n\n${lines.join("\n")}`;
26
+ }
27
+ //# sourceMappingURL=listTasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listTasks.js","sourceRoot":"","sources":["../../../src/mcp/tools/listTasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAazC,MAAM,YAAY,GAA2B;IAC3C,OAAO,EAAE,IAAI;IACb,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,GAAG;IACT,SAAS,EAAE,GAAG;CACf,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAA0C,EAC1C,SAAiB,EACjB,MAAiB;IAEjB,MAAM,MAAM,GAA2B,EAAE,SAAS,EAAE,CAAC;IACrD,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC7C,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE7C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAe,MAAM,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAEhD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;QAC5C,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,GAAG,eAAe,CAAC,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,OAAO,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { mcpGet } from "../mcpClient.js";
2
+ export async function handleLoadSkill(args, projectId, config) {
3
+ const data = await mcpGet(config, `/api/skills/${args.slug}`, { projectId });
4
+ if (!data.ok)
5
+ throw new Error(data.error);
6
+ return `# Skill: ${data.name}\n> ${data.contextHint}\n\n${data.content}`;
7
+ }
8
+ //# sourceMappingURL=loadSkill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadSkill.js","sourceRoot":"","sources":["../../../src/mcp/tools/loadSkill.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAMzC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAsB,EACtB,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAgB,MAAM,EAAE,eAAe,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5F,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,YAAY,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,WAAW,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { mcpPost } from "../mcpClient.js";
2
+ export async function handleLogSession(args, projectId, config, sessionId) {
3
+ const data = await mcpPost(config, "/api/memory/sessions", {
4
+ projectId,
5
+ summary: args.summary,
6
+ aiTool: args.aiTool ?? "unknown",
7
+ sessionId,
8
+ });
9
+ if (!data.ok)
10
+ throw new Error(data.error);
11
+ return `세션 로그 저장됐어요 (id: ${data.sessionLog.id})`;
12
+ }
13
+ //# sourceMappingURL=logSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSession.js","sourceRoot":"","sources":["../../../src/mcp/tools/logSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA0C,EAC1C,SAAiB,EACjB,MAAiB,EACjB,SAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAqB,MAAM,EAAE,sBAAsB,EAAE;QAC7E,SAAS;QACT,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;QAChC,SAAS;KACV,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,oBAAoB,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC;AACnD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { mcpPost } from "../mcpClient.js";
2
+ export async function handleRecall(args, projectId, config) {
3
+ const data = await mcpPost(config, "/api/memory/thoughts/search", {
4
+ projectId,
5
+ query: args.query,
6
+ limit: args.limit ?? 10,
7
+ });
8
+ if (!data.ok)
9
+ throw new Error(data.error);
10
+ if (data.results.length === 0)
11
+ return "관련된 기억을 찾지 못했어요.";
12
+ const lines = data.results.map((r) => {
13
+ const date = new Date(r.doneAt ?? r.createdAt).toLocaleDateString("ko-KR");
14
+ const moduleTag = r.module ? ` [${r.module}]` : "";
15
+ const header = `#${r.seq} ${r.title}${moduleTag} (${date})`;
16
+ if (r.keyDecisions.length === 0)
17
+ return header;
18
+ const decisions = r.keyDecisions.map((d) => ` • ${d}`).join("\n");
19
+ return `${header}\n${decisions}`;
20
+ });
21
+ return `검색 결과 (${data.results.length}개):\n\n${lines.join("\n\n")}`;
22
+ }
23
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.js","sourceRoot":"","sources":["../../../src/mcp/tools/recall.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAa1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAuC,EACvC,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAiB,MAAM,EAAE,6BAA6B,EAAE;QAChF,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAEzD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC3E,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,SAAS,KAAK,IAAI,GAAG,CAAC;QAC5D,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QAC/C,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,OAAO,GAAG,MAAM,KAAK,SAAS,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,UAAU,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AACrE,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { createServer } from "node:http";
3
+ import { authFilePath, writeAuth } from "../../auth.js";
4
+ import { openBrowser } from "../../openBrowser.js";
5
+ const DEFAULT_APP_URL = "https://haema.jocodingax.ai";
6
+ const PORT_RANGE_START = 5180;
7
+ const PORT_RANGE_END = 5189;
8
+ const TIMEOUT_MS = 120_000;
9
+ export async function handleSignin(args) {
10
+ const appUrl = stripTrailingSlash(args.appUrl ?? process.env.HAEMA_APP_URL ?? DEFAULT_APP_URL);
11
+ if (process.env.MOCK_AUTH === "true") {
12
+ await writeAuth({
13
+ appUrl,
14
+ apiKey: `haema_mock_${randomBytes(16).toString("hex")}`,
15
+ email: "dev@mock.local",
16
+ signedInAt: new Date().toISOString(),
17
+ });
18
+ return `🛠 Mock 로그인 완료 (MOCK_AUTH=true)\n자격증명 저장: ${authFilePath()}`;
19
+ }
20
+ const state = randomBytes(16).toString("hex");
21
+ const { port, server, resultPromise } = await startCallbackServer(state);
22
+ const callback = `http://127.0.0.1:${port}/callback`;
23
+ const signinUrl = `${appUrl}/cli/signin?callback=${encodeURIComponent(callback)}&state=${state}`;
24
+ openBrowser(signinUrl);
25
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("TIMEOUT")), TIMEOUT_MS));
26
+ let result;
27
+ try {
28
+ result = await Promise.race([resultPromise, timeoutPromise]);
29
+ }
30
+ catch (e) {
31
+ server.close();
32
+ const msg = e instanceof Error ? e.message : String(e);
33
+ if (msg === "TIMEOUT") {
34
+ return `로그인 대기 시간이 초과됐어요. 아래 URL을 직접 브라우저에서 열고 다시 시도해주세요:\n${signinUrl}`;
35
+ }
36
+ throw e;
37
+ }
38
+ finally {
39
+ server.close();
40
+ }
41
+ await writeAuth({
42
+ appUrl,
43
+ apiKey: result.token,
44
+ email: result.email,
45
+ signedInAt: new Date().toISOString(),
46
+ });
47
+ const who = result.email ? ` (${result.email})` : "";
48
+ return `로그인 성공${who}\n자격증명 저장: ${authFilePath()}`;
49
+ }
50
+ function stripTrailingSlash(s) {
51
+ return s.endsWith("/") ? s.slice(0, -1) : s;
52
+ }
53
+ async function startCallbackServer(expectedState) {
54
+ let resolveResult;
55
+ let rejectResult;
56
+ const resultPromise = new Promise((res, rej) => {
57
+ resolveResult = res;
58
+ rejectResult = rej;
59
+ });
60
+ const server = createServer((req, res) => {
61
+ if (!req.url) {
62
+ res.statusCode = 400;
63
+ res.end();
64
+ return;
65
+ }
66
+ const u = new URL(req.url, "http://127.0.0.1");
67
+ if (u.pathname !== "/callback") {
68
+ res.statusCode = 404;
69
+ res.end();
70
+ return;
71
+ }
72
+ const token = u.searchParams.get("token");
73
+ const state = u.searchParams.get("state");
74
+ const email = u.searchParams.get("email") ?? undefined;
75
+ if (!token || state !== expectedState) {
76
+ res.statusCode = 400;
77
+ res.setHeader("content-type", "text/html; charset=utf-8");
78
+ res.end(htmlPage("로그인 실패", "유효하지 않은 응답이에요. 다시 시도해주세요."));
79
+ rejectResult(new Error("invalid callback"));
80
+ return;
81
+ }
82
+ res.setHeader("content-type", "text/html; charset=utf-8");
83
+ res.end(htmlPage("로그인 완료", "이 창은 닫아도 돼요."));
84
+ resolveResult({ token, email });
85
+ });
86
+ const port = await listenFirstAvailable(server);
87
+ return { port, server, resultPromise };
88
+ }
89
+ async function listenFirstAvailable(server) {
90
+ let lastErr;
91
+ for (let p = PORT_RANGE_START; p <= PORT_RANGE_END; p++) {
92
+ try {
93
+ await new Promise((resolve, reject) => {
94
+ server.once("error", (e) => { server.removeAllListeners("listening"); reject(e); });
95
+ server.once("listening", () => { server.removeAllListeners("error"); resolve(); });
96
+ server.listen(p, "127.0.0.1");
97
+ });
98
+ return p;
99
+ }
100
+ catch (e) {
101
+ lastErr = e instanceof Error ? e : new Error(String(e));
102
+ }
103
+ }
104
+ throw new Error(`사용 가능한 포트가 없어요 (${PORT_RANGE_START}-${PORT_RANGE_END}): ${lastErr?.message ?? ""}`);
105
+ }
106
+ function htmlPage(title, body) {
107
+ return `<!doctype html><html lang="ko"><head><meta charset="utf-8"><title>${title}</title>
108
+ <style>body{font-family:-apple-system,system-ui,sans-serif;display:grid;place-items:center;height:100vh;margin:0;background:#0a0a0a;color:#e5e5e5}div{text-align:center;max-width:420px;padding:24px}h1{margin:0 0 12px;font-weight:500;font-size:22px}p{color:#888;line-height:1.5;margin:0}</style>
109
+ </head><body><div><h1>${title}</h1><p>${body}</p></div></body></html>`;
110
+ }
111
+ //# sourceMappingURL=signin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signin.js","sourceRoot":"","sources":["../../../src/mcp/tools/signin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { authFilePath, readAuth } from "../../auth.js";
3
+ export async function handleSignout() {
4
+ const auth = await readAuth();
5
+ if (!auth)
6
+ return "이미 로그아웃 상태예요.";
7
+ await fs.rm(authFilePath());
8
+ const who = auth.email ? ` (${auth.email})` : "";
9
+ return `로그아웃 완료${who}`;
10
+ }
11
+ //# sourceMappingURL=signout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signout.js","sourceRoot":"","sources":["../../../src/mcp/tools/signout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,eAAe,CAAC;IAClC,MAAM,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,OAAO,UAAU,GAAG,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { mcpPost } from "../mcpClient.js";
2
+ export async function handleStartTask(args, projectId, config) {
3
+ const data = await mcpPost(config, "/api/memory/tasks/start", {
4
+ projectId,
5
+ title: args.title,
6
+ description: args.description,
7
+ module: args.module,
8
+ priority: args.priority,
9
+ folderId: args.folderId,
10
+ });
11
+ if (!data.ok)
12
+ throw new Error(data.error);
13
+ let output = `태스크 시작됨: #${data.task.seq} "${data.task.title}" → IN_PROGRESS`;
14
+ if (data.matchedSkills && data.matchedSkills.length > 0) {
15
+ const skillLines = data.matchedSkills.map((s) => `- ${s.slug}: ${s.name} — ${s.contextHint}`).join("\n");
16
+ output += `\n\n[필수] 매칭된 스킬이 있어요. 구현 전 반드시 load_skill(slug)를 호출하세요:\n${skillLines}`;
17
+ }
18
+ output += `\n\n다음 단계: recall("${data.task.title}")로 관련 과거 결정을 검색하세요.`;
19
+ return output;
20
+ }
21
+ //# sourceMappingURL=startTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startTask.js","sourceRoot":"","sources":["../../../src/mcp/tools/startTask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAQ1C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAoG,EACpG,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAoB,MAAM,EAAE,yBAAyB,EAAE;QAC/E,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,MAAM,GAAG,aAAa,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,iBAAiB,CAAC;IAC7E,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzG,MAAM,IAAI,4DAA4D,UAAU,EAAE,CAAC;IACrF,CAAC;IACD,MAAM,IAAI,sBAAsB,IAAI,CAAC,IAAI,CAAC,KAAK,sBAAsB,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { mcpPatch } from "../mcpClient.js";
2
+ export async function handleUpdateTask(args, config) {
3
+ const { taskSeq, projectId, ...updates } = args;
4
+ const data = await mcpPatch(config, `/api/memory/tasks/${taskSeq}`, { projectId, ...updates });
5
+ if (!data.ok)
6
+ throw new Error(data.error);
7
+ return `태스크 업데이트됨: #${data.task.seq} "${data.task.title}" → ${data.task.status}`;
8
+ }
9
+ //# sourceMappingURL=updateTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateTask.js","sourceRoot":"","sources":["../../../src/mcp/tools/updateTask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAK3C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAQC,EACD,MAAiB;IAEjB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAiB,MAAM,EAAE,qBAAqB,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC/G,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,eAAe,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AACnF,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { discoverClaudeFiles } from "../../discoverClaudeFiles.js";
2
+ import { readClaudeFile } from "../../readClaudeFile.js";
3
+ export async function handleUploadPrompt(args, config) {
4
+ const discovered = await discoverClaudeFiles(args.cwd);
5
+ if (discovered.length === 0) {
6
+ return "업로드할 파일이 없어요. CLAUDE.md, AGENTS.md, SKILL.md 파일을 확인해주세요.";
7
+ }
8
+ const files = [];
9
+ for (const f of discovered) {
10
+ const result = await readClaudeFile(f.absPath);
11
+ if (!result)
12
+ continue;
13
+ files.push({ ...f, content: result.content, mtime: result.mtime });
14
+ }
15
+ if (files.length === 0)
16
+ return "파일을 읽을 수 없었어요.";
17
+ const res = await fetch(`${config.appUrl}/api/claude-files/ingest`, {
18
+ method: "POST",
19
+ headers: {
20
+ "content-type": "application/json",
21
+ authorization: `Bearer ${config.apiKey}`,
22
+ },
23
+ body: JSON.stringify({ source: args.cwd, files }),
24
+ });
25
+ if (!res.ok) {
26
+ const text = await res.text().catch(() => "");
27
+ throw new Error(`업로드 실패 HTTP ${res.status}: ${text.slice(0, 200)}`);
28
+ }
29
+ const lines = files.map((f) => ` • ${f.displayPath} [${f.kind}]`).join("\n");
30
+ return `${files.length}개 파일 업로드 완료:\n${lines}`;
31
+ }
32
+ //# sourceMappingURL=uploadPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadPrompt.js","sourceRoot":"","sources":["../../../src/mcp/tools/uploadPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAqB,EACrB,MAAiB;IAEjB,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,0DAA0D,CAAC;IACpE,CAAC;IAED,MAAM,KAAK,GAOL,EAAE,CAAC;IAET,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,gBAAgB,CAAC;IAEhD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,0BAA0B,EAAE;QAClE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;SACzC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;KAClD,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,eAAe,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,GAAG,KAAK,CAAC,MAAM,iBAAiB,KAAK,EAAE,CAAC;AACjD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { authFilePath, readAuth } from "../../auth.js";
2
+ export async function handleWhoami() {
3
+ const auth = await readAuth();
4
+ if (!auth)
5
+ return "로그인되지 않았어요. `signin` 툴로 로그인해 주세요.";
6
+ return [
7
+ `계정: ${auth.email ?? "(이메일 정보 없음)"}`,
8
+ `서버: ${auth.appUrl}`,
9
+ `로그인: ${auth.signedInAt}`,
10
+ `저장: ${authFilePath()}`,
11
+ ].join("\n");
12
+ }
13
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../../src/mcp/tools/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,mCAAmC,CAAC;IACtD,OAAO;QACL,SAAS,IAAI,CAAC,KAAK,IAAI,aAAa,EAAE;QACtC,SAAS,IAAI,CAAC,MAAM,EAAE;QACtB,QAAQ,IAAI,CAAC,UAAU,EAAE;QACzB,SAAS,YAAY,EAAE,EAAE;KAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { spawn } from "node:child_process";
2
+ export function openBrowser(url) {
3
+ const cmd = process.platform === "darwin"
4
+ ? "open"
5
+ : process.platform === "win32"
6
+ ? "cmd"
7
+ : "xdg-open";
8
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
9
+ const child = spawn(cmd, args, { stdio: "ignore", detached: true });
10
+ child.on("error", () => {
11
+ // 브라우저 자동 열기 실패해도 무시 — 사용자가 URL 직접 열면 됨
12
+ });
13
+ child.unref();
14
+ }
15
+ //# sourceMappingURL=openBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openBrowser.js","sourceRoot":"","sources":["../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,GAAG,GACP,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC5B,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,UAAU,CAAC;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,wCAAwC;IAC1C,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}