@dongju101/gemini-mcp 0.1.5 → 0.1.6
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/README.md +56 -16
- package/dist/changeMode.d.ts +1 -1
- package/dist/changeMode.d.ts.map +1 -1
- package/dist/changeMode.js +11 -13
- package/dist/changeMode.js.map +1 -1
- package/dist/progress.d.ts +49 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +314 -0
- package/dist/progress.js.map +1 -0
- package/dist/runner.d.ts +10 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +170 -73
- package/dist/runner.js.map +1 -1
- package/dist/server.d.ts +2 -53
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +180 -444
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +11 -0
- package/dist/util.js.map +1 -0
- package/dist/workspace.d.ts +44 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +395 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,16 +17,30 @@ gemini # 최초 실행 시 OAuth 인증 진행
|
|
|
17
17
|
|
|
18
18
|
설치 없이 `npx`로 즉시 실행할 수 있다.
|
|
19
19
|
|
|
20
|
-
**Claude Code
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
**Claude Code (프로젝트별 `.mcp.json` 권장):**
|
|
21
|
+
|
|
22
|
+
프로젝트 루트에 `.mcp.json` 파일을 생성한다.
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"gemini": {
|
|
28
|
+
"type": "stdio",
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "@dongju101/gemini-mcp"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
23
34
|
```
|
|
24
35
|
|
|
36
|
+
이 방식은 해당 프로젝트에서만 gemini MCP server가 기동되어 다른 세션에 영향을 주지 않는다.
|
|
37
|
+
`.mcp.json`을 `.gitignore`에 추가하거나 팀과 공유할 수 있다.
|
|
38
|
+
|
|
25
39
|
**Claude Desktop (`claude_desktop_config.json`):**
|
|
26
40
|
```json
|
|
27
41
|
{
|
|
28
42
|
"mcpServers": {
|
|
29
|
-
"gemini
|
|
43
|
+
"gemini": {
|
|
30
44
|
"command": "npx",
|
|
31
45
|
"args": ["-y", "@dongju101/gemini-mcp"]
|
|
32
46
|
}
|
|
@@ -39,7 +53,18 @@ claude mcp add gemini-mcp -s user -- npx -y @dongju101/gemini-mcp
|
|
|
39
53
|
GEMINI_MCP_HOME=/custom/path npx @dongju101/gemini-mcp
|
|
40
54
|
```
|
|
41
55
|
|
|
42
|
-
기본 Workspace는
|
|
56
|
+
기본 Workspace는 프로젝트 루트의 `.gemini-mcp/`에 자동 생성된다.
|
|
57
|
+
`.gitignore`에 `.gemini-mcp/`를 추가하여 커밋에서 제외한다.
|
|
58
|
+
|
|
59
|
+
**기존 `~/.gemini-mcp/` 사용자 마이그레이션:**
|
|
60
|
+
|
|
61
|
+
이전 버전을 사용 중이었다면, `~/.gemini-mcp/`에 session 데이터가 남아 있을 수 있다.
|
|
62
|
+
필요한 데이터를 프로젝트 루트의 `.gemini-mcp/`로 복사하거나 삭제한다.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 이전 데이터 제거 (선택)
|
|
66
|
+
rm -rf ~/.gemini-mcp/
|
|
67
|
+
```
|
|
43
68
|
|
|
44
69
|
## 소스에서 설치
|
|
45
70
|
|
|
@@ -50,13 +75,23 @@ npm install
|
|
|
50
75
|
npm run build
|
|
51
76
|
```
|
|
52
77
|
|
|
53
|
-
|
|
54
|
-
|
|
78
|
+
프로젝트 루트에 `.mcp.json`을 생성한다.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"mcpServers": {
|
|
83
|
+
"gemini": {
|
|
84
|
+
"type": "stdio",
|
|
85
|
+
"command": "node",
|
|
86
|
+
"args": ["/path/to/gemini_mcp/dist/server.js"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
55
90
|
```
|
|
56
91
|
|
|
57
92
|
## 설정
|
|
58
93
|
|
|
59
|
-
|
|
94
|
+
`.gemini-mcp/config.json`으로 Server 동작을 제어한다.
|
|
60
95
|
Config 파일이 없거나 잘못된 경우 각 항목의 기본값이 적용된다.
|
|
61
96
|
|
|
62
97
|
```json
|
|
@@ -72,8 +107,8 @@ Gemini가 프로젝트 파일에 접근할 수 있는지를 제어한다.
|
|
|
72
107
|
|
|
73
108
|
| 값 | 동작 |
|
|
74
109
|
|------|------|
|
|
75
|
-
| `true` | Project Root에서 실행. Gemini가 프로젝트 파일을 읽고 분석 가능. |
|
|
76
|
-
| `false`
|
|
110
|
+
| `true` (기본값) | Project Root에서 실행. Gemini가 프로젝트 파일을 읽고 분석 가능. |
|
|
111
|
+
| `false` | 격리된 Workspace에서 실행. 프로젝트 파일 접근 불가. |
|
|
77
112
|
|
|
78
113
|
### Model 선택 (model)
|
|
79
114
|
|
|
@@ -91,18 +126,19 @@ Tool 호출 시 `model` Parameter를 직접 지정하면 Config 설정보다 우
|
|
|
91
126
|
|
|
92
127
|
```bash
|
|
93
128
|
# 기본 모델 + 파일 접근 활성화
|
|
94
|
-
echo '{"file_access": true}' >
|
|
129
|
+
echo '{"file_access": true}' > .gemini-mcp/config.json
|
|
95
130
|
|
|
96
131
|
# 특정 Model 고정 + 파일 접근 활성화
|
|
97
|
-
echo '{"file_access": true, "model": "gemini-3-flash-preview"}' >
|
|
132
|
+
echo '{"file_access": true, "model": "gemini-3-flash-preview"}' > .gemini-mcp/config.json
|
|
98
133
|
```
|
|
99
134
|
|
|
100
135
|
## Tool 목록
|
|
101
136
|
|
|
102
137
|
| Tool | Parameter | 용도 |
|
|
103
138
|
|------|-----------|------|
|
|
104
|
-
| `gemini_chat` | `message`, `model`, `session`, `sandbox`, `
|
|
139
|
+
| `gemini_chat` | `message`, `model`, `session`, `sandbox`, `change_mode`, `include_meta` | Gemini와 대화형 질의. `--resume`으로 이전 대화 맥락 자동 유지. |
|
|
105
140
|
| `gemini_reset` | `session` | 대화 Session 초기화. 다음 호출부터 새 대화 시작. |
|
|
141
|
+
| `gemini_fetch_chunk` | `cache_key`, `chunk_index` | `change_mode` 응답이 여러 chunk로 분할된 경우 후속 chunk 조회. |
|
|
106
142
|
|
|
107
143
|
### gemini_chat Parameter
|
|
108
144
|
|
|
@@ -112,7 +148,11 @@ echo '{"file_access": true, "model": "gemini-3-flash-preview"}' > ~/.gemini-mcp/
|
|
|
112
148
|
| `model` | `""` (gemini-3-pro-preview) | 사용할 모델 |
|
|
113
149
|
| `session` | `"default"` | Session 이름. 독립적인 대화 맥락 유지 |
|
|
114
150
|
| `sandbox` | `false` | Sandbox mode로 code를 격리 환경에서 실행 |
|
|
115
|
-
| `
|
|
151
|
+
| `change_mode` | `false` | 코드 수정 요청 시 활성화. 응답을 구조화된 OLD/NEW 포맷으로 파싱하여 Edit tool 적용 가능. |
|
|
152
|
+
| `include_meta` | `false` | true 시 응답 footer에 사용 model명과 token 수를 표시. `change_mode`와 함께 사용 시 아래 제약사항 참고. |
|
|
153
|
+
|
|
154
|
+
> **`include_meta` + `change_mode` 결합 시 제약사항:**
|
|
155
|
+
> `change_mode: true`와 `include_meta: true`를 동시에 사용하는 경우, change_mode 파싱이 성공하여 edits가 존재하면 구조화된 편집 결과를 즉시 반환한다. 이때 meta footer(model명, token 수)는 반환 결과에 포함되지 않는다. 파싱이 실패하여 edits가 없는 경우에는 원본 응답에 meta footer가 포함된 상태로 반환된다.
|
|
116
156
|
|
|
117
157
|
## Multi-Session
|
|
118
158
|
|
|
@@ -130,7 +170,7 @@ Terminal B (backend 작업):
|
|
|
130
170
|
```
|
|
131
171
|
|
|
132
172
|
- `session` 미지정 시 `"default"` Session 사용
|
|
133
|
-
- Session별 Workspace가
|
|
173
|
+
- Session별 Workspace가 `.gemini-mcp/sessions/{session_name}/`에 자동 생성
|
|
134
174
|
- Claude Code를 종료했다 재시작해도 `--resume`으로 직전 대화를 이어갈 수 있다
|
|
135
175
|
- `gemini_reset(session="frontend")`: 특정 Session만 초기화
|
|
136
176
|
- `gemini_reset()`: 전체 Session 초기화
|
|
@@ -150,7 +190,7 @@ gemini_mcp/ # 소스 Repository
|
|
|
150
190
|
tsconfig.json
|
|
151
191
|
vitest.config.ts
|
|
152
192
|
|
|
153
|
-
|
|
193
|
+
.gemini-mcp/ # Runtime Workspace (프로젝트 루트에 자동 생성)
|
|
154
194
|
config.json # Server 설정 (file_access, model)
|
|
155
195
|
.gemini/
|
|
156
196
|
settings.json # CLI 설정 (thinkingConfig, security.auth)
|
package/dist/changeMode.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface ChangeEdit {
|
|
|
17
17
|
* Gemini prompt에 prepend할 OLD/NEW 포맷 지시문.
|
|
18
18
|
* change_mode=true 시 message 앞에 추가된다.
|
|
19
19
|
*/
|
|
20
|
-
export declare const CHANGE_MODE_INSTRUCTIONS = "
|
|
20
|
+
export declare const CHANGE_MODE_INSTRUCTIONS = "[CHANGE MODE] For ALL code changes use this exact format:\n\n**FILE: path/to/file:startLine-endLine**\n```\nOLD:\n<original lines only>\n---\nNEW:\n<replacement lines>\n```\nRules: one block per change region; no context lines; line numbers from original file.\n\n";
|
|
21
21
|
/**
|
|
22
22
|
* Gemini 응답 텍스트에서 ChangeEdit[] 를 추출한다.
|
|
23
23
|
*
|
package/dist/changeMode.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changeMode.d.ts","sourceRoot":"","sources":["../src/changeMode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"changeMode.d.ts","sourceRoot":"","sources":["../src/changeMode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,6QAapC,CAAC;AAWF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAOrE;AA8DD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAoBvD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,QAAQ,SAAS,GAAG,MAAM,EAAE,CA0B3E;AAYD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAoBxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAW9C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUpC,sBAAsB;IACtB,KAAK,IAAI,IAAI;CAGd;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
package/dist/changeMode.js
CHANGED
|
@@ -15,23 +15,17 @@ exports.chunkEdits = chunkEdits;
|
|
|
15
15
|
* change_mode=true 시 message 앞에 추가된다.
|
|
16
16
|
*/
|
|
17
17
|
exports.CHANGE_MODE_INSTRUCTIONS = `\
|
|
18
|
-
|
|
18
|
+
[CHANGE MODE] For ALL code changes use this exact format:
|
|
19
19
|
|
|
20
|
-
**FILE:
|
|
20
|
+
**FILE: path/to/file:startLine-endLine**
|
|
21
21
|
\`\`\`
|
|
22
22
|
OLD:
|
|
23
|
-
<
|
|
23
|
+
<original lines only>
|
|
24
24
|
---
|
|
25
25
|
NEW:
|
|
26
|
-
<replacement
|
|
26
|
+
<replacement lines>
|
|
27
27
|
\`\`\`
|
|
28
|
-
|
|
29
|
-
Rules:
|
|
30
|
-
- Use one block per contiguous change region.
|
|
31
|
-
- Line numbers refer to the original file before any changes.
|
|
32
|
-
- Do NOT include surrounding unchanged context lines.
|
|
33
|
-
- If adding new code with no replacement, set OLD section to empty and use the insertion line number for both oldStartLine and oldEndLine.
|
|
34
|
-
- After all change blocks, you may add a brief explanation.
|
|
28
|
+
Rules: one block per change region; no context lines; line numbers from original file.
|
|
35
29
|
|
|
36
30
|
`;
|
|
37
31
|
const FILE_HEADER_RE = /\*\*FILE:\s*([^\s:*]+):(\d+)-(\d+)\*\*/g;
|
|
@@ -53,12 +47,16 @@ function parseChangeModeResponse(content) {
|
|
|
53
47
|
function parsePattern1(content) {
|
|
54
48
|
const edits = [];
|
|
55
49
|
const fileMatches = [...content.matchAll(FILE_HEADER_RE)];
|
|
56
|
-
for (
|
|
50
|
+
for (let i = 0; i < fileMatches.length; i++) {
|
|
51
|
+
const fileMatch = fileMatches[i];
|
|
57
52
|
const filename = fileMatch[1];
|
|
58
53
|
const oldStartLine = parseInt(fileMatch[2], 10);
|
|
59
54
|
const oldEndLine = parseInt(fileMatch[3], 10);
|
|
60
55
|
const matchEnd = (fileMatch.index ?? 0) + fileMatch[0].length;
|
|
61
|
-
const
|
|
56
|
+
const nextHeaderStart = i + 1 < fileMatches.length
|
|
57
|
+
? (fileMatches[i + 1].index ?? content.length)
|
|
58
|
+
: content.length;
|
|
59
|
+
const remaining = content.slice(matchEnd, nextHeaderStart);
|
|
62
60
|
const blockMatch = BLOCK_OLD_NEW_RE.exec(remaining);
|
|
63
61
|
if (!blockMatch)
|
|
64
62
|
continue;
|
package/dist/changeMode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changeMode.js","sourceRoot":"","sources":["../src/changeMode.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;
|
|
1
|
+
{"version":3,"file":"changeMode.js","sourceRoot":"","sources":["../src/changeMode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress 추적 및 Tool description 생성.
|
|
3
|
+
* ProgressTracker는 MCP tool 실행 중 진행 상황을 reportProgress callback으로
|
|
4
|
+
* 주기적으로 보고한다. toolDesc는 Gemini CLI 네이티브 스타일의 tool label을 생성한다.
|
|
5
|
+
*/
|
|
6
|
+
import type { GeminiResponse, RunnerEvent } from "./types";
|
|
7
|
+
export declare class ProgressTracker {
|
|
8
|
+
private static readonly TOTAL;
|
|
9
|
+
private static readonly TICK_INTERVAL;
|
|
10
|
+
private static readonly PRE_INIT_CAP;
|
|
11
|
+
private static readonly RESPONSE_CAP;
|
|
12
|
+
private static readonly SQRT_K;
|
|
13
|
+
private static readonly KEEP_ALIVE_INTERVAL;
|
|
14
|
+
private static readonly REPORT_CIRCUIT_BREAK_THRESHOLD;
|
|
15
|
+
private static readonly INIT_PROGRESS;
|
|
16
|
+
private static readonly MSG_USER_PROGRESS;
|
|
17
|
+
private static readonly MSG_ASSISTANT_MIN_INC;
|
|
18
|
+
private static readonly MSG_ASSISTANT_RATE;
|
|
19
|
+
private static readonly TOOL_USE_INC;
|
|
20
|
+
private static readonly TOOL_RESULT_INC;
|
|
21
|
+
private static readonly FALLBACK_PROGRESS;
|
|
22
|
+
private progress;
|
|
23
|
+
private label;
|
|
24
|
+
private reportProgress;
|
|
25
|
+
private tickTimer;
|
|
26
|
+
private initTime;
|
|
27
|
+
private initReceived;
|
|
28
|
+
private lastKeepAliveTime;
|
|
29
|
+
private dirty;
|
|
30
|
+
private reporting;
|
|
31
|
+
private reportFailCount;
|
|
32
|
+
private lastToolName;
|
|
33
|
+
private lastToolDesc;
|
|
34
|
+
start(reportFn: (p: {
|
|
35
|
+
progress: number;
|
|
36
|
+
total: number;
|
|
37
|
+
message?: string;
|
|
38
|
+
}) => Promise<void>): Promise<void>;
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
private timeTarget;
|
|
41
|
+
private startTickLoop;
|
|
42
|
+
private report;
|
|
43
|
+
finish(): Promise<void>;
|
|
44
|
+
notify(event: Exclude<RunnerEvent, {
|
|
45
|
+
type: "_response";
|
|
46
|
+
data: GeminiResponse;
|
|
47
|
+
}>): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAoI3D,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAO;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAO;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAK;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAM;IAC1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAM;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAAK;IAE3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAM;IAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAM;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAK;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAK;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAK;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAM;IAE/C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,cAAc,CAEN;IAChB,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,YAAY,CAAM;IAEpB,KAAK,CACT,QAAQ,EAAE,CAAC,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GACpF,OAAO,CAAC,IAAI,CAAC;IAQV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;YAuDP,MAAM;IAYd,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOvB,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA4EtG"}
|
package/dist/progress.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Progress 추적 및 Tool description 생성.
|
|
4
|
+
* ProgressTracker는 MCP tool 실행 중 진행 상황을 reportProgress callback으로
|
|
5
|
+
* 주기적으로 보고한다. toolDesc는 Gemini CLI 네이티브 스타일의 tool label을 생성한다.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ProgressTracker = void 0;
|
|
9
|
+
// --- toolDesc helpers ---
|
|
10
|
+
// truncation 길이 상수
|
|
11
|
+
const SNIPPET_SHORT = 20; // 짧은 코드 snippet (old/new string)
|
|
12
|
+
const SNIPPET_CMD = 60; // shell command
|
|
13
|
+
const SNIPPET_QUERY = 40; // web search query
|
|
14
|
+
const SNIPPET_URL = 50; // URL
|
|
15
|
+
const SNIPPET_MEMORY = 30; // memory content
|
|
16
|
+
function descFilePath(_p, sh, fp) {
|
|
17
|
+
return fp ? sh(fp) : "";
|
|
18
|
+
}
|
|
19
|
+
function descWrite(_p, sh, fp) {
|
|
20
|
+
return fp ? `Writing to ${sh(fp)}` : "";
|
|
21
|
+
}
|
|
22
|
+
function descReplace(p, sh, fp) {
|
|
23
|
+
const old = (p.old_string ?? p.search ?? "");
|
|
24
|
+
const neu = (p.new_string ?? p.replace ?? "");
|
|
25
|
+
if (!old && fp)
|
|
26
|
+
return `Create ${sh(fp)}`;
|
|
27
|
+
const oldSnip = old.split("\n")[0].substring(0, SNIPPET_SHORT) + (old.length > SNIPPET_SHORT ? "..." : "");
|
|
28
|
+
const newSnip = neu.split("\n")[0].substring(0, SNIPPET_SHORT) + (neu.length > SNIPPET_SHORT ? "..." : "");
|
|
29
|
+
return fp ? `${sh(fp)}: ${oldSnip} -> ${newSnip}` : `${oldSnip} -> ${newSnip}`;
|
|
30
|
+
}
|
|
31
|
+
function descListDir(p, sh) {
|
|
32
|
+
return sh((p.path ?? p.dir_path ?? p.directory ?? "."));
|
|
33
|
+
}
|
|
34
|
+
function descGrep(p, sh) {
|
|
35
|
+
const pattern = (p.pattern ?? "");
|
|
36
|
+
const include = (p.include ?? p.glob ?? "");
|
|
37
|
+
const dir = (p.path ?? p.dir_path ?? "");
|
|
38
|
+
let desc = `'${pattern}'`;
|
|
39
|
+
if (include)
|
|
40
|
+
desc += ` in ${include}`;
|
|
41
|
+
if (dir)
|
|
42
|
+
desc += ` within ${sh(dir)}`;
|
|
43
|
+
return desc;
|
|
44
|
+
}
|
|
45
|
+
function descShell(p) {
|
|
46
|
+
const cmd = (p.command ?? p.cmd ?? "").trim();
|
|
47
|
+
return cmd.length > SNIPPET_CMD ? cmd.substring(0, SNIPPET_CMD - 3) + "..." : cmd;
|
|
48
|
+
}
|
|
49
|
+
function descSearch(p) {
|
|
50
|
+
const query = (p.query ?? "");
|
|
51
|
+
return query
|
|
52
|
+
? `Searching for: "${query.substring(0, SNIPPET_QUERY)}${query.length > SNIPPET_QUERY ? "..." : ""}"`
|
|
53
|
+
: "";
|
|
54
|
+
}
|
|
55
|
+
function descFetch(p) {
|
|
56
|
+
const url = (p.url ?? "");
|
|
57
|
+
return url.length > SNIPPET_URL ? url.substring(0, SNIPPET_URL - 3) + "..." : url;
|
|
58
|
+
}
|
|
59
|
+
function descMemory(p) {
|
|
60
|
+
const content = (p.content ?? p.text ?? "");
|
|
61
|
+
return content
|
|
62
|
+
? `"${content.substring(0, SNIPPET_MEMORY)}${content.length > SNIPPET_MEMORY ? "..." : ""}"`
|
|
63
|
+
: "";
|
|
64
|
+
}
|
|
65
|
+
const TOOL_DESC_MAP = {
|
|
66
|
+
read_file: descFilePath,
|
|
67
|
+
read_many_files: descFilePath,
|
|
68
|
+
write_file: descWrite,
|
|
69
|
+
create_file: descWrite,
|
|
70
|
+
replace: descReplace,
|
|
71
|
+
edit_file: descReplace,
|
|
72
|
+
replace_in_file: descReplace,
|
|
73
|
+
delete_file: descFilePath,
|
|
74
|
+
list_directory: (p, sh) => descListDir(p, sh),
|
|
75
|
+
ls: (p, sh) => descListDir(p, sh),
|
|
76
|
+
glob: (p, sh) => {
|
|
77
|
+
const pattern = (p.pattern ?? "*");
|
|
78
|
+
const dir = (p.path ?? p.dir_path ?? "");
|
|
79
|
+
return dir ? `'${pattern}' within ${sh(dir)}` : `'${pattern}'`;
|
|
80
|
+
},
|
|
81
|
+
grep_search: (p, sh) => descGrep(p, sh),
|
|
82
|
+
grep: (p, sh) => descGrep(p, sh),
|
|
83
|
+
search_files: (p, sh) => descGrep(p, sh),
|
|
84
|
+
run_shell_command: (p) => descShell(p),
|
|
85
|
+
execute_command: (p) => descShell(p),
|
|
86
|
+
shell: (p) => descShell(p),
|
|
87
|
+
google_web_search: (p) => descSearch(p),
|
|
88
|
+
web_search: (p) => descSearch(p),
|
|
89
|
+
search: (p) => descSearch(p),
|
|
90
|
+
web_fetch: (p) => descFetch(p),
|
|
91
|
+
fetch_url: (p) => descFetch(p),
|
|
92
|
+
save_memory: (p) => descMemory(p),
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Gemini CLI 네이티브 스타일의 tool description 생성.
|
|
96
|
+
* 각 tool의 getDescription() 구현을 기반으로 한다.
|
|
97
|
+
*/
|
|
98
|
+
function toolDesc(name, params) {
|
|
99
|
+
// 경로를 마지막 2개 segment로 축약 (긴 절대경로 처리)
|
|
100
|
+
const shorten = (p) => {
|
|
101
|
+
if (!p)
|
|
102
|
+
return "";
|
|
103
|
+
const parts = p.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
104
|
+
if (parts.length <= 2)
|
|
105
|
+
return p;
|
|
106
|
+
return ".../" + parts.slice(-2).join("/");
|
|
107
|
+
};
|
|
108
|
+
const filePath = (params.file_path ?? params.path ?? params.absolute_path ??
|
|
109
|
+
params.filename ?? params.filepath ?? "");
|
|
110
|
+
const handler = TOOL_DESC_MAP[name];
|
|
111
|
+
if (handler)
|
|
112
|
+
return handler(params, shorten, filePath);
|
|
113
|
+
// MCP tool: "server__tool" -> "server: tool"
|
|
114
|
+
if (name.includes("__")) {
|
|
115
|
+
const [server, tool] = name.split("__", 2);
|
|
116
|
+
return `${server}: ${tool}`;
|
|
117
|
+
}
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
// --- ProgressTracker ---
|
|
121
|
+
class ProgressTracker {
|
|
122
|
+
static TOTAL = 100;
|
|
123
|
+
static TICK_INTERVAL = 300; // ms
|
|
124
|
+
static PRE_INIT_CAP = 9;
|
|
125
|
+
static RESPONSE_CAP = 90;
|
|
126
|
+
static SQRT_K = 15;
|
|
127
|
+
static KEEP_ALIVE_INTERVAL = 25_000; // 25초
|
|
128
|
+
static REPORT_CIRCUIT_BREAK_THRESHOLD = 3;
|
|
129
|
+
// notify() 내 progress increment 값
|
|
130
|
+
static INIT_PROGRESS = 10; // init 이벤트 최소 progress
|
|
131
|
+
static MSG_USER_PROGRESS = 15; // user message 최소 progress
|
|
132
|
+
static MSG_ASSISTANT_MIN_INC = 2; // assistant 메시지 최소 증분
|
|
133
|
+
static MSG_ASSISTANT_RATE = 0.08; // assistant 메시지 증분 비율
|
|
134
|
+
static TOOL_USE_INC = 3; // tool_use 증분
|
|
135
|
+
static TOOL_RESULT_INC = 2; // tool_result 증분
|
|
136
|
+
static FALLBACK_PROGRESS = 15; // fallback 최소 progress
|
|
137
|
+
progress = 0;
|
|
138
|
+
label = "Gemini 시작 중";
|
|
139
|
+
reportProgress = null;
|
|
140
|
+
tickTimer = null;
|
|
141
|
+
initTime = 0;
|
|
142
|
+
initReceived = false;
|
|
143
|
+
lastKeepAliveTime = 0;
|
|
144
|
+
dirty = false;
|
|
145
|
+
reporting = false;
|
|
146
|
+
reportFailCount = 0;
|
|
147
|
+
// 마지막 tool_use 정보: tool_result 시 ✓/✗ 표시에 재사용
|
|
148
|
+
lastToolName = "";
|
|
149
|
+
lastToolDesc = "";
|
|
150
|
+
async start(reportFn) {
|
|
151
|
+
this.reportProgress = reportFn;
|
|
152
|
+
this.progress = 0;
|
|
153
|
+
this.lastKeepAliveTime = Date.now();
|
|
154
|
+
await this.report(0, "Gemini 시작 중");
|
|
155
|
+
this.startTickLoop();
|
|
156
|
+
}
|
|
157
|
+
async stop() {
|
|
158
|
+
if (this.tickTimer !== null) {
|
|
159
|
+
clearInterval(this.tickTimer);
|
|
160
|
+
this.tickTimer = null;
|
|
161
|
+
}
|
|
162
|
+
// 미처리 dirty report flush: tick loop 종료 전 마지막 중간 상태 보장
|
|
163
|
+
if (this.dirty && !this.reporting) {
|
|
164
|
+
this.dirty = false;
|
|
165
|
+
await this.report(this.progress, this.label);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
timeTarget(elapsed) {
|
|
169
|
+
// target(t) = 15 + 75 * (1 - e^(-sqrt(t / K)))
|
|
170
|
+
return 15 + 75 * (1 - Math.exp(-Math.sqrt(elapsed / ProgressTracker.SQRT_K)));
|
|
171
|
+
}
|
|
172
|
+
startTickLoop() {
|
|
173
|
+
this.lastKeepAliveTime = Date.now();
|
|
174
|
+
this.tickTimer = setInterval(async () => {
|
|
175
|
+
if (this.reporting)
|
|
176
|
+
return; // 4-2: tick overlap 방지
|
|
177
|
+
const now = Date.now();
|
|
178
|
+
// 4-1: notify()가 갱신한 내용을 우선 report
|
|
179
|
+
if (this.dirty) {
|
|
180
|
+
this.dirty = false;
|
|
181
|
+
this.lastKeepAliveTime = now;
|
|
182
|
+
this.reporting = true;
|
|
183
|
+
try {
|
|
184
|
+
await this.report(this.progress, this.label);
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
this.reporting = false;
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (this.progress < ProgressTracker.RESPONSE_CAP) {
|
|
192
|
+
let target;
|
|
193
|
+
if (!this.initReceived) {
|
|
194
|
+
target = Math.min(this.progress + 1.0, ProgressTracker.PRE_INIT_CAP);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
const elapsed = (now - this.initTime) / 1000;
|
|
198
|
+
target = Math.min(this.timeTarget(elapsed), ProgressTracker.RESPONSE_CAP);
|
|
199
|
+
}
|
|
200
|
+
if (target > this.progress) {
|
|
201
|
+
this.progress = target;
|
|
202
|
+
this.lastKeepAliveTime = now;
|
|
203
|
+
this.reporting = true;
|
|
204
|
+
try {
|
|
205
|
+
await this.report(this.progress, this.label);
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
this.reporting = false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// RESPONSE_CAP 이상: 25초 간격 keep-alive
|
|
214
|
+
if (now - this.lastKeepAliveTime >= ProgressTracker.KEEP_ALIVE_INTERVAL) {
|
|
215
|
+
this.lastKeepAliveTime = now;
|
|
216
|
+
this.reporting = true;
|
|
217
|
+
try {
|
|
218
|
+
await this.report(this.progress, this.label);
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
this.reporting = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}, ProgressTracker.TICK_INTERVAL);
|
|
225
|
+
}
|
|
226
|
+
async report(progress, label) {
|
|
227
|
+
if (this.reportProgress && this.reportFailCount < ProgressTracker.REPORT_CIRCUIT_BREAK_THRESHOLD) {
|
|
228
|
+
const pct = Math.floor(progress);
|
|
229
|
+
try {
|
|
230
|
+
await this.reportProgress({ progress: pct, total: ProgressTracker.TOTAL, message: label });
|
|
231
|
+
this.reportFailCount = 0;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
this.reportFailCount++;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async finish() {
|
|
239
|
+
this.progress = Math.max(this.progress, 97);
|
|
240
|
+
await this.report(this.progress, "마무리 중");
|
|
241
|
+
this.progress = 100;
|
|
242
|
+
await this.report(this.progress, "완료");
|
|
243
|
+
}
|
|
244
|
+
async notify(event) {
|
|
245
|
+
switch (event.type) {
|
|
246
|
+
case "init":
|
|
247
|
+
// init도 즉시 report: 빠른 응답 시 tick 실행 전에 tool_use가 오면 "Gemini 연결됨"이 유실되기 때문
|
|
248
|
+
this.initReceived = true;
|
|
249
|
+
this.initTime = Date.now();
|
|
250
|
+
this.progress = Math.max(this.progress, ProgressTracker.INIT_PROGRESS);
|
|
251
|
+
this.label = "Gemini 연결됨";
|
|
252
|
+
this.dirty = false;
|
|
253
|
+
await this.report(this.progress, this.label);
|
|
254
|
+
break;
|
|
255
|
+
case "message":
|
|
256
|
+
if (event.role === "user") {
|
|
257
|
+
this.progress = Math.max(this.progress, ProgressTracker.MSG_USER_PROGRESS);
|
|
258
|
+
this.label = "요청 전송 완료";
|
|
259
|
+
this.dirty = true;
|
|
260
|
+
}
|
|
261
|
+
else if (event.role === "assistant") {
|
|
262
|
+
const increment = Math.max(ProgressTracker.MSG_ASSISTANT_MIN_INC, (ProgressTracker.RESPONSE_CAP - this.progress) * ProgressTracker.MSG_ASSISTANT_RATE);
|
|
263
|
+
this.progress = Math.min(this.progress + increment, ProgressTracker.RESPONSE_CAP);
|
|
264
|
+
this.label = "응답 생성 중";
|
|
265
|
+
this.dirty = true;
|
|
266
|
+
}
|
|
267
|
+
break;
|
|
268
|
+
case "tool_use": {
|
|
269
|
+
// tool_use는 즉시 report: tool_result가 300ms 이내에 오면 label이 덮여 유실되기 때문
|
|
270
|
+
this.progress = Math.min(this.progress + ProgressTracker.TOOL_USE_INC, ProgressTracker.RESPONSE_CAP);
|
|
271
|
+
const desc = toolDesc(event.tool_name, event.parameters);
|
|
272
|
+
this.lastToolName = event.tool_name;
|
|
273
|
+
this.lastToolDesc = desc;
|
|
274
|
+
this.label = desc ? `⊷ ${event.tool_name} ${desc}` : `⊷ ${event.tool_name}`;
|
|
275
|
+
this.dirty = false;
|
|
276
|
+
await this.report(this.progress, this.label);
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
case "tool_result": {
|
|
280
|
+
// tool_result도 즉시 report: 연속 tool_use가 300ms 이내에 오면 ✓ label이 유실되기 때문
|
|
281
|
+
this.progress = Math.min(this.progress + ProgressTracker.TOOL_RESULT_INC, ProgressTracker.RESPONSE_CAP);
|
|
282
|
+
const indicator = event.status === "ok" ? "✓" : "✗";
|
|
283
|
+
const toolInfo = this.lastToolDesc
|
|
284
|
+
? `${this.lastToolName} ${this.lastToolDesc}`
|
|
285
|
+
: this.lastToolName;
|
|
286
|
+
this.label = toolInfo ? `${indicator} ${toolInfo}` : `${indicator} Tool completed`;
|
|
287
|
+
this.dirty = false;
|
|
288
|
+
await this.report(this.progress, this.label);
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case "result":
|
|
292
|
+
await this.stop();
|
|
293
|
+
this.progress = Math.max(this.progress, 95);
|
|
294
|
+
await this.report(this.progress, "마무리 중");
|
|
295
|
+
break;
|
|
296
|
+
case "_fallback":
|
|
297
|
+
this.initReceived = false;
|
|
298
|
+
this.progress = Math.max(this.progress, ProgressTracker.FALLBACK_PROGRESS);
|
|
299
|
+
this.label = `Fallback: ${event.model}`;
|
|
300
|
+
this.dirty = true;
|
|
301
|
+
if (this.tickTimer === null) {
|
|
302
|
+
this.startTickLoop();
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
default:
|
|
306
|
+
if (this.progress > 0) {
|
|
307
|
+
this.dirty = true;
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.ProgressTracker = ProgressTracker;
|
|
314
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"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"}
|