pilot-ai 0.1.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.
Files changed (213) hide show
  1. package/dist/agent/claude.d.ts +45 -0
  2. package/dist/agent/claude.d.ts.map +1 -0
  3. package/dist/agent/claude.js +114 -0
  4. package/dist/agent/claude.js.map +1 -0
  5. package/dist/agent/core.d.ts +17 -0
  6. package/dist/agent/core.d.ts.map +1 -0
  7. package/dist/agent/core.js +129 -0
  8. package/dist/agent/core.js.map +1 -0
  9. package/dist/agent/heartbeat.d.ts +51 -0
  10. package/dist/agent/heartbeat.d.ts.map +1 -0
  11. package/dist/agent/heartbeat.js +253 -0
  12. package/dist/agent/heartbeat.js.map +1 -0
  13. package/dist/agent/memory-commands.d.ts +11 -0
  14. package/dist/agent/memory-commands.d.ts.map +1 -0
  15. package/dist/agent/memory-commands.js +55 -0
  16. package/dist/agent/memory-commands.js.map +1 -0
  17. package/dist/agent/memory.d.ts +11 -0
  18. package/dist/agent/memory.d.ts.map +1 -0
  19. package/dist/agent/memory.js +109 -0
  20. package/dist/agent/memory.js.map +1 -0
  21. package/dist/agent/multi-agent.d.ts +47 -0
  22. package/dist/agent/multi-agent.d.ts.map +1 -0
  23. package/dist/agent/multi-agent.js +117 -0
  24. package/dist/agent/multi-agent.js.map +1 -0
  25. package/dist/agent/pipeline.d.ts +27 -0
  26. package/dist/agent/pipeline.d.ts.map +1 -0
  27. package/dist/agent/pipeline.js +52 -0
  28. package/dist/agent/pipeline.js.map +1 -0
  29. package/dist/agent/planner.d.ts +21 -0
  30. package/dist/agent/planner.d.ts.map +1 -0
  31. package/dist/agent/planner.js +51 -0
  32. package/dist/agent/planner.js.map +1 -0
  33. package/dist/agent/preference-detector.d.ts +6 -0
  34. package/dist/agent/preference-detector.d.ts.map +1 -0
  35. package/dist/agent/preference-detector.js +50 -0
  36. package/dist/agent/preference-detector.js.map +1 -0
  37. package/dist/agent/project-analyzer.d.ts +6 -0
  38. package/dist/agent/project-analyzer.d.ts.map +1 -0
  39. package/dist/agent/project-analyzer.js +108 -0
  40. package/dist/agent/project-analyzer.js.map +1 -0
  41. package/dist/agent/project.d.ts +28 -0
  42. package/dist/agent/project.d.ts.map +1 -0
  43. package/dist/agent/project.js +121 -0
  44. package/dist/agent/project.js.map +1 -0
  45. package/dist/agent/queue.d.ts +61 -0
  46. package/dist/agent/queue.d.ts.map +1 -0
  47. package/dist/agent/queue.js +167 -0
  48. package/dist/agent/queue.js.map +1 -0
  49. package/dist/agent/safety.d.ts +25 -0
  50. package/dist/agent/safety.d.ts.map +1 -0
  51. package/dist/agent/safety.js +77 -0
  52. package/dist/agent/safety.js.map +1 -0
  53. package/dist/agent/semantic-search.d.ts +34 -0
  54. package/dist/agent/semantic-search.d.ts.map +1 -0
  55. package/dist/agent/semantic-search.js +183 -0
  56. package/dist/agent/semantic-search.js.map +1 -0
  57. package/dist/agent/skills.d.ts +59 -0
  58. package/dist/agent/skills.d.ts.map +1 -0
  59. package/dist/agent/skills.js +161 -0
  60. package/dist/agent/skills.js.map +1 -0
  61. package/dist/agent/tool-descriptions.d.ts +7 -0
  62. package/dist/agent/tool-descriptions.d.ts.map +1 -0
  63. package/dist/agent/tool-descriptions.js +51 -0
  64. package/dist/agent/tool-descriptions.js.map +1 -0
  65. package/dist/agent/worktree.d.ts +28 -0
  66. package/dist/agent/worktree.d.ts.map +1 -0
  67. package/dist/agent/worktree.js +59 -0
  68. package/dist/agent/worktree.js.map +1 -0
  69. package/dist/api/server.d.ts +30 -0
  70. package/dist/api/server.d.ts.map +1 -0
  71. package/dist/api/server.js +135 -0
  72. package/dist/api/server.js.map +1 -0
  73. package/dist/cli/connection-test.d.ts +14 -0
  74. package/dist/cli/connection-test.d.ts.map +1 -0
  75. package/dist/cli/connection-test.js +82 -0
  76. package/dist/cli/connection-test.js.map +1 -0
  77. package/dist/cli/init.d.ts +2 -0
  78. package/dist/cli/init.d.ts.map +1 -0
  79. package/dist/cli/init.js +287 -0
  80. package/dist/cli/init.js.map +1 -0
  81. package/dist/cli/logs.d.ts +5 -0
  82. package/dist/cli/logs.d.ts.map +1 -0
  83. package/dist/cli/logs.js +32 -0
  84. package/dist/cli/logs.js.map +1 -0
  85. package/dist/cli/project.d.ts +3 -0
  86. package/dist/cli/project.d.ts.map +1 -0
  87. package/dist/cli/project.js +58 -0
  88. package/dist/cli/project.js.map +1 -0
  89. package/dist/cli/start.d.ts +5 -0
  90. package/dist/cli/start.d.ts.map +1 -0
  91. package/dist/cli/start.js +82 -0
  92. package/dist/cli/start.js.map +1 -0
  93. package/dist/cli/status.d.ts +8 -0
  94. package/dist/cli/status.d.ts.map +1 -0
  95. package/dist/cli/status.js +39 -0
  96. package/dist/cli/status.js.map +1 -0
  97. package/dist/cli/stop.d.ts +2 -0
  98. package/dist/cli/stop.d.ts.map +1 -0
  99. package/dist/cli/stop.js +28 -0
  100. package/dist/cli/stop.js.map +1 -0
  101. package/dist/config/keychain.d.ts +4 -0
  102. package/dist/config/keychain.d.ts.map +1 -0
  103. package/dist/config/keychain.js +54 -0
  104. package/dist/config/keychain.js.map +1 -0
  105. package/dist/config/schema.d.ts +60 -0
  106. package/dist/config/schema.d.ts.map +1 -0
  107. package/dist/config/schema.js +88 -0
  108. package/dist/config/schema.js.map +1 -0
  109. package/dist/config/store.d.ts +8 -0
  110. package/dist/config/store.d.ts.map +1 -0
  111. package/dist/config/store.js +48 -0
  112. package/dist/config/store.js.map +1 -0
  113. package/dist/index.d.ts +3 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +47 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/messenger/adapter.d.ts +30 -0
  118. package/dist/messenger/adapter.d.ts.map +1 -0
  119. package/dist/messenger/adapter.js +2 -0
  120. package/dist/messenger/adapter.js.map +1 -0
  121. package/dist/messenger/factory.d.ts +4 -0
  122. package/dist/messenger/factory.d.ts.map +1 -0
  123. package/dist/messenger/factory.js +19 -0
  124. package/dist/messenger/factory.js.map +1 -0
  125. package/dist/messenger/slack.d.ts +21 -0
  126. package/dist/messenger/slack.d.ts.map +1 -0
  127. package/dist/messenger/slack.js +127 -0
  128. package/dist/messenger/slack.js.map +1 -0
  129. package/dist/messenger/telegram.d.ts +21 -0
  130. package/dist/messenger/telegram.d.ts.map +1 -0
  131. package/dist/messenger/telegram.js +118 -0
  132. package/dist/messenger/telegram.js.map +1 -0
  133. package/dist/security/audit.d.ts +15 -0
  134. package/dist/security/audit.d.ts.map +1 -0
  135. package/dist/security/audit.js +41 -0
  136. package/dist/security/audit.js.map +1 -0
  137. package/dist/security/auth.d.ts +8 -0
  138. package/dist/security/auth.d.ts.map +1 -0
  139. package/dist/security/auth.js +15 -0
  140. package/dist/security/auth.js.map +1 -0
  141. package/dist/security/prompt-guard.d.ts +11 -0
  142. package/dist/security/prompt-guard.d.ts.map +1 -0
  143. package/dist/security/prompt-guard.js +30 -0
  144. package/dist/security/prompt-guard.js.map +1 -0
  145. package/dist/security/sandbox.d.ts +11 -0
  146. package/dist/security/sandbox.d.ts.map +1 -0
  147. package/dist/security/sandbox.js +76 -0
  148. package/dist/security/sandbox.js.map +1 -0
  149. package/dist/tools/browser.d.ts +61 -0
  150. package/dist/tools/browser.d.ts.map +1 -0
  151. package/dist/tools/browser.js +196 -0
  152. package/dist/tools/browser.js.map +1 -0
  153. package/dist/tools/calendar.d.ts +36 -0
  154. package/dist/tools/calendar.d.ts.map +1 -0
  155. package/dist/tools/calendar.js +146 -0
  156. package/dist/tools/calendar.js.map +1 -0
  157. package/dist/tools/clipboard.d.ts +13 -0
  158. package/dist/tools/clipboard.d.ts.map +1 -0
  159. package/dist/tools/clipboard.js +47 -0
  160. package/dist/tools/clipboard.js.map +1 -0
  161. package/dist/tools/email.d.ts +52 -0
  162. package/dist/tools/email.d.ts.map +1 -0
  163. package/dist/tools/email.js +211 -0
  164. package/dist/tools/email.js.map +1 -0
  165. package/dist/tools/figma-mcp.d.ts +30 -0
  166. package/dist/tools/figma-mcp.d.ts.map +1 -0
  167. package/dist/tools/figma-mcp.js +58 -0
  168. package/dist/tools/figma-mcp.js.map +1 -0
  169. package/dist/tools/figma.d.ts +52 -0
  170. package/dist/tools/figma.d.ts.map +1 -0
  171. package/dist/tools/figma.js +62 -0
  172. package/dist/tools/figma.js.map +1 -0
  173. package/dist/tools/filesystem.d.ts +9 -0
  174. package/dist/tools/filesystem.d.ts.map +1 -0
  175. package/dist/tools/filesystem.js +62 -0
  176. package/dist/tools/filesystem.js.map +1 -0
  177. package/dist/tools/github.d.ts +36 -0
  178. package/dist/tools/github.d.ts.map +1 -0
  179. package/dist/tools/github.js +93 -0
  180. package/dist/tools/github.js.map +1 -0
  181. package/dist/tools/image.d.ts +14 -0
  182. package/dist/tools/image.d.ts.map +1 -0
  183. package/dist/tools/image.js +57 -0
  184. package/dist/tools/image.js.map +1 -0
  185. package/dist/tools/linear.d.ts +41 -0
  186. package/dist/tools/linear.d.ts.map +1 -0
  187. package/dist/tools/linear.js +87 -0
  188. package/dist/tools/linear.js.map +1 -0
  189. package/dist/tools/notification.d.ts +8 -0
  190. package/dist/tools/notification.d.ts.map +1 -0
  191. package/dist/tools/notification.js +49 -0
  192. package/dist/tools/notification.js.map +1 -0
  193. package/dist/tools/notion.d.ts +23 -0
  194. package/dist/tools/notion.d.ts.map +1 -0
  195. package/dist/tools/notion.js +91 -0
  196. package/dist/tools/notion.js.map +1 -0
  197. package/dist/tools/obsidian.d.ts +17 -0
  198. package/dist/tools/obsidian.d.ts.map +1 -0
  199. package/dist/tools/obsidian.js +100 -0
  200. package/dist/tools/obsidian.js.map +1 -0
  201. package/dist/tools/shell.d.ts +10 -0
  202. package/dist/tools/shell.d.ts.map +1 -0
  203. package/dist/tools/shell.js +37 -0
  204. package/dist/tools/shell.js.map +1 -0
  205. package/dist/tools/voice.d.ts +28 -0
  206. package/dist/tools/voice.d.ts.map +1 -0
  207. package/dist/tools/voice.js +88 -0
  208. package/dist/tools/voice.js.map +1 -0
  209. package/dist/tools/vscode.d.ts +42 -0
  210. package/dist/tools/vscode.d.ts.map +1 -0
  211. package/dist/tools/vscode.js +80 -0
  212. package/dist/tools/vscode.js.map +1 -0
  213. package/package.json +51 -0
@@ -0,0 +1,108 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { readProjectMemory, writeProjectMemory } from './memory.js';
4
+ const STACK_DETECTORS = [
5
+ { file: 'package.json', label: 'Node.js' },
6
+ { file: 'tsconfig.json', label: 'TypeScript' },
7
+ { file: 'Cargo.toml', label: 'Rust' },
8
+ { file: 'pyproject.toml', label: 'Python' },
9
+ { file: 'go.mod', label: 'Go' },
10
+ { file: 'pom.xml', label: 'Java (Maven)' },
11
+ { file: 'build.gradle', label: 'Java (Gradle)' },
12
+ { file: 'Gemfile', label: 'Ruby' },
13
+ { file: 'docker-compose.yml', label: 'Docker Compose' },
14
+ { file: 'Dockerfile', label: 'Docker' },
15
+ { file: '.github/workflows', label: 'GitHub Actions' },
16
+ ];
17
+ const FRAMEWORK_DETECTORS = [
18
+ { dep: 'next', label: 'Next.js' },
19
+ { dep: 'react', label: 'React' },
20
+ { dep: 'vue', label: 'Vue.js' },
21
+ { dep: 'express', label: 'Express' },
22
+ { dep: 'fastify', label: 'Fastify' },
23
+ { dep: 'nestjs', label: 'NestJS' },
24
+ { dep: '@angular/core', label: 'Angular' },
25
+ { dep: 'svelte', label: 'Svelte' },
26
+ { dep: 'vitest', label: 'Vitest' },
27
+ { dep: 'jest', label: 'Jest' },
28
+ { dep: 'mocha', label: 'Mocha' },
29
+ { dep: 'prisma', label: 'Prisma' },
30
+ { dep: 'drizzle-orm', label: 'Drizzle' },
31
+ { dep: 'tailwindcss', label: 'Tailwind CSS' },
32
+ ];
33
+ /**
34
+ * Analyzes a project directory and generates a summary.
35
+ * Only runs if project memory is empty (first time).
36
+ */
37
+ export async function analyzeProjectIfNew(projectName, projectPath) {
38
+ const existing = await readProjectMemory(projectName);
39
+ if (existing)
40
+ return null; // Already analyzed
41
+ const analysis = await analyzeProject(projectName, projectPath);
42
+ if (analysis.stack.length === 0 && analysis.structure.length === 0) {
43
+ return null; // Nothing detected
44
+ }
45
+ const lines = [`# ${projectName}`];
46
+ if (analysis.stack.length > 0) {
47
+ lines.push('', `## Stack`, analysis.stack.map((s) => `- ${s}`).join('\n'));
48
+ }
49
+ if (analysis.structure.length > 0) {
50
+ lines.push('', `## Structure`, analysis.structure.map((s) => `- ${s}`).join('\n'));
51
+ }
52
+ const content = lines.join('\n');
53
+ await writeProjectMemory(projectName, content);
54
+ return content;
55
+ }
56
+ async function analyzeProject(name, projectPath) {
57
+ const stack = [];
58
+ const structure = [];
59
+ // Detect stack from marker files
60
+ for (const { file, label } of STACK_DETECTORS) {
61
+ try {
62
+ await fs.access(path.join(projectPath, file));
63
+ stack.push(label);
64
+ }
65
+ catch {
66
+ // Not found
67
+ }
68
+ }
69
+ // Detect frameworks from package.json
70
+ try {
71
+ const pkgContent = await fs.readFile(path.join(projectPath, 'package.json'), 'utf-8');
72
+ const pkg = JSON.parse(pkgContent);
73
+ const allDeps = {
74
+ ...pkg.dependencies,
75
+ ...pkg.devDependencies,
76
+ };
77
+ for (const { dep, label } of FRAMEWORK_DETECTORS) {
78
+ if (dep in allDeps) {
79
+ stack.push(label);
80
+ }
81
+ }
82
+ if (pkg.scripts) {
83
+ const scripts = Object.keys(pkg.scripts);
84
+ if (scripts.length > 0) {
85
+ structure.push(`Scripts: ${scripts.slice(0, 8).join(', ')}`);
86
+ }
87
+ }
88
+ }
89
+ catch {
90
+ // No package.json or invalid
91
+ }
92
+ // Detect top-level directory structure
93
+ try {
94
+ const entries = await fs.readdir(projectPath, { withFileTypes: true });
95
+ const dirs = entries
96
+ .filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules')
97
+ .map((e) => e.name)
98
+ .slice(0, 10);
99
+ if (dirs.length > 0) {
100
+ structure.push(`Directories: ${dirs.join(', ')}`);
101
+ }
102
+ }
103
+ catch {
104
+ // Can't read
105
+ }
106
+ return { name, stack, structure };
107
+ }
108
+ //# sourceMappingURL=project-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-analyzer.js","sourceRoot":"","sources":["../../src/agent/project-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface ProjectEntry {
2
+ path: string;
3
+ description?: string;
4
+ lastUsed?: string;
5
+ }
6
+ export interface ProjectRegistry {
7
+ scanRoots: string[];
8
+ detectBy: string[];
9
+ projects: Record<string, ProjectEntry>;
10
+ }
11
+ export declare function loadRegistry(): Promise<ProjectRegistry>;
12
+ export declare function addProject(name: string, projectPath: string, description?: string): Promise<void>;
13
+ export declare function removeProject(name: string): Promise<boolean>;
14
+ export declare function listProjects(): Promise<Record<string, ProjectEntry>>;
15
+ /**
16
+ * 지정된 루트 디렉토리들을 스캔하여 프로젝트를 자동 감지한다.
17
+ */
18
+ export declare function scanProjects(roots: string[]): Promise<Record<string, string>>;
19
+ /**
20
+ * 사용자 메시지에서 프로젝트를 매칭한다.
21
+ * 우선순위: 정확한 이름 → 절대경로 → fuzzy match
22
+ */
23
+ export declare function resolveProject(query: string): Promise<{
24
+ name: string;
25
+ path: string;
26
+ } | null>;
27
+ export declare function touchProject(name: string): Promise<void>;
28
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/agent/project.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACxC;AAQD,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAO7D;AAOD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvG;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMlE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAG1E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmCnF;AAcD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAuBlG;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D"}
@@ -0,0 +1,121 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getPilotDir } from '../config/store.js';
4
+ const DEFAULT_DETECT_BY = ['package.json', '.git', 'Cargo.toml', 'pyproject.toml', 'go.mod'];
5
+ function getRegistryPath() {
6
+ return path.join(getPilotDir(), 'projects.json');
7
+ }
8
+ export async function loadRegistry() {
9
+ try {
10
+ const content = await fs.readFile(getRegistryPath(), 'utf-8');
11
+ return JSON.parse(content);
12
+ }
13
+ catch {
14
+ return { scanRoots: [], detectBy: DEFAULT_DETECT_BY, projects: {} };
15
+ }
16
+ }
17
+ async function saveRegistry(registry) {
18
+ const content = JSON.stringify(registry, null, 2) + '\n';
19
+ await fs.writeFile(getRegistryPath(), content);
20
+ }
21
+ export async function addProject(name, projectPath, description) {
22
+ const registry = await loadRegistry();
23
+ registry.projects[name] = {
24
+ path: projectPath,
25
+ description,
26
+ lastUsed: new Date().toISOString(),
27
+ };
28
+ await saveRegistry(registry);
29
+ }
30
+ export async function removeProject(name) {
31
+ const registry = await loadRegistry();
32
+ if (!(name in registry.projects))
33
+ return false;
34
+ delete registry.projects[name];
35
+ await saveRegistry(registry);
36
+ return true;
37
+ }
38
+ export async function listProjects() {
39
+ const registry = await loadRegistry();
40
+ return registry.projects;
41
+ }
42
+ /**
43
+ * 지정된 루트 디렉토리들을 스캔하여 프로젝트를 자동 감지한다.
44
+ */
45
+ export async function scanProjects(roots) {
46
+ const registry = await loadRegistry();
47
+ const detected = {};
48
+ for (const root of roots) {
49
+ const resolvedRoot = path.resolve(root);
50
+ let entries;
51
+ try {
52
+ entries = await fs.readdir(resolvedRoot, { withFileTypes: true });
53
+ }
54
+ catch {
55
+ continue;
56
+ }
57
+ for (const entry of entries) {
58
+ if (!entry.isDirectory() || entry.name.startsWith('.'))
59
+ continue;
60
+ const dirPath = path.join(resolvedRoot, entry.name);
61
+ const isProject = await detectProject(dirPath, registry.detectBy);
62
+ if (isProject) {
63
+ const name = entry.name;
64
+ if (!(name in registry.projects)) {
65
+ registry.projects[name] = { path: dirPath, lastUsed: new Date().toISOString() };
66
+ detected[name] = dirPath;
67
+ }
68
+ }
69
+ }
70
+ // scanRoots에 추가
71
+ if (!registry.scanRoots.includes(resolvedRoot)) {
72
+ registry.scanRoots.push(resolvedRoot);
73
+ }
74
+ }
75
+ await saveRegistry(registry);
76
+ return detected;
77
+ }
78
+ async function detectProject(dirPath, markers) {
79
+ for (const marker of markers) {
80
+ try {
81
+ await fs.access(path.join(dirPath, marker));
82
+ return true;
83
+ }
84
+ catch {
85
+ // 다음 마커 시도
86
+ }
87
+ }
88
+ return false;
89
+ }
90
+ /**
91
+ * 사용자 메시지에서 프로젝트를 매칭한다.
92
+ * 우선순위: 정확한 이름 → 절대경로 → fuzzy match
93
+ */
94
+ export async function resolveProject(query) {
95
+ const registry = await loadRegistry();
96
+ const projects = registry.projects;
97
+ // 1. 정확한 이름 매칭
98
+ if (query in projects) {
99
+ return { name: query, path: projects[query].path };
100
+ }
101
+ // 2. 절대경로 포함 여부
102
+ if (query.startsWith('/') || query.startsWith('~')) {
103
+ return { name: path.basename(query), path: path.resolve(query) };
104
+ }
105
+ // 3. Fuzzy match (부분 문자열)
106
+ const lowerQuery = query.toLowerCase();
107
+ for (const [name, entry] of Object.entries(projects)) {
108
+ if (name.toLowerCase().includes(lowerQuery) || lowerQuery.includes(name.toLowerCase())) {
109
+ return { name, path: entry.path };
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ export async function touchProject(name) {
115
+ const registry = await loadRegistry();
116
+ if (name in registry.projects) {
117
+ registry.projects[name].lastUsed = new Date().toISOString();
118
+ await saveRegistry(registry);
119
+ }
120
+ }
121
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/agent/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAcjD,MAAM,iBAAiB,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AAE7F,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACtE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAyB;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IACzD,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,WAAmB,EAAE,WAAoB;IACtF,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG;QACxB,IAAI,EAAE,WAAW;QACjB,WAAW;QACX,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACnC,CAAC;IACF,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,OAAO,QAAQ,CAAC,QAAQ,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAe;IAChD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAEjE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAClE,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;gBACxB,IAAI,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACjC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;oBAChF,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/C,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,OAAiB;IAC7D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IAChD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAEnC,eAAe;IACf,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,gBAAgB;IAChB,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;IACnE,CAAC;IAED,0BAA0B;IAC1B,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACvF,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,IAAI,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC9B,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5D,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { type WorktreeInfo } from './worktree.js';
2
+ export type TaskStatus = 'queued' | 'running' | 'waiting_approval' | 'completed' | 'failed' | 'cancelled';
3
+ export interface Task {
4
+ id: string;
5
+ status: TaskStatus;
6
+ project: string | null;
7
+ projectPath?: string;
8
+ command: string;
9
+ threadId?: string;
10
+ channelId: string;
11
+ userId: string;
12
+ createdAt: Date;
13
+ startedAt: Date | null;
14
+ completedAt: Date | null;
15
+ result?: string;
16
+ error?: string;
17
+ worktree?: WorktreeInfo;
18
+ }
19
+ export type TaskHandler = (task: Task) => Promise<void>;
20
+ /**
21
+ * Task queue with project-based parallel execution.
22
+ * - Different projects run in parallel
23
+ * - Same project tasks run sequentially
24
+ * - Null-project tasks (Notion, browser) run in parallel with everything
25
+ * - Max concurrent limit to respect Claude CLI rate limits
26
+ */
27
+ export declare class TaskQueue {
28
+ private queue;
29
+ private runningTasks;
30
+ private handler;
31
+ private maxConcurrent;
32
+ private worktreeEnabled;
33
+ constructor(maxConcurrent?: number, worktreeEnabled?: boolean);
34
+ onTask(handler: TaskHandler): void;
35
+ enqueue(params: {
36
+ command: string;
37
+ project?: string;
38
+ projectPath?: string;
39
+ channelId: string;
40
+ userId: string;
41
+ threadId?: string;
42
+ }): Task;
43
+ private processNext;
44
+ /**
45
+ * Finds the next task that can run based on project parallelism rules.
46
+ * With worktree enabled, same-project tasks can run in parallel via worktrees.
47
+ */
48
+ private findNextRunnable;
49
+ private executeTask;
50
+ cancel(taskId: string): boolean;
51
+ getStatus(): {
52
+ running: Task[];
53
+ queued: Task[];
54
+ completed: Task[];
55
+ };
56
+ getTask(taskId: string): Task | undefined;
57
+ getQueueLength(): number;
58
+ getRunningCount(): number;
59
+ formatStatus(): string;
60
+ }
61
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/agent/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAElF,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE1G,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQxD;;;;;;GAMG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAU;gBAErB,aAAa,GAAE,MAAU,EAAE,eAAe,GAAE,OAAe;IAKvE,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIlC,OAAO,CAAC,MAAM,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI;YAoBM,WAAW;IAuBzB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;YAsBV,WAAW;IAoCzB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAQ/B,SAAS,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAAC,MAAM,EAAE,IAAI,EAAE,CAAC;QAAC,SAAS,EAAE,IAAI,EAAE,CAAA;KAAE;IAQnE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIzC,cAAc,IAAI,MAAM;IAIxB,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM;CAqBvB"}
@@ -0,0 +1,167 @@
1
+ import { createWorktree, removeWorktree } from './worktree.js';
2
+ let taskCounter = 0;
3
+ function generateTaskId() {
4
+ return `task-${Date.now()}-${++taskCounter}`;
5
+ }
6
+ /**
7
+ * Task queue with project-based parallel execution.
8
+ * - Different projects run in parallel
9
+ * - Same project tasks run sequentially
10
+ * - Null-project tasks (Notion, browser) run in parallel with everything
11
+ * - Max concurrent limit to respect Claude CLI rate limits
12
+ */
13
+ export class TaskQueue {
14
+ queue = [];
15
+ runningTasks = new Set();
16
+ handler = null;
17
+ maxConcurrent;
18
+ worktreeEnabled;
19
+ constructor(maxConcurrent = 3, worktreeEnabled = false) {
20
+ this.maxConcurrent = maxConcurrent;
21
+ this.worktreeEnabled = worktreeEnabled;
22
+ }
23
+ onTask(handler) {
24
+ this.handler = handler;
25
+ }
26
+ enqueue(params) {
27
+ const task = {
28
+ id: generateTaskId(),
29
+ status: 'queued',
30
+ project: params.project ?? null,
31
+ projectPath: params.projectPath,
32
+ command: params.command,
33
+ channelId: params.channelId,
34
+ userId: params.userId,
35
+ threadId: params.threadId,
36
+ createdAt: new Date(),
37
+ startedAt: null,
38
+ completedAt: null,
39
+ };
40
+ this.queue.push(task);
41
+ this.processNext();
42
+ return task;
43
+ }
44
+ async processNext() {
45
+ if (this.runningTasks.size >= this.maxConcurrent)
46
+ return;
47
+ const nextTask = this.findNextRunnable();
48
+ if (!nextTask)
49
+ return;
50
+ this.runningTasks.add(nextTask);
51
+ nextTask.status = 'running';
52
+ nextTask.startedAt = new Date();
53
+ // Run async without blocking processNext
54
+ this.executeTask(nextTask).finally(() => {
55
+ this.runningTasks.delete(nextTask);
56
+ // Try to start more tasks
57
+ this.processNext();
58
+ });
59
+ // Try to start more parallel tasks immediately
60
+ if (this.runningTasks.size < this.maxConcurrent) {
61
+ this.processNext();
62
+ }
63
+ }
64
+ /**
65
+ * Finds the next task that can run based on project parallelism rules.
66
+ * With worktree enabled, same-project tasks can run in parallel via worktrees.
67
+ */
68
+ findNextRunnable() {
69
+ const runningProjects = new Set();
70
+ for (const task of this.runningTasks) {
71
+ if (task.project)
72
+ runningProjects.add(task.project);
73
+ }
74
+ for (const task of this.queue) {
75
+ if (task.status !== 'queued')
76
+ continue;
77
+ // Null-project tasks can always run (no project conflict)
78
+ if (task.project === null)
79
+ return task;
80
+ // No conflict - run directly
81
+ if (!runningProjects.has(task.project))
82
+ return task;
83
+ // Worktree mode: allow same-project if projectPath is available
84
+ if (this.worktreeEnabled && task.projectPath)
85
+ return task;
86
+ }
87
+ return null;
88
+ }
89
+ async executeTask(task) {
90
+ // If same project is already running and worktree is enabled, create worktree
91
+ if (this.worktreeEnabled && task.project && task.projectPath) {
92
+ const alreadyRunning = [...this.runningTasks].some((t) => t !== task && t.project === task.project && !t.worktree);
93
+ if (alreadyRunning) {
94
+ try {
95
+ task.worktree = await createWorktree(task.projectPath, task.id);
96
+ }
97
+ catch {
98
+ // Worktree creation failed - fall back to sequential wait handled elsewhere
99
+ }
100
+ }
101
+ }
102
+ try {
103
+ if (this.handler) {
104
+ await this.handler(task);
105
+ }
106
+ task.status = 'completed';
107
+ }
108
+ catch (err) {
109
+ task.status = 'failed';
110
+ task.error = err instanceof Error ? err.message : String(err);
111
+ }
112
+ finally {
113
+ task.completedAt = new Date();
114
+ // Clean up worktree
115
+ if (task.worktree && task.projectPath) {
116
+ try {
117
+ await removeWorktree(task.projectPath, task.worktree.path, task.worktree.branch);
118
+ }
119
+ catch {
120
+ // Best-effort cleanup
121
+ }
122
+ }
123
+ }
124
+ }
125
+ cancel(taskId) {
126
+ const task = this.queue.find((t) => t.id === taskId && t.status === 'queued');
127
+ if (!task)
128
+ return false;
129
+ task.status = 'cancelled';
130
+ task.completedAt = new Date();
131
+ return true;
132
+ }
133
+ getStatus() {
134
+ return {
135
+ running: [...this.runningTasks],
136
+ queued: this.queue.filter((t) => t.status === 'queued'),
137
+ completed: this.queue.filter((t) => t.status === 'completed' || t.status === 'failed'),
138
+ };
139
+ }
140
+ getTask(taskId) {
141
+ return this.queue.find((t) => t.id === taskId);
142
+ }
143
+ getQueueLength() {
144
+ return this.queue.filter((t) => t.status === 'queued').length;
145
+ }
146
+ getRunningCount() {
147
+ return this.runningTasks.size;
148
+ }
149
+ formatStatus() {
150
+ const { running, queued } = this.getStatus();
151
+ const lines = ['Task Queue:'];
152
+ for (const task of running) {
153
+ const elapsed = Math.floor((Date.now() - (task.startedAt?.getTime() ?? Date.now())) / 1000);
154
+ const proj = task.project ? `[${task.project}] ` : '';
155
+ lines.push(` [${task.id}] running - ${proj}${task.command} (${elapsed}s)`);
156
+ }
157
+ for (const task of queued) {
158
+ const proj = task.project ? `[${task.project}] ` : '';
159
+ lines.push(` [${task.id}] queued - ${proj}${task.command}`);
160
+ }
161
+ if (running.length === 0 && queued.length === 0) {
162
+ lines.push(' No pending tasks.');
163
+ }
164
+ return lines.join('\n');
165
+ }
166
+ }
167
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/agent/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export type SafetyLevel = 'safe' | 'moderate' | 'dangerous';
2
+ export declare function classifySafety(action: string): SafetyLevel;
3
+ /**
4
+ * 승인 대기 상태를 관리한다.
5
+ */
6
+ export interface PendingApproval {
7
+ taskId: string;
8
+ action: string;
9
+ resolve: (approved: boolean) => void;
10
+ timer: ReturnType<typeof setTimeout>;
11
+ }
12
+ export declare class ApprovalManager {
13
+ private pending;
14
+ /**
15
+ * 승인을 요청하고, 승인/거부/타임아웃까지 대기한다.
16
+ */
17
+ requestApproval(taskId: string, action: string, timeoutMs: number): Promise<boolean>;
18
+ /**
19
+ * 사용자의 승인/거부 응답을 처리한다.
20
+ */
21
+ handleResponse(taskId: string, approved: boolean): boolean;
22
+ hasPending(taskId: string): boolean;
23
+ getPendingCount(): number;
24
+ }
25
+ //# sourceMappingURL=safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/agent/safety.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;AAmC5D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAc1D;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACtC;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAsC;IAErD;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWpF;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO;IAU1D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAInC,eAAe,IAAI,MAAM;CAG1B"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 작업 계획의 위험도를 분류한다.
3
+ */
4
+ const DANGEROUS_PATTERNS = [
5
+ /\bgit\s+push\b/,
6
+ /\bgit\s+push\s+--force\b/,
7
+ /\bgit\s+reset\s+--hard\b/,
8
+ /\brm\s+(-[a-zA-Z]*r|-[a-zA-Z]*f)/, // rm -r, rm -f, rm -rf
9
+ /\bdrop\s+(table|database)\b/i,
10
+ /\btruncate\s+table\b/i,
11
+ /\bformat\s/,
12
+ /\bdeploy\b/,
13
+ /\bnpm\s+publish\b/,
14
+ /\bsend\s*(email|mail|message)\b/i,
15
+ /\bsubmit\s*(form)\b/i,
16
+ ];
17
+ const MODERATE_PATTERNS = [
18
+ /\bgit\s+commit\b/,
19
+ /\bgit\s+merge\b/,
20
+ /\bgit\s+checkout\b/,
21
+ /\bnpm\s+install\b/,
22
+ /\bmkdir\b/,
23
+ /\btouch\b/,
24
+ /\bcp\b/,
25
+ /\bmv\b/,
26
+ /\bwrite\b/i,
27
+ /\bcreate\b/i,
28
+ /\bmodify\b/i,
29
+ /\bedit\b/i,
30
+ ];
31
+ export function classifySafety(action) {
32
+ for (const pattern of DANGEROUS_PATTERNS) {
33
+ if (pattern.test(action)) {
34
+ return 'dangerous';
35
+ }
36
+ }
37
+ for (const pattern of MODERATE_PATTERNS) {
38
+ if (pattern.test(action)) {
39
+ return 'moderate';
40
+ }
41
+ }
42
+ return 'safe';
43
+ }
44
+ export class ApprovalManager {
45
+ pending = new Map();
46
+ /**
47
+ * 승인을 요청하고, 승인/거부/타임아웃까지 대기한다.
48
+ */
49
+ requestApproval(taskId, action, timeoutMs) {
50
+ return new Promise((resolve) => {
51
+ const timer = setTimeout(() => {
52
+ this.pending.delete(taskId);
53
+ resolve(false); // 타임아웃 → 거부 처리
54
+ }, timeoutMs);
55
+ this.pending.set(taskId, { taskId, action, resolve, timer });
56
+ });
57
+ }
58
+ /**
59
+ * 사용자의 승인/거부 응답을 처리한다.
60
+ */
61
+ handleResponse(taskId, approved) {
62
+ const entry = this.pending.get(taskId);
63
+ if (!entry)
64
+ return false;
65
+ clearTimeout(entry.timer);
66
+ this.pending.delete(taskId);
67
+ entry.resolve(approved);
68
+ return true;
69
+ }
70
+ hasPending(taskId) {
71
+ return this.pending.has(taskId);
72
+ }
73
+ getPendingCount() {
74
+ return this.pending.size;
75
+ }
76
+ }
77
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../../src/agent/safety.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,MAAM,kBAAkB,GAAG;IACzB,gBAAgB;IAChB,0BAA0B;IAC1B,0BAA0B;IAC1B,kCAAkC,EAAI,uBAAuB;IAC7D,8BAA8B;IAC9B,uBAAuB;IACvB,YAAY;IACZ,YAAY;IACZ,mBAAmB;IACnB,kCAAkC;IAClC,sBAAsB;CACvB,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,kBAAkB;IAClB,iBAAiB;IACjB,oBAAoB;IACpB,mBAAmB;IACnB,WAAW;IACX,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,aAAa;IACb,aAAa;IACb,WAAW;CACZ,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAYD,MAAM,OAAO,eAAe;IAClB,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IAErD;;OAEG;IACH,eAAe,CAAC,MAAc,EAAE,MAAc,EAAE,SAAiB;QAC/D,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACtC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC5B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe;YACjC,CAAC,EAAE,SAAS,CAAC,CAAC;YAEd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,MAAc,EAAE,QAAiB;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAEzB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF"}