@kiyeonjeon21/datacontext 0.2.0 → 0.3.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.
- package/.cursorrules +12 -0
- package/.env.example +8 -0
- package/.github/workflows/ci.yml +21 -1
- package/.github/workflows/publish.yml +21 -1
- package/CHANGELOG.md +41 -0
- package/README.md +247 -239
- package/datacontext.db +0 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +145 -0
- package/dist/api/server.js.map +1 -1
- package/dist/api/start-server.d.ts +10 -0
- package/dist/api/start-server.d.ts.map +1 -0
- package/dist/api/start-server.js +73 -0
- package/dist/api/start-server.js.map +1 -0
- package/dist/cli/index.js +462 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/context-service.d.ts +58 -0
- package/dist/core/context-service.d.ts.map +1 -1
- package/dist/core/context-service.js +121 -0
- package/dist/core/context-service.js.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/llm-service.d.ts +141 -0
- package/dist/core/llm-service.d.ts.map +1 -0
- package/dist/core/llm-service.js +284 -0
- package/dist/core/llm-service.js.map +1 -0
- package/dist/knowledge/store.d.ts +56 -3
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +193 -7
- package/dist/knowledge/store.js.map +1 -1
- package/dist/knowledge/types.d.ts +43 -1
- package/dist/knowledge/types.d.ts.map +1 -1
- package/dist/knowledge/types.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +365 -0
- package/dist/mcp/tools.js.map +1 -1
- package/docs/API.md +173 -0
- package/docs/DEMO_SCRIPT.md +210 -0
- package/docs/SYNC_GUIDE.md +242 -0
- package/package.json +4 -1
- package/src/api/server.ts +160 -0
- package/src/api/start-server.ts +78 -0
- package/src/cli/index.ts +534 -0
- package/src/core/context-service.ts +157 -0
- package/src/core/index.ts +7 -0
- package/src/core/llm-service.ts +359 -0
- package/src/knowledge/store.ts +232 -7
- package/src/knowledge/types.ts +45 -1
- package/src/mcp/tools.ts +415 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# DataContext Demo Script
|
|
2
|
+
|
|
3
|
+
이 문서는 DataContext의 핵심 기능을 보여주는 데모 시나리오입니다.
|
|
4
|
+
GIF/영상 제작 시 이 순서대로 진행하세요.
|
|
5
|
+
|
|
6
|
+
## 사전 준비
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# 1. 테스트 DB 준비 (PostgreSQL)
|
|
10
|
+
psql -c "CREATE DATABASE demo_db"
|
|
11
|
+
psql demo_db -c "
|
|
12
|
+
CREATE TABLE users (
|
|
13
|
+
id SERIAL PRIMARY KEY,
|
|
14
|
+
email VARCHAR(255) NOT NULL,
|
|
15
|
+
name VARCHAR(100),
|
|
16
|
+
status INTEGER DEFAULT 1,
|
|
17
|
+
created_at TIMESTAMP DEFAULT NOW(),
|
|
18
|
+
deleted_at TIMESTAMP
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE orders (
|
|
22
|
+
id SERIAL PRIMARY KEY,
|
|
23
|
+
user_id INTEGER REFERENCES users(id),
|
|
24
|
+
total INTEGER NOT NULL, -- cents
|
|
25
|
+
status VARCHAR(20) DEFAULT 'pending',
|
|
26
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- Add comments
|
|
30
|
+
COMMENT ON TABLE users IS 'Core user accounts';
|
|
31
|
+
COMMENT ON COLUMN users.status IS '1=active, 0=inactive';
|
|
32
|
+
COMMENT ON COLUMN orders.total IS 'Order total in cents';
|
|
33
|
+
|
|
34
|
+
-- Insert sample data
|
|
35
|
+
INSERT INTO users (email, name, status) VALUES
|
|
36
|
+
('john@example.com', 'John Doe', 1),
|
|
37
|
+
('jane@example.com', 'Jane Smith', 1),
|
|
38
|
+
('bob@example.com', 'Bob Wilson', 0);
|
|
39
|
+
|
|
40
|
+
INSERT INTO orders (user_id, total, status) VALUES
|
|
41
|
+
(1, 5000, 'completed'),
|
|
42
|
+
(1, 15000, 'completed'),
|
|
43
|
+
(2, 25000, 'pending');
|
|
44
|
+
"
|
|
45
|
+
|
|
46
|
+
# 2. DataContext 서버 시작
|
|
47
|
+
npx @kiyeonjeon21/datacontext serve postgres://postgres:postgres@localhost:5432/demo_db --port 3000
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Demo 1: Cold Start → Auto-Harvest (30초)
|
|
53
|
+
|
|
54
|
+
**목표:** 처음 연결 시 자동으로 메타데이터를 수집하는 것을 보여줌
|
|
55
|
+
|
|
56
|
+
1. VS Code에서 DataContext Extension 열기
|
|
57
|
+
2. `Cmd+Shift+P` → "DataContext: Connect to Database"
|
|
58
|
+
3. `http://localhost:3000` 입력
|
|
59
|
+
4. 왼쪽 사이드바에 테이블 목록 표시됨
|
|
60
|
+
5. `Cmd+Shift+P` → "DataContext: Harvest Metadata"
|
|
61
|
+
6. "Harvested 2 tables, 2 descriptions" 메시지 표시
|
|
62
|
+
7. Knowledge 패널에 수집된 설명 표시
|
|
63
|
+
|
|
64
|
+
**녹화 포인트:**
|
|
65
|
+
- 연결 후 테이블이 나타나는 순간
|
|
66
|
+
- Harvest 후 Knowledge가 채워지는 순간
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Demo 2: SQL Autocomplete (30초)
|
|
71
|
+
|
|
72
|
+
**목표:** 스키마 인식 SQL 자동완성
|
|
73
|
+
|
|
74
|
+
1. 새 파일 생성: `query.sql`
|
|
75
|
+
2. `SEL` 입력 → SELECT 스니펫 선택
|
|
76
|
+
3. `FROM u` 입력 → `users` 테이블 자동완성
|
|
77
|
+
4. `users.` 입력 → 컬럼 목록 표시 (id, email, name, status...)
|
|
78
|
+
5. 완성된 쿼리:
|
|
79
|
+
```sql
|
|
80
|
+
SELECT users.id, users.email, users.status
|
|
81
|
+
FROM users
|
|
82
|
+
WHERE users.status = 1
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**녹화 포인트:**
|
|
86
|
+
- 테이블 이름 자동완성
|
|
87
|
+
- 컬럼 목록 (타입, PK 표시)
|
|
88
|
+
- JOIN 시 연관 테이블 제안
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Demo 3: Hover Descriptions (20초)
|
|
93
|
+
|
|
94
|
+
**목표:** 테이블/컬럼에 마우스 올리면 비즈니스 설명 표시
|
|
95
|
+
|
|
96
|
+
1. SQL 파일에서 `users` 테이블에 마우스 hover
|
|
97
|
+
2. "Core user accounts" 툴팁 표시
|
|
98
|
+
3. `orders.total`에 마우스 hover
|
|
99
|
+
4. "Order total in cents" 툴팁 표시
|
|
100
|
+
|
|
101
|
+
**녹화 포인트:**
|
|
102
|
+
- Hover 시 Markdown 포맷의 풍부한 툴팁
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Demo 4: AI Context (Cursor에서) (45초)
|
|
107
|
+
|
|
108
|
+
**목표:** AI가 비즈니스 컨텍스트를 이해하고 정확한 SQL 생성
|
|
109
|
+
|
|
110
|
+
1. Cursor에서 DataContext MCP 활성화
|
|
111
|
+
2. Agent 모드에서 질문:
|
|
112
|
+
> "활성 사용자 중 $100 이상 주문한 사람 조회해줘"
|
|
113
|
+
3. AI 응답:
|
|
114
|
+
```sql
|
|
115
|
+
SELECT u.*
|
|
116
|
+
FROM users u
|
|
117
|
+
JOIN orders o ON o.user_id = u.id
|
|
118
|
+
WHERE u.status = 1 -- Active users (from context)
|
|
119
|
+
AND u.deleted_at IS NULL -- Soft-delete (from business rule)
|
|
120
|
+
GROUP BY u.id
|
|
121
|
+
HAVING SUM(o.total) > 10000 -- $100 in cents (from context)
|
|
122
|
+
```
|
|
123
|
+
4. 컨텍스트 사용됨 표시 (table descriptions, business rules)
|
|
124
|
+
|
|
125
|
+
**녹화 포인트:**
|
|
126
|
+
- AI가 status=1이 "active"임을 아는 것
|
|
127
|
+
- AI가 total이 "cents"임을 아는 것
|
|
128
|
+
- 컨텍스트 참조 표시
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Demo 5: Safety Guardrails (30초)
|
|
133
|
+
|
|
134
|
+
**목표:** 위험한 쿼리 차단
|
|
135
|
+
|
|
136
|
+
1. Cursor에서:
|
|
137
|
+
> "users 테이블 전체 삭제해줘"
|
|
138
|
+
2. AI가 DELETE 쿼리 시도
|
|
139
|
+
3. DataContext가 차단: "Read-only mode: DELETE statements are not allowed"
|
|
140
|
+
4. 또는:
|
|
141
|
+
> "전체 주문 데이터 조회해줘" (LIMIT 없이)
|
|
142
|
+
5. DataContext가 자동으로 LIMIT 1000 추가
|
|
143
|
+
|
|
144
|
+
**녹화 포인트:**
|
|
145
|
+
- 차단 메시지
|
|
146
|
+
- 자동 LIMIT 추가
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Demo 6: Learning Loop (30초)
|
|
151
|
+
|
|
152
|
+
**목표:** 피드백으로 학습
|
|
153
|
+
|
|
154
|
+
1. AI가 생성한 쿼리에 수정 필요
|
|
155
|
+
2. 사용자가 `AND created_at > '2024-01-01'` 추가
|
|
156
|
+
3. "Record Feedback" 실행
|
|
157
|
+
4. Metrics에서 correction rate 표시
|
|
158
|
+
5. 다음에 유사한 질문 시 AI가 날짜 필터 제안
|
|
159
|
+
|
|
160
|
+
**녹화 포인트:**
|
|
161
|
+
- 수정 전/후 SQL
|
|
162
|
+
- Metrics 화면
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## GIF 제작 도구
|
|
167
|
+
|
|
168
|
+
### 추천 도구
|
|
169
|
+
- **macOS**: Kap (https://getkap.co/) - 무료, 간단
|
|
170
|
+
- **Cross-platform**: ScreenToGif (Windows), Peek (Linux)
|
|
171
|
+
- **터미널**: asciinema (https://asciinema.org/)
|
|
172
|
+
|
|
173
|
+
### GIF 설정
|
|
174
|
+
- 해상도: 800x600 또는 1200x800
|
|
175
|
+
- FPS: 15-20
|
|
176
|
+
- 파일 크기: 2MB 이하 (GitHub 표시용)
|
|
177
|
+
- 루프: 무한 반복
|
|
178
|
+
|
|
179
|
+
### 파일명
|
|
180
|
+
- `demo-autocomplete.gif`
|
|
181
|
+
- `demo-harvest.gif`
|
|
182
|
+
- `demo-ai-context.gif`
|
|
183
|
+
- `demo-safety.gif`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 영상 제작 (Product Hunt/YouTube)
|
|
188
|
+
|
|
189
|
+
### 구성 (2분 이내)
|
|
190
|
+
1. **Intro (10초)**: 문제 제시 - "AI에게 매번 스키마 설명하기 지치셨나요?"
|
|
191
|
+
2. **Solution (10초)**: DataContext 소개
|
|
192
|
+
3. **Demo 1-4 (90초)**: 핵심 기능 시연
|
|
193
|
+
4. **Outro (10초)**: CTA - "지금 시작하세요"
|
|
194
|
+
|
|
195
|
+
### 배경음악
|
|
196
|
+
- 저작권 무료 음악 사용
|
|
197
|
+
- 볼륨 낮게 (나레이션보다 50% 낮게)
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 스크린샷 체크리스트
|
|
202
|
+
|
|
203
|
+
README 및 마케팅용:
|
|
204
|
+
- [ ] VS Code Extension 사이드바 (테이블 목록)
|
|
205
|
+
- [ ] SQL 자동완성 드롭다운
|
|
206
|
+
- [ ] Hover 툴팁
|
|
207
|
+
- [ ] Knowledge 패널 (카테고리별)
|
|
208
|
+
- [ ] 터미널에서 서버 실행 화면
|
|
209
|
+
- [ ] Cursor에서 AI 응답 (컨텍스트 포함)
|
|
210
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# DataContext Sync Guide
|
|
2
|
+
|
|
3
|
+
> 이 문서는 AI 코드 어시스턴트가 DataContext 프로젝트의 여러 컴포넌트 간 동기화를 유지하는 데 필요한 정보를 제공합니다.
|
|
4
|
+
|
|
5
|
+
## 프로젝트 구조 개요
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
DataContext-HQ/
|
|
9
|
+
├── datacontext-cli/ # CLI + MCP Server + REST API
|
|
10
|
+
├── vscode-datacontext/ # VS Code Extension
|
|
11
|
+
└── datacontext/ # Business docs, landing page
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 동기화 규칙
|
|
17
|
+
|
|
18
|
+
### 1. REST API ↔ VS Code Extension 동기화
|
|
19
|
+
|
|
20
|
+
**원칙:** CLI의 REST API 엔드포인트가 추가/변경되면, VS Code Extension도 업데이트해야 합니다.
|
|
21
|
+
|
|
22
|
+
#### 체크리스트
|
|
23
|
+
|
|
24
|
+
| CLI 변경 (`datacontext-cli`) | Extension 변경 (`vscode-datacontext`) |
|
|
25
|
+
|------------------------------|---------------------------------------|
|
|
26
|
+
| `src/api/server.ts`에 새 엔드포인트 추가 | `src/services/connectionManager.ts`에 메서드 추가 |
|
|
27
|
+
| `docs/API.md` 업데이트 | `README.md` API Endpoints 섹션 업데이트 |
|
|
28
|
+
| 새 기능/tool 추가 | `package.json` commands 추가 |
|
|
29
|
+
| — | `src/extension.ts`에 명령어 핸들러 추가 |
|
|
30
|
+
|
|
31
|
+
#### API 매핑 테이블
|
|
32
|
+
|
|
33
|
+
이 테이블은 CLI API와 Extension 메서드 간의 매핑을 보여줍니다:
|
|
34
|
+
|
|
35
|
+
| REST API Endpoint | HTTP Method | Extension Method | 상태 |
|
|
36
|
+
|-------------------|-------------|------------------|------|
|
|
37
|
+
| `/health` | GET | `connect()` 내부 체크 | ✅ |
|
|
38
|
+
| `/api/tables` | GET | `getTables()` | ✅ |
|
|
39
|
+
| `/api/tables/:name` | GET | `getTables()` 내부 | ✅ |
|
|
40
|
+
| `/api/tables/:name/description` | PUT | `setTableDescription()` | ✅ |
|
|
41
|
+
| `/api/tables/:table/columns/:column/description` | PUT | `setColumnDescription()` | ✅ |
|
|
42
|
+
| `/api/query` | POST | `SQLExecutor.execute()` | ✅ |
|
|
43
|
+
| `/api/query/estimate` | POST | `SQLExecutor.estimateCost()` | ✅ |
|
|
44
|
+
| `/api/harvest` | POST | `harvest()` | ✅ |
|
|
45
|
+
| `/api/knowledge` | GET | `getKnowledge()` | ✅ |
|
|
46
|
+
| `/api/feedback` | POST | `recordFeedback()` | ✅ |
|
|
47
|
+
| `/api/metrics` | GET | `getMetrics()` | ✅ |
|
|
48
|
+
| `/api/examples` | POST | `addQueryExample()` | ✅ |
|
|
49
|
+
| `/api/rules` | POST | `addBusinessRule()` | ✅ |
|
|
50
|
+
| `/api/rules/candidates` | GET | `getRuleCandidates()` | ✅ |
|
|
51
|
+
| `/api/context` | POST | (미구현 - 선택적) | ⚠️ |
|
|
52
|
+
| `/api/schema` | GET | (미구현 - 선택적) | ⚠️ |
|
|
53
|
+
| `/api/harvest/preview` | GET | (미구현 - 선택적) | ⚠️ |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### 2. MCP Tools ↔ REST API 동기화
|
|
58
|
+
|
|
59
|
+
**원칙:** MCP tool과 REST API는 동일한 `DataContextService`를 사용합니다. 새 기능은 두 곳 모두에 노출되어야 합니다.
|
|
60
|
+
|
|
61
|
+
#### 파일 매핑
|
|
62
|
+
|
|
63
|
+
| 기능 추가 시 | MCP 파일 | REST 파일 |
|
|
64
|
+
|-------------|----------|----------|
|
|
65
|
+
| 새 tool/endpoint | `src/mcp/tools.ts` | `src/api/server.ts` |
|
|
66
|
+
| 새 service 메서드 | `src/core/context-service.ts` | `src/core/context-service.ts` |
|
|
67
|
+
|
|
68
|
+
#### MCP Tools ↔ REST Endpoints 매핑
|
|
69
|
+
|
|
70
|
+
| MCP Tool | REST Endpoint | Service Method |
|
|
71
|
+
|----------|---------------|----------------|
|
|
72
|
+
| `query` | `POST /api/query` | `service.query()` |
|
|
73
|
+
| `list_tables` | `GET /api/tables` | `service.listTables()` |
|
|
74
|
+
| `describe_table` | `GET /api/tables/:name` | `service.getTableWithContext()` |
|
|
75
|
+
| `get_context` | `POST /api/context` | `service.buildContext()` |
|
|
76
|
+
| `add_description` | `PUT /api/tables/:name/description` | `service.setTableDescription()` |
|
|
77
|
+
| `harvest_metadata` | `POST /api/harvest` | `service.harvest()` |
|
|
78
|
+
| `estimate_cost` | `POST /api/query/estimate` | `service.estimateCost()` |
|
|
79
|
+
| `record_feedback` | `POST /api/feedback` | `service.recordFeedback()` |
|
|
80
|
+
| `get_metrics` | `GET /api/metrics` | `service.getMetricsSummary()` |
|
|
81
|
+
| `add_query_example` | `POST /api/examples` | `service.addQueryExample()` |
|
|
82
|
+
| `add_business_rule` | `POST /api/rules` | `service.addBusinessRule()` |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### 3. 문서 동기화
|
|
87
|
+
|
|
88
|
+
**원칙:** 코드 변경 시 관련 문서도 함께 업데이트합니다.
|
|
89
|
+
|
|
90
|
+
| 변경 유형 | 업데이트 필요 문서 |
|
|
91
|
+
|----------|-------------------|
|
|
92
|
+
| 새 CLI command | `datacontext-cli/README.md` |
|
|
93
|
+
| 새 REST endpoint | `datacontext-cli/docs/API.md` |
|
|
94
|
+
| 새 MCP tool | `datacontext-cli/README.md` MCP Tools 테이블 |
|
|
95
|
+
| 새 Extension command | `vscode-datacontext/README.md` Commands 테이블 |
|
|
96
|
+
| Extension 설정 추가 | `vscode-datacontext/README.md` Configuration 섹션 |
|
|
97
|
+
| 데모 시나리오 변경 | `datacontext-cli/docs/DEMO_SCRIPT.md` |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 버전 관리
|
|
102
|
+
|
|
103
|
+
### 버전 위치
|
|
104
|
+
|
|
105
|
+
| 컴포넌트 | 파일 | 필드 |
|
|
106
|
+
|----------|------|------|
|
|
107
|
+
| CLI | `datacontext-cli/package.json` | `"version"` |
|
|
108
|
+
| Extension | `vscode-datacontext/package.json` | `"version"` |
|
|
109
|
+
|
|
110
|
+
### 버전 증가 규칙
|
|
111
|
+
|
|
112
|
+
- **Patch (0.0.X)**: 버그 수정, 문서 업데이트
|
|
113
|
+
- **Minor (0.X.0)**: 새 기능 추가 (하위 호환)
|
|
114
|
+
- **Major (X.0.0)**: Breaking changes
|
|
115
|
+
|
|
116
|
+
### CHANGELOG 업데이트
|
|
117
|
+
|
|
118
|
+
각 릴리스에서 다음 파일 업데이트:
|
|
119
|
+
- `datacontext-cli/CHANGELOG.md`
|
|
120
|
+
- `vscode-datacontext/CHANGELOG.md`
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 타입 동기화
|
|
125
|
+
|
|
126
|
+
### CLI 타입 → Extension 타입
|
|
127
|
+
|
|
128
|
+
CLI에서 정의된 타입이 Extension에서도 필요할 때, 동일한 구조로 재정의합니다.
|
|
129
|
+
|
|
130
|
+
#### 예시: QueryFeedback 타입
|
|
131
|
+
|
|
132
|
+
**CLI (`src/core/feedback-manager.ts`):**
|
|
133
|
+
```typescript
|
|
134
|
+
export interface QueryFeedback {
|
|
135
|
+
originalSql: string;
|
|
136
|
+
correctedSql?: string;
|
|
137
|
+
intent?: string;
|
|
138
|
+
feedbackType: 'success' | 'corrected' | 'failed' | 'rejected';
|
|
139
|
+
tables?: string[];
|
|
140
|
+
// ...
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Extension (`src/services/connectionManager.ts`):**
|
|
145
|
+
```typescript
|
|
146
|
+
export interface QueryFeedback {
|
|
147
|
+
originalSql: string;
|
|
148
|
+
correctedSql?: string;
|
|
149
|
+
intent?: string;
|
|
150
|
+
feedbackType: 'success' | 'corrected' | 'failed' | 'rejected';
|
|
151
|
+
tables?: string[];
|
|
152
|
+
errorMessage?: string;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**주의:** Extension은 API Response 기준으로 타입을 정의합니다. CLI 내부 타입과 100% 일치할 필요 없음.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 자동 동기화 체크리스트
|
|
161
|
+
|
|
162
|
+
AI 어시스턴트가 코드 변경 시 확인해야 할 사항:
|
|
163
|
+
|
|
164
|
+
### REST API 엔드포인트 추가 시
|
|
165
|
+
- [ ] `src/api/server.ts`에 라우트 추가
|
|
166
|
+
- [ ] `docs/API.md`에 문서 추가
|
|
167
|
+
- [ ] `vscode-datacontext/src/services/connectionManager.ts`에 메서드 추가
|
|
168
|
+
- [ ] `vscode-datacontext/README.md` API Endpoints 섹션 업데이트
|
|
169
|
+
|
|
170
|
+
### MCP Tool 추가 시
|
|
171
|
+
- [ ] `src/mcp/tools.ts`의 `getMcpTools()` 에 추가
|
|
172
|
+
- [ ] `src/mcp/tools.ts`의 `handleToolCall()` switch에 핸들러 추가
|
|
173
|
+
- [ ] `README.md` MCP Tools 테이블 업데이트
|
|
174
|
+
|
|
175
|
+
### Extension Command 추가 시
|
|
176
|
+
- [ ] `package.json` contributes.commands에 추가
|
|
177
|
+
- [ ] `src/extension.ts`에 핸들러 등록
|
|
178
|
+
- [ ] `README.md` Commands 테이블 업데이트
|
|
179
|
+
- [ ] 필요 시 `package.json` keybindings/menus 추가
|
|
180
|
+
|
|
181
|
+
### 새 설정 옵션 추가 시
|
|
182
|
+
- [ ] `package.json` contributes.configuration에 추가
|
|
183
|
+
- [ ] `README.md` Configuration 섹션 업데이트
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 테스트 동기화
|
|
188
|
+
|
|
189
|
+
| 기능 영역 | 테스트 파일 |
|
|
190
|
+
|----------|------------|
|
|
191
|
+
| Knowledge Store | `tests/knowledge-store.test.ts` |
|
|
192
|
+
| MCP Tools | `tests/mcp-tools.test.ts` |
|
|
193
|
+
| PostgreSQL Adapter | `tests/postgres-adapter.test.ts` |
|
|
194
|
+
| SQLite Adapter | `tests/sqlite-adapter.test.ts` |
|
|
195
|
+
| Safety Validator | `tests/safety-validator.test.ts` |
|
|
196
|
+
|
|
197
|
+
새 기능 추가 시 관련 테스트도 추가해야 합니다.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 참고: 의존성 관계
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
205
|
+
│ vscode-datacontext │
|
|
206
|
+
│ (VS Code Extension - UI Layer) │
|
|
207
|
+
└─────────────────────────┬───────────────────────────────────┘
|
|
208
|
+
│ HTTP (REST API)
|
|
209
|
+
▼
|
|
210
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
211
|
+
│ datacontext-cli │
|
|
212
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
213
|
+
│ │ api/ │ │ mcp/ │ │ cli/ │ │
|
|
214
|
+
│ │ (REST) │ │ (MCP) │ │ (Terminal) │ │
|
|
215
|
+
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
|
216
|
+
│ │ │ │ │
|
|
217
|
+
│ └────────────────┼────────────────┘ │
|
|
218
|
+
│ ▼ │
|
|
219
|
+
│ ┌─────────────────────────────────────────────────────┐ │
|
|
220
|
+
│ │ core/ │ │
|
|
221
|
+
│ │ (DataContextService - platform-agnostic) │ │
|
|
222
|
+
│ └─────────────────────────┬───────────────────────────┘ │
|
|
223
|
+
│ │ │
|
|
224
|
+
│ ┌───────────┬─────────────┼─────────────┬───────────┐ │
|
|
225
|
+
│ ▼ ▼ ▼ ▼ ▼ │
|
|
226
|
+
│ adapters/ knowledge/ safety/ schema/ feedback/ │
|
|
227
|
+
└─────────────────────────────────────────────────────────────┘
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**핵심 원칙:**
|
|
231
|
+
- `core/`는 platform-agnostic - `mcp/`, `api/`를 import하지 않음
|
|
232
|
+
- `mcp/`와 `api/`는 서로를 import하지 않음 - 둘 다 `core/`만 사용
|
|
233
|
+
- Extension은 REST API만 사용 - CLI 코드 직접 import 불가
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 변경 이력
|
|
238
|
+
|
|
239
|
+
| 날짜 | 변경 내용 |
|
|
240
|
+
|------|----------|
|
|
241
|
+
| 2026-01-01 | 초기 문서 작성 |
|
|
242
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kiyeonjeon21/datacontext",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "AI-native database context layer - Make AI understand your data better",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "node dist/index.js",
|
|
14
|
+
"serve": "node dist/api/start-server.js",
|
|
14
15
|
"lint": "eslint src --ext .ts",
|
|
15
16
|
"test": "vitest run",
|
|
16
17
|
"test:watch": "vitest",
|
|
@@ -42,10 +43,12 @@
|
|
|
42
43
|
"node": ">=18.0.0"
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
46
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
45
47
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
46
48
|
"better-sqlite3": "^12.5.0",
|
|
47
49
|
"commander": "^12.1.0",
|
|
48
50
|
"cors": "^2.8.5",
|
|
51
|
+
"dotenv": "^17.2.3",
|
|
49
52
|
"express": "^5.2.1",
|
|
50
53
|
"mysql2": "^3.16.0",
|
|
51
54
|
"pg": "^8.13.0",
|
package/src/api/server.ts
CHANGED
|
@@ -403,6 +403,166 @@ export function createApiServer(config: ApiServerConfig): express.Application {
|
|
|
403
403
|
}
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
+
// ============================================================
|
|
407
|
+
// Glossary (Business Terms) Endpoints
|
|
408
|
+
// ============================================================
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* List all business terms
|
|
412
|
+
* GET /api/terms?category=status&table=users
|
|
413
|
+
*/
|
|
414
|
+
app.get('/api/terms', (_req: Request, res: Response) => {
|
|
415
|
+
try {
|
|
416
|
+
const category = _req.query.category as string | undefined;
|
|
417
|
+
const table = _req.query.table as string | undefined;
|
|
418
|
+
|
|
419
|
+
let terms = service.getBusinessTerms();
|
|
420
|
+
|
|
421
|
+
// Apply filters
|
|
422
|
+
if (category) {
|
|
423
|
+
terms = terms.filter(t => t.category === category);
|
|
424
|
+
}
|
|
425
|
+
if (table) {
|
|
426
|
+
terms = terms.filter(t => t.appliesTo?.tables?.includes(table));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
res.json({
|
|
430
|
+
count: terms.length,
|
|
431
|
+
terms,
|
|
432
|
+
});
|
|
433
|
+
} catch (error) {
|
|
434
|
+
res.status(500).json({
|
|
435
|
+
error: error instanceof Error ? error.message : 'Failed to get terms'
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Search business terms
|
|
442
|
+
* GET /api/terms/search?q=활성
|
|
443
|
+
*/
|
|
444
|
+
app.get('/api/terms/search', (_req: Request, res: Response) => {
|
|
445
|
+
try {
|
|
446
|
+
const query = _req.query.q as string;
|
|
447
|
+
|
|
448
|
+
if (!query) {
|
|
449
|
+
res.status(400).json({ error: 'q (query) parameter is required' });
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const terms = service.findMatchingTerms(query);
|
|
454
|
+
|
|
455
|
+
res.json({
|
|
456
|
+
query,
|
|
457
|
+
count: terms.length,
|
|
458
|
+
terms,
|
|
459
|
+
suggestedConditions: terms
|
|
460
|
+
.filter(t => t.sqlExpression)
|
|
461
|
+
.map(t => t.sqlExpression),
|
|
462
|
+
});
|
|
463
|
+
} catch (error) {
|
|
464
|
+
res.status(500).json({
|
|
465
|
+
error: error instanceof Error ? error.message : 'Failed to search terms'
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Add a business term manually
|
|
472
|
+
* POST /api/terms
|
|
473
|
+
* Body: { term, definition, sql?, synonyms?, tables?, category? }
|
|
474
|
+
*/
|
|
475
|
+
app.post('/api/terms', async (req: Request, res: Response) => {
|
|
476
|
+
try {
|
|
477
|
+
const { term, definition, sql, synonyms, tables, category } = req.body;
|
|
478
|
+
|
|
479
|
+
if (!term || !definition) {
|
|
480
|
+
res.status(400).json({ error: 'term and definition are required' });
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const added = await service.addBusinessTerm(term, definition, {
|
|
485
|
+
sqlExpression: sql,
|
|
486
|
+
synonyms,
|
|
487
|
+
appliesTo: tables ? { tables } : undefined,
|
|
488
|
+
category,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
res.json({ success: true, term: added });
|
|
492
|
+
} catch (error) {
|
|
493
|
+
res.status(500).json({
|
|
494
|
+
error: error instanceof Error ? error.message : 'Failed to add term'
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Generate glossary from raw terms using AI
|
|
501
|
+
* POST /api/terms/generate
|
|
502
|
+
* Body: { terms: string }
|
|
503
|
+
*/
|
|
504
|
+
app.post('/api/terms/generate', async (req: Request, res: Response) => {
|
|
505
|
+
try {
|
|
506
|
+
const { terms } = req.body;
|
|
507
|
+
|
|
508
|
+
if (!terms) {
|
|
509
|
+
res.status(400).json({ error: 'terms is required' });
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const generated = await service.generateGlossary(terms);
|
|
514
|
+
|
|
515
|
+
res.json({
|
|
516
|
+
success: true,
|
|
517
|
+
generated: generated.length,
|
|
518
|
+
terms: generated,
|
|
519
|
+
});
|
|
520
|
+
} catch (error) {
|
|
521
|
+
res.status(500).json({
|
|
522
|
+
error: error instanceof Error ? error.message : 'Failed to generate glossary'
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Delete a business term
|
|
529
|
+
* DELETE /api/terms/:id
|
|
530
|
+
*/
|
|
531
|
+
app.delete('/api/terms/:id', async (req: Request, res: Response) => {
|
|
532
|
+
try {
|
|
533
|
+
const { id } = req.params;
|
|
534
|
+
await service.deleteBusinessTerm(id);
|
|
535
|
+
res.json({ success: true, deleted: id });
|
|
536
|
+
} catch (error) {
|
|
537
|
+
res.status(500).json({
|
|
538
|
+
error: error instanceof Error ? error.message : 'Failed to delete term'
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Enhance a query with glossary terms
|
|
545
|
+
* POST /api/terms/enhance
|
|
546
|
+
* Body: { query: string }
|
|
547
|
+
*/
|
|
548
|
+
app.post('/api/terms/enhance', async (req: Request, res: Response) => {
|
|
549
|
+
try {
|
|
550
|
+
const { query } = req.body;
|
|
551
|
+
|
|
552
|
+
if (!query) {
|
|
553
|
+
res.status(400).json({ error: 'query is required' });
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const result = await service.enhanceQuery(query);
|
|
558
|
+
res.json(result);
|
|
559
|
+
} catch (error) {
|
|
560
|
+
res.status(500).json({
|
|
561
|
+
error: error instanceof Error ? error.message : 'Failed to enhance query'
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
406
566
|
// ============================================================
|
|
407
567
|
// Error Handler
|
|
408
568
|
// ============================================================
|