@nerdvana/parism 0.1.5 → 0.2.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/README.en.md +46 -8
- package/README.md +70 -9
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +29 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/engine/guard.d.ts.map +1 -1
- package/dist/engine/guard.js +33 -9
- package/dist/engine/guard.js.map +1 -1
- package/dist/parsers/compact.d.ts +6 -0
- package/dist/parsers/compact.d.ts.map +1 -0
- package/dist/parsers/compact.js +31 -0
- package/dist/parsers/compact.js.map +1 -0
- package/dist/parsers/devops/docker.d.ts +28 -0
- package/dist/parsers/devops/docker.d.ts.map +1 -0
- package/dist/parsers/devops/docker.js +63 -0
- package/dist/parsers/devops/docker.js.map +1 -0
- package/dist/parsers/devops/gh.d.ts +18 -0
- package/dist/parsers/devops/gh.d.ts.map +1 -0
- package/dist/parsers/devops/gh.js +62 -0
- package/dist/parsers/devops/gh.js.map +1 -0
- package/dist/parsers/devops/index.d.ts +4 -0
- package/dist/parsers/devops/index.d.ts.map +1 -0
- package/dist/parsers/devops/index.js +4 -0
- package/dist/parsers/devops/index.js.map +1 -0
- package/dist/parsers/devops/kubectl.d.ts +27 -0
- package/dist/parsers/devops/kubectl.d.ts.map +1 -0
- package/dist/parsers/devops/kubectl.js +68 -0
- package/dist/parsers/devops/kubectl.js.map +1 -0
- package/dist/parsers/index.d.ts.map +1 -1
- package/dist/parsers/index.js +4 -0
- package/dist/parsers/index.js.map +1 -1
- package/dist/parsers/json-passthrough.d.ts +6 -0
- package/dist/parsers/json-passthrough.d.ts.map +1 -0
- package/dist/parsers/json-passthrough.js +19 -0
- package/dist/parsers/json-passthrough.js.map +1 -0
- package/dist/parsers/registry.d.ts +5 -0
- package/dist/parsers/registry.d.ts.map +1 -1
- package/dist/parsers/registry.js.map +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +37 -38
- package/dist/server.js.map +1 -1
- package/package.json +8 -2
- package/prism.config.json +2 -1
package/README.en.md
CHANGED
|
@@ -99,11 +99,11 @@ There are four layers of defense.
|
|
|
99
99
|
|
|
100
100
|
**Command Whitelist**: Commands not in `allowed_commands` are never executed. No process is created. Rejected silently.
|
|
101
101
|
|
|
102
|
-
**Path Restriction**: When `allowed_paths` is set,
|
|
102
|
+
**Path Restriction**: When `allowed_paths` is set, Guard validates both `cwd` and path-like args (starting with `/`, `./`, `../`). Anything outside allowed paths is blocked.
|
|
103
103
|
|
|
104
|
-
**Injection Pattern Blocking**: If `;`, `$(`, `` ` ``, `&&`, `||`, or
|
|
104
|
+
**Injection Pattern Blocking**: If `;`, `$(`, `` ` ``, `&&`, `||`, `|`, `>`, `>>`, or `<` appear in any argument, the command is not executed.
|
|
105
105
|
|
|
106
|
-
**Per-Command Argument Restrictions
|
|
106
|
+
**Per-Command Argument Restrictions**: Specific flags can be blocked per command. `node -e`, `node --eval`, and `node --input-type` are blocked by default. `npx --yes` is also blocked.
|
|
107
107
|
|
|
108
108
|
A blocked command returns this:
|
|
109
109
|
|
|
@@ -121,7 +121,7 @@ The agent receives the block reason in the same envelope structure as any other
|
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
|
124
|
-
## Supported Commands —
|
|
124
|
+
## Supported Commands — 34 Built-in Parsers
|
|
125
125
|
|
|
126
126
|
| Category | Command | Parsed Output |
|
|
127
127
|
|---|---|---|
|
|
@@ -146,6 +146,9 @@ The agent receives the block reason in the same envelope structure as any other
|
|
|
146
146
|
| Git | `git log --oneline` | `commits[]` — hash, message |
|
|
147
147
|
| Git | `git diff` | `files_changed[]` |
|
|
148
148
|
| Git | `git branch -vv` | `branches[]` — name, current, upstream, ahead/behind |
|
|
149
|
+
| DevOps | `kubectl get pods`, `kubectl get events` | `pods[]` / `events[]` — status, restarts, reasons, messages |
|
|
150
|
+
| DevOps | `docker ps`, `docker stats --no-stream` | `containers[]` / `stats[]` — image, status, CPU/MEM/IO |
|
|
151
|
+
| DevOps | `gh pr list` | `pull_requests[]` — number, title, state, author, labels |
|
|
149
152
|
| Env | `env` | `vars{}` — key-value map (secrets filtered) |
|
|
150
153
|
| Env | `pwd` | `path` |
|
|
151
154
|
| Env | `which` | `paths[]` |
|
|
@@ -210,7 +213,37 @@ Claude Code (Linux):
|
|
|
210
213
|
}
|
|
211
214
|
```
|
|
212
215
|
|
|
213
|
-
Once connected,
|
|
216
|
+
Once connected, two tools are exposed: `run` and `run_paged`.
|
|
217
|
+
|
|
218
|
+
`run` is the default command runner with structured parsing when available.
|
|
219
|
+
`run_paged` returns paginated stdout for large output and includes `page_info`.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Tools
|
|
224
|
+
|
|
225
|
+
### run
|
|
226
|
+
|
|
227
|
+
Default tool for most commands. Use when output is small or structured parsing is needed.
|
|
228
|
+
|
|
229
|
+
Parameters:
|
|
230
|
+
- `cmd` — command name (e.g. `ls`, `git`)
|
|
231
|
+
- `args` — argument array (default: `[]`)
|
|
232
|
+
- `cwd` — working directory (default: current directory)
|
|
233
|
+
|
|
234
|
+
### run_paged
|
|
235
|
+
|
|
236
|
+
Use for large stdout (`ps aux`, `find`, `grep -r`).
|
|
237
|
+
|
|
238
|
+
Parameters:
|
|
239
|
+
- `cmd`, `args`, `cwd` — same as `run`
|
|
240
|
+
- `page` — 0-indexed page number (default: `0`)
|
|
241
|
+
- `page_size` — lines per page (default: `default_page_size`, 100 by default)
|
|
242
|
+
|
|
243
|
+
Extra fields:
|
|
244
|
+
- `page_info.total_lines` — total line count
|
|
245
|
+
- `page_info.has_next` — whether next page exists
|
|
246
|
+
- `stdout.parsed` — always `null` (partial output cannot be safely parsed)
|
|
214
247
|
|
|
215
248
|
---
|
|
216
249
|
|
|
@@ -224,12 +257,15 @@ Place `prism.config.json` in the project root to control Guard behavior.
|
|
|
224
257
|
"allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
|
|
225
258
|
"allowed_paths": ["/home/user/projects"],
|
|
226
259
|
"timeout_ms": 10000,
|
|
227
|
-
"
|
|
260
|
+
"max_output_bytes": 102400,
|
|
261
|
+
"max_items": 500,
|
|
262
|
+
"default_page_size": 100,
|
|
263
|
+
"block_patterns": [";", "$(", "`", "&&", "||", ">", ">>", "<", "|"],
|
|
228
264
|
"command_arg_restrictions": {
|
|
229
|
-
"node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print"] },
|
|
265
|
+
"node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print", "--input-type"] },
|
|
230
266
|
"npx": { "blocked_flags": ["--yes", "-y"] }
|
|
231
267
|
},
|
|
232
|
-
"env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "CREDENTIAL"]
|
|
268
|
+
"env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "PASSWD", "CREDENTIAL"]
|
|
233
269
|
}
|
|
234
270
|
}
|
|
235
271
|
```
|
|
@@ -238,6 +274,8 @@ Place `prism.config.json` in the project root to control Guard behavior.
|
|
|
238
274
|
|
|
239
275
|
`env_secret_patterns` strips matching environment variables from child processes before execution. The `env` command will not expose them.
|
|
240
276
|
|
|
277
|
+
`command_arg_restrictions` is deep-merged with defaults. Overriding one command does not remove restrictions for others.
|
|
278
|
+
|
|
241
279
|
---
|
|
242
280
|
|
|
243
281
|
## What Parism Is Not
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Parism
|
|
2
2
|
|
|
3
3
|
> Refract the Shell. Every command, structured.
|
|
4
|
+
>
|
|
5
|
+
> AI 에이전트를 위한 안전하고 예측 가능한 OS 실행 게이트웨이.
|
|
4
6
|
|
|
5
7
|
<p align="right"><a href="README.md">한국어</a> | <a href="README.en.md">English</a></p>
|
|
6
8
|
|
|
@@ -34,6 +36,18 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
34
36
|
|
|
35
37
|
---
|
|
36
38
|
|
|
39
|
+
## 솔직한 이야기 — 토큰은 더 든다
|
|
40
|
+
|
|
41
|
+
Parism을 만들 때 기대한 것은 토큰 절약이었다. 구조화된 데이터가 raw 텍스트보다 효율적일 것이라고.
|
|
42
|
+
|
|
43
|
+
17개 시나리오를 벤치마크한 결과는 그 기대를 정면으로 배반했다. JSON 출력은 raw 텍스트보다 평균 205% 더 무겁다. `ls -la` 200개 파일 기준으로 raw 5,807 토큰, Parism 15,531 토큰. 거의 세 배다. 키 이름이 매 항목마다 반복되기 때문이다. 인간의 눈에 테이블 헤더 한 줄이면 되는 정보를 N번 써야 한다.
|
|
44
|
+
|
|
45
|
+
하지만 같은 벤치마크가 다른 사실 하나를 드러냈다. 에이전트가 raw 텍스트를 직접 파싱할 때 오독률이 평균 4.18%, 공백이 섞인 파일명에서는 28.6%에 달했다. 열 번 중 세 번은 틀린다. 틀린 결과로 에이전트가 다음 작업을 수행하고, 그 작업이 또 틀리고, 결국 사람이 개입해서 되돌린다. 재시도 토큰, 디버깅 시간, 롤백 비용. 보이지 않는 곳에서 비용이 불어난다.
|
|
46
|
+
|
|
47
|
+
Parism의 경제성은 토큰 청구서 위에 있지 않다. 실수와 재작업이 사라지는 자리에 있다. 한 번 더 읽는 비용보다, 한 번 잘못 읽어서 치르는 비용이 더 크다.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
37
51
|
## Parism이 하는 일
|
|
38
52
|
|
|
39
53
|
프리즘은 빛을 파괴하지 않는다. 분해할 뿐이다.
|
|
@@ -62,7 +76,11 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
62
76
|
|
|
63
77
|
### 파싱 오류가 없어진다
|
|
64
78
|
|
|
65
|
-
텍스트 파싱은 깨지기 쉽다. `ps aux`는 리눅스와 macOS에서 컬럼 순서가 다르다. `df -h`의 `1K-blocks` 헤더는 환경에 따라 다르게 나온다. 파일명에 공백이 있으면 `ls` 파싱은 거의 반드시 틀린다.
|
|
79
|
+
텍스트 파싱은 깨지기 쉽다. `ps aux`는 리눅스와 macOS에서 컬럼 순서가 다르다. `df -h`의 `1K-blocks` 헤더는 환경에 따라 다르게 나온다. 파일명에 공백이 있으면 `ls` 파싱은 거의 반드시 틀린다.
|
|
80
|
+
|
|
81
|
+
수치로 말하면: raw 텍스트를 에이전트가 직접 파싱할 때 평균 CFR(Critical Failure Rate)은 4.18%다. 공백이 포함된 파일명이 섞이면 28.6%까지 치솟는다. 1000회 호출 시 286회는 잘못된 파일 목록을 기반으로 에이전트가 다음 작업을 수행한다는 뜻이다. 잘못된 파일을 읽고, 존재하지 않는 경로에 쓰고, 엉뚱한 파일을 삭제한다.
|
|
82
|
+
|
|
83
|
+
Parism의 CFR은 0%다. 파서는 deterministic code이기 때문이다. 정규표현식 추론이 아니라 구조적 분해다. 에이전트는 구조화된 데이터만 받는다.
|
|
66
84
|
|
|
67
85
|
### 재시도가 줄어든다
|
|
68
86
|
|
|
@@ -99,11 +117,11 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
99
117
|
|
|
100
118
|
**화이트리스트**: `allowed_commands`에 없는 명령어는 실행되지 않는다. 프로세스를 만들지도 않는다. 설명 없이 거절한다.
|
|
101
119
|
|
|
102
|
-
**경로 제한**: `allowed_paths`를
|
|
120
|
+
**경로 제한**: `allowed_paths`를 설정하면 `cwd`뿐 아니라 경로형 인자(`/`, `./`, `../` 시작)도 검사한다. 허용 경로 밖을 참조하면 차단된다.
|
|
103
121
|
|
|
104
|
-
**인젝션 패턴 차단**: `;`, `$(`, `` ` ``, `&&`, `||`,
|
|
122
|
+
**인젝션 패턴 차단**: `;`, `$(`, `` ` ``, `&&`, `||`, `|`, `>`, `>>`, `<`가 인자에 포함되면 실행하지 않는다.
|
|
105
123
|
|
|
106
|
-
**명령별 인자
|
|
124
|
+
**명령별 인자 제한**: 명령마다 차단할 플래그를 지정할 수 있다. `node -e`, `node --eval`, `node --input-type`은 기본 차단된다. `npx --yes`도 기본 차단된다.
|
|
107
125
|
|
|
108
126
|
차단된 명령은 이런 응답을 반환한다.
|
|
109
127
|
|
|
@@ -121,7 +139,7 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
121
139
|
|
|
122
140
|
---
|
|
123
141
|
|
|
124
|
-
## 지원 명령어 —
|
|
142
|
+
## 지원 명령어 — 34종 내장 파서
|
|
125
143
|
|
|
126
144
|
| 카테고리 | 명령어 | 파싱 결과 |
|
|
127
145
|
|---|---|---|
|
|
@@ -146,6 +164,9 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
146
164
|
| Git | `git log --oneline` | `commits[]` — hash, message |
|
|
147
165
|
| Git | `git diff` | `files_changed[]` |
|
|
148
166
|
| Git | `git branch -vv` | `branches[]` — 이름, current, upstream, ahead/behind |
|
|
167
|
+
| DevOps | `kubectl get pods`, `kubectl get events` | `pods[]`/`events[]` — 상태, 재시도, 이벤트 사유/메시지 |
|
|
168
|
+
| DevOps | `docker ps`, `docker stats --no-stream` | `containers[]`/`stats[]` — 이미지, 상태, CPU/MEM/IO |
|
|
169
|
+
| DevOps | `gh pr list` | `pull_requests[]` — 번호, 제목, 상태, 작성자, 라벨 |
|
|
149
170
|
| 환경 | `env` | `vars{}` — 키-값 맵 |
|
|
150
171
|
| 환경 | `pwd` | `path` |
|
|
151
172
|
| 환경 | `which` | `paths[]` |
|
|
@@ -159,6 +180,10 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
|
|
|
159
180
|
|
|
160
181
|
파서가 없는 명령어는 `parsed: null`로 반환된다. `raw`는 그대로 있다.
|
|
161
182
|
|
|
183
|
+
### 네이티브 JSON 패스스루
|
|
184
|
+
|
|
185
|
+
파서가 없는 명령이라도 출력 자체가 JSON이면(예: `kubectl get pods -o json`, `docker inspect`) Parism이 이를 자동으로 감지하여 `parsed`에 넣는다. Guard 검사와 봉투 래핑은 동일하게 적용된다. 별도 설정은 필요 없다.
|
|
186
|
+
|
|
162
187
|
---
|
|
163
188
|
|
|
164
189
|
## 설치
|
|
@@ -214,6 +239,28 @@ Claude Code (Linux):
|
|
|
214
239
|
|
|
215
240
|
---
|
|
216
241
|
|
|
242
|
+
## Cursor 연동
|
|
243
|
+
|
|
244
|
+
전역 설정: `~/.cursor/mcp.json`
|
|
245
|
+
|
|
246
|
+
프로젝트별 설정: 프로젝트 루트 `.cursor/mcp.json` (이 프로젝트를 열었을 때만 parism 사용)
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"mcpServers": {
|
|
251
|
+
"parism": {
|
|
252
|
+
"command": "node",
|
|
253
|
+
"args": ["/home/nirna/job/nerdvana-prism/dist/index.js"],
|
|
254
|
+
"cwd": "/home/nirna/job/nerdvana-prism"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
빌드 후 위 설정을 `~/.cursor/mcp.json`의 `mcpServers`에 병합하거나, `.cursor/mcp.json`을 프로젝트 루트에 생성한다. Cursor 재시작 후 parism 도구가 사용 가능해진다.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
217
264
|
## Tools
|
|
218
265
|
|
|
219
266
|
### run
|
|
@@ -224,6 +271,16 @@ Claude Code (Linux):
|
|
|
224
271
|
- `cmd` — 명령어 이름 (예: `ls`, `git`)
|
|
225
272
|
- `args` — 인자 배열 (기본값: `[]`)
|
|
226
273
|
- `cwd` — 작업 디렉토리 (기본값: 현재 디렉토리)
|
|
274
|
+
- `format` — 출력 형식 (`"json"` 기본값, `"compact"` 가능). compact는 리스트형 출력을 schema+rows 컬럼 기반으로 압축하여 토큰 비용을 절감한다.
|
|
275
|
+
|
|
276
|
+
compact 예시:
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"schema": ["name", "type", "size_bytes"],
|
|
281
|
+
"rows": [["src", "directory", 4096], ["main.ts", "file", 1200]]
|
|
282
|
+
}
|
|
283
|
+
```
|
|
227
284
|
|
|
228
285
|
### run_paged
|
|
229
286
|
|
|
@@ -260,13 +317,15 @@ Claude Code (Linux):
|
|
|
260
317
|
"allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
|
|
261
318
|
"allowed_paths": ["/home/user/projects"],
|
|
262
319
|
"timeout_ms": 10000,
|
|
263
|
-
"
|
|
320
|
+
"max_output_bytes": 102400,
|
|
321
|
+
"max_items": 500,
|
|
322
|
+
"default_page_size": 100,
|
|
323
|
+
"block_patterns": [";", "$(", "`", "&&", "||", ">", ">>", "<", "|"],
|
|
264
324
|
"command_arg_restrictions": {
|
|
265
|
-
"node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print"] },
|
|
325
|
+
"node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print", "--input-type"] },
|
|
266
326
|
"npx": { "blocked_flags": ["--yes", "-y"] }
|
|
267
327
|
},
|
|
268
|
-
"env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "CREDENTIAL"]
|
|
269
|
-
"default_page_size": 100
|
|
328
|
+
"env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "PASSWD", "CREDENTIAL"]
|
|
270
329
|
}
|
|
271
330
|
}
|
|
272
331
|
```
|
|
@@ -275,6 +334,8 @@ Claude Code (Linux):
|
|
|
275
334
|
|
|
276
335
|
`env_secret_patterns`에 일치하는 환경 변수는 실행 전 자식 프로세스에서 제거된다. `env` 명령 실행 시 해당 변수가 노출되지 않는다.
|
|
277
336
|
|
|
337
|
+
`command_arg_restrictions`는 기본값과 병합된다. 일부 명령만 override해도 나머지 기본 제한은 유지된다.
|
|
338
|
+
|
|
278
339
|
---
|
|
279
340
|
|
|
280
341
|
## Parism이 아닌 것
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAU,MAAM,EAAE,CAAC;IACnC,aAAa,EAAa,MAAM,EAAE,CAAC;IACnC,UAAU,EAAgB,MAAM,CAAC;IACjC,gBAAgB,EAAU,MAAM,CAAC;IACjC,SAAS,EAAiB,MAAM,CAAC;IACjC,iBAAiB,EAAS,MAAM,CAAC;IACjC,cAAc,EAAY,MAAM,EAAE,CAAC;IACnC,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAChE,mBAAmB,EAAO,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,gBAAgB,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAU,MAAM,EAAE,CAAC;IACnC,aAAa,EAAa,MAAM,EAAE,CAAC;IACnC,UAAU,EAAgB,MAAM,CAAC;IACjC,gBAAgB,EAAU,MAAM,CAAC;IACjC,SAAS,EAAiB,MAAM,CAAC;IACjC,iBAAiB,EAAS,MAAM,CAAC;IACjC,cAAc,EAAY,MAAM,EAAE,CAAC;IACnC,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAChE,mBAAmB,EAAO,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAID,eAAO,MAAM,cAAc,EAAE,WA0B5B,CAAC;AAmBF;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA6BzE"}
|
package/dist/config/loader.js
CHANGED
|
@@ -9,6 +9,7 @@ export const DEFAULT_CONFIG = {
|
|
|
9
9
|
"git",
|
|
10
10
|
"env", "pwd", "which",
|
|
11
11
|
"echo", "date", "uname", "hostname",
|
|
12
|
+
"kubectl", "docker", "gh",
|
|
12
13
|
],
|
|
13
14
|
allowed_paths: [],
|
|
14
15
|
timeout_ms: 10000,
|
|
@@ -25,6 +26,21 @@ export const DEFAULT_CONFIG = {
|
|
|
25
26
|
],
|
|
26
27
|
},
|
|
27
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* guard 설정을 기본값과 병합한다.
|
|
31
|
+
* command_arg_restrictions는 하위 키 기준으로 깊은 병합하여 기본 보안 제한 유실을 방지한다.
|
|
32
|
+
*/
|
|
33
|
+
function mergeGuardConfig(userGuard) {
|
|
34
|
+
const mergedCommandArgRestrictions = {
|
|
35
|
+
...DEFAULT_CONFIG.guard.command_arg_restrictions,
|
|
36
|
+
...(userGuard.command_arg_restrictions ?? {}),
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
...DEFAULT_CONFIG.guard,
|
|
40
|
+
...userGuard,
|
|
41
|
+
command_arg_restrictions: mergedCommandArgRestrictions,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
28
44
|
/**
|
|
29
45
|
* 지정된 경로에서 prism.config.json을 로드한다.
|
|
30
46
|
* 파일이 없거나 파싱 실패 시 DEFAULT_CONFIG를 반환한다.
|
|
@@ -33,11 +49,22 @@ export async function loadConfig(configPath) {
|
|
|
33
49
|
try {
|
|
34
50
|
const raw = await readFile(configPath, "utf-8");
|
|
35
51
|
const json = JSON.parse(raw);
|
|
36
|
-
|
|
37
|
-
guard:
|
|
52
|
+
const config = {
|
|
53
|
+
guard: mergeGuardConfig(json.guard ?? {}),
|
|
38
54
|
};
|
|
55
|
+
if (config.guard.allowed_paths.length === 0) {
|
|
56
|
+
console.warn("[parism] WARNING: allowed_paths is empty. " +
|
|
57
|
+
"All filesystem paths are accessible. " +
|
|
58
|
+
"Set guard.allowed_paths in prism.config.json for production use.");
|
|
59
|
+
}
|
|
60
|
+
return config;
|
|
39
61
|
}
|
|
40
62
|
catch {
|
|
63
|
+
if (DEFAULT_CONFIG.guard.allowed_paths.length === 0) {
|
|
64
|
+
console.warn("[parism] WARNING: allowed_paths is empty. " +
|
|
65
|
+
"All filesystem paths are accessible. " +
|
|
66
|
+
"Set guard.allowed_paths in prism.config.json for production use.");
|
|
67
|
+
}
|
|
41
68
|
return DEFAULT_CONFIG;
|
|
42
69
|
}
|
|
43
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAwB5C,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,EAAE;QACL,gBAAgB,EAAE;YAChB,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM;YACxC,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,MAAM,EAAE,SAAS;YACzB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;YACnC,KAAK;YACL,KAAK,EAAE,KAAK,EAAE,OAAO;YACrB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;YACnC,SAAS,EAAE,QAAQ,EAAE,IAAI;SAC1B;QACD,aAAa,EAAK,EAAE;QACpB,UAAU,EAAQ,KAAK;QACvB,gBAAgB,EAAG,MAAM,EAAI,SAAS;QACtC,SAAS,EAAU,GAAG;QACtB,iBAAiB,EAAE,GAAG;QACtB,cAAc,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;QACjE,wBAAwB,EAAE;YACxB,IAAI,EAAE,EAAE,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE;YAC7F,GAAG,EAAG,EAAE,aAAa,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;SACzC;QACD,mBAAmB,EAAE;YACnB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY;SAC/D;KACF;CACF,CAAC;AAEF;;;GAGG;AACH,SAAS,gBAAgB,CAAC,SAAkC;IAC1D,MAAM,4BAA4B,GAAG;QACnC,GAAG,cAAc,CAAC,KAAK,CAAC,wBAAwB;QAChD,GAAG,CAAC,SAAS,CAAC,wBAAwB,IAAI,EAAE,CAAC;KAC9C,CAAC;IAEF,OAAO;QACL,GAAG,cAAc,CAAC,KAAK;QACvB,GAAG,SAAS;QACZ,wBAAwB,EAAE,4BAA4B;KACvD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAI,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QAErD,MAAM,MAAM,GAAgB;YAC1B,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;SAC1C,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,IAAI,CACV,4CAA4C;gBAC5C,uCAAuC;gBACvC,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO,CAAC,IAAI,CACV,4CAA4C;gBAC5C,uCAAuC;gBACvC,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,MAAM,EAClB,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB;gBALrB,OAAO,EAAE,MAAM,EACC,MAAM,EAClB,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB;CAKxB;
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,MAAM,EAClB,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB;gBALrB,OAAO,EAAE,MAAM,EACC,MAAM,EAClB,qBAAqB,GACrB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB;CAKxB;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAK,MAAM,EACd,IAAI,EAAI,MAAM,EAAE,EAChB,GAAG,EAAK,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAuDN"}
|
package/dist/engine/guard.js
CHANGED
|
@@ -10,6 +10,31 @@ export class GuardError extends Error {
|
|
|
10
10
|
this.name = "GuardError";
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* 경로 비교 시 접미 슬래시를 강제해 `/home/user` vs `/home/user2` 오탐을 방지한다.
|
|
15
|
+
*/
|
|
16
|
+
function normalizePathForPrefix(inputPath) {
|
|
17
|
+
const resolved = path.resolve(inputPath);
|
|
18
|
+
return resolved.endsWith("/") ? resolved : resolved + "/";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 대상 경로가 허용 경로 집합 중 하나의 하위 경로인지 검사한다.
|
|
22
|
+
*/
|
|
23
|
+
function isAllowedPath(targetPath, allowedPaths) {
|
|
24
|
+
const normalizedTarget = normalizePathForPrefix(targetPath);
|
|
25
|
+
return allowedPaths.some((allowedPath) => {
|
|
26
|
+
const normalizedAllowed = normalizePathForPrefix(allowedPath);
|
|
27
|
+
return normalizedTarget.startsWith(normalizedAllowed);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 명령 인자 중 실제 파일시스템 경로로 해석 가능한 값만 추출한다.
|
|
32
|
+
*/
|
|
33
|
+
function getPathLikeArgs(args) {
|
|
34
|
+
return args.filter((arg) => arg.startsWith("/") ||
|
|
35
|
+
arg.startsWith("./") ||
|
|
36
|
+
arg.startsWith("../"));
|
|
37
|
+
}
|
|
13
38
|
/**
|
|
14
39
|
* 명령 실행 허용 여부를 검사한다. 차단 조건 충족 시 GuardError를 던진다.
|
|
15
40
|
*
|
|
@@ -41,18 +66,17 @@ export function checkGuard(cmd, args, cwd, config) {
|
|
|
41
66
|
}
|
|
42
67
|
}
|
|
43
68
|
if (guard.allowed_paths.length > 0) {
|
|
44
|
-
// path.resolve()로 ../를 포함한 모든 경로 순회 패턴을 정규화한 뒤 비교.
|
|
45
|
-
// 단순 문자열 startsWith()는 /home/user/../../etc 형태로 우회 가능.
|
|
46
69
|
const resolvedCwd = path.resolve(cwd);
|
|
47
|
-
|
|
48
|
-
const allowed = guard.allowed_paths.some((p) => {
|
|
49
|
-
const resolvedP = path.resolve(p);
|
|
50
|
-
const normalizedP = resolvedP.endsWith("/") ? resolvedP : resolvedP + "/";
|
|
51
|
-
return normalizedCwd.startsWith(normalizedP);
|
|
52
|
-
});
|
|
53
|
-
if (!allowed) {
|
|
70
|
+
if (!isAllowedPath(resolvedCwd, guard.allowed_paths)) {
|
|
54
71
|
throw new GuardError(`Working directory '${cwd}' is outside allowed paths`, "path_not_allowed");
|
|
55
72
|
}
|
|
73
|
+
const pathLikeArgs = getPathLikeArgs(args);
|
|
74
|
+
for (const arg of pathLikeArgs) {
|
|
75
|
+
const resolvedArgPath = path.resolve(cwd, arg);
|
|
76
|
+
if (!isAllowedPath(resolvedArgPath, guard.allowed_paths)) {
|
|
77
|
+
throw new GuardError(`Path argument '${arg}' resolves outside allowed paths`, "path_not_allowed");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
56
80
|
}
|
|
57
81
|
}
|
|
58
82
|
//# sourceMappingURL=guard.js.map
|
package/dist/engine/guard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IAFlB,YACE,OAAe,EACC,MAIK;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QANC,WAAM,GAAN,MAAM,CAID;QAGrB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,GAAc,EACd,IAAgB,EAChB,GAAc,EACd,MAAmB;IAEnB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAClB,YAAY,GAAG,8BAA8B,EAC7C,qBAAqB,CACtB,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,UAAU,CAClB,oBAAoB,OAAO,yBAAyB,EACpD,mBAAmB,CACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,wBAAwB,EAAE,CAAC,GAAG,CAAC,CAAC;IAC1D,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,+BAA+B;YAC/B,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACnE,IAAI,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,UAAU,CAClB,aAAa,GAAG,iCAAiC,GAAG,GAAG,EACvD,iBAAiB,CAClB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/engine/guard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAGjB;IAFlB,YACE,OAAe,EACC,MAIK;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QANC,WAAM,GAAN,MAAM,CAID;QAGrB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,SAAiB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,UAAkB,EAAE,YAAsB;IAC/D,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC5D,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;QACvC,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC9D,OAAO,gBAAgB,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAc;IACrC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACzB,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QACnB,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QACpB,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CACtB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,GAAc,EACd,IAAgB,EAChB,GAAc,EACd,MAAmB;IAEnB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAClB,YAAY,GAAG,8BAA8B,EAC7C,qBAAqB,CACtB,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,UAAU,CAClB,oBAAoB,OAAO,yBAAyB,EACpD,mBAAmB,CACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,wBAAwB,EAAE,CAAC,GAAG,CAAC,CAAC;IAC1D,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,+BAA+B;YAC/B,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACnE,IAAI,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,UAAU,CAClB,aAAa,GAAG,iCAAiC,GAAG,GAAG,EACvD,iBAAiB,CAClB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,UAAU,CAClB,sBAAsB,GAAG,4BAA4B,EACrD,kBAAkB,CACnB,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,UAAU,CAClB,kBAAkB,GAAG,kCAAkC,EACvD,kBAAkB,CACnB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../src/parsers/compact.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAI,OAAO,EAAE,EAAE,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CA+BlD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function toCompact(parsed) {
|
|
2
|
+
if (parsed == null)
|
|
3
|
+
return null;
|
|
4
|
+
if (typeof parsed !== "object" || Array.isArray(parsed))
|
|
5
|
+
return parsed;
|
|
6
|
+
const obj = parsed;
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
9
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
10
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
11
|
+
result[key] = { schema: [], rows: [] };
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
result[key] = value;
|
|
15
|
+
}
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value[0] !== "object" || value[0] === null) {
|
|
19
|
+
result[key] = value;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const schema = Object.keys(value[0]);
|
|
23
|
+
const rows = value.map((item) => {
|
|
24
|
+
const rec = item;
|
|
25
|
+
return schema.map((k) => rec[k]);
|
|
26
|
+
});
|
|
27
|
+
result[key] = { schema, rows };
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/parsers/compact.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS,CAAC,MAAe;IACvC,IAAI,MAAM,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAEvE,MAAM,GAAG,GAAM,MAAiC,CAAC;IACjD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACtB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACpB,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA4B,CAAC,CAAC;QAChE,MAAM,IAAI,GAAK,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,GAAG,GAAG,IAA+B,CAAC;YAC5C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface DockerPsEntry {
|
|
2
|
+
container_id: string;
|
|
3
|
+
image: string;
|
|
4
|
+
command: string;
|
|
5
|
+
created: string;
|
|
6
|
+
status: string;
|
|
7
|
+
ports: string;
|
|
8
|
+
names: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DockerStatsEntry {
|
|
11
|
+
container_id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
cpu_perc: string;
|
|
14
|
+
mem_usage: string;
|
|
15
|
+
mem_limit: string;
|
|
16
|
+
mem_perc: string;
|
|
17
|
+
net_io: string;
|
|
18
|
+
block_io: string;
|
|
19
|
+
pids: number | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* docker 서브커맨드별 출력 파싱.
|
|
23
|
+
* 현재 지원:
|
|
24
|
+
* - docker ps
|
|
25
|
+
* - docker stats --no-stream
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseDocker(_cmd: string, args: string[], raw: string): unknown | null;
|
|
28
|
+
//# sourceMappingURL=docker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/parsers/devops/docker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;IACrB,OAAO,EAAO,MAAM,CAAC;IACrB,OAAO,EAAO,MAAM,CAAC;IACrB,MAAM,EAAQ,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAU,MAAM,CAAC;IACrB,QAAQ,EAAM,MAAM,CAAC;IACrB,SAAS,EAAK,MAAM,CAAC;IACrB,SAAS,EAAK,MAAM,CAAC;IACrB,QAAQ,EAAM,MAAM,CAAC;IACrB,MAAM,EAAQ,MAAM,CAAC;IACrB,QAAQ,EAAM,MAAM,CAAC;IACrB,IAAI,EAAU,MAAM,GAAG,IAAI,CAAC;CAC7B;AA0DD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAOrF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function splitColumns(line) {
|
|
2
|
+
return line.trim().split(/\s{2,}/).map((v) => v.trim());
|
|
3
|
+
}
|
|
4
|
+
function parseDockerPs(raw) {
|
|
5
|
+
const lines = raw.split("\n").filter(Boolean);
|
|
6
|
+
if (lines.length <= 1)
|
|
7
|
+
return { resource: "ps", containers: [] };
|
|
8
|
+
const containers = [];
|
|
9
|
+
for (const line of lines.slice(1)) {
|
|
10
|
+
const cols = splitColumns(line);
|
|
11
|
+
if (cols.length < 6)
|
|
12
|
+
continue;
|
|
13
|
+
containers.push({
|
|
14
|
+
container_id: cols[0] ?? "",
|
|
15
|
+
image: cols[1] ?? "",
|
|
16
|
+
command: cols[2] ?? "",
|
|
17
|
+
created: cols[3] ?? "",
|
|
18
|
+
status: cols[4] ?? "",
|
|
19
|
+
ports: cols.length === 6 ? "" : (cols[5] ?? ""),
|
|
20
|
+
names: cols.length === 6 ? (cols[5] ?? "") : (cols[6] ?? ""),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return { resource: "ps", containers };
|
|
24
|
+
}
|
|
25
|
+
function parseDockerStats(raw) {
|
|
26
|
+
const lines = raw.split("\n").filter(Boolean);
|
|
27
|
+
if (lines.length <= 1)
|
|
28
|
+
return { resource: "stats", stats: [] };
|
|
29
|
+
const stats = [];
|
|
30
|
+
for (const line of lines.slice(1)) {
|
|
31
|
+
const cols = splitColumns(line);
|
|
32
|
+
if (cols.length < 7)
|
|
33
|
+
continue;
|
|
34
|
+
const memUsageParts = (cols[3] ?? "").split("/").map((v) => v.trim());
|
|
35
|
+
stats.push({
|
|
36
|
+
container_id: cols[0] ?? "",
|
|
37
|
+
name: cols[1] ?? "",
|
|
38
|
+
cpu_perc: cols[2] ?? "",
|
|
39
|
+
mem_usage: memUsageParts[0] ?? "",
|
|
40
|
+
mem_limit: memUsageParts[1] ?? "",
|
|
41
|
+
mem_perc: cols[4] ?? "",
|
|
42
|
+
net_io: cols[5] ?? "",
|
|
43
|
+
block_io: cols[6] ?? "",
|
|
44
|
+
pids: cols[7] ? (parseInt(cols[7], 10) || null) : null,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return { resource: "stats", stats };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* docker 서브커맨드별 출력 파싱.
|
|
51
|
+
* 현재 지원:
|
|
52
|
+
* - docker ps
|
|
53
|
+
* - docker stats --no-stream
|
|
54
|
+
*/
|
|
55
|
+
export function parseDocker(_cmd, args, raw) {
|
|
56
|
+
const sub = args[0];
|
|
57
|
+
if (sub === "ps")
|
|
58
|
+
return parseDockerPs(raw);
|
|
59
|
+
if (sub === "stats")
|
|
60
|
+
return parseDockerStats(raw);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../src/parsers/devops/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface GhPullRequest {
|
|
2
|
+
number: number | null;
|
|
3
|
+
title: string;
|
|
4
|
+
branch: string | null;
|
|
5
|
+
state: string | null;
|
|
6
|
+
age: string | null;
|
|
7
|
+
author: string | null;
|
|
8
|
+
labels: string[];
|
|
9
|
+
updated_at: string | null;
|
|
10
|
+
draft: boolean | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* gh 서브커맨드별 출력 파싱.
|
|
14
|
+
* 현재 지원:
|
|
15
|
+
* - gh pr list (table/json)
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseGh(_cmd: string, args: string[], raw: string): unknown | null;
|
|
18
|
+
//# sourceMappingURL=gh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gh.d.ts","sourceRoot":"","sources":["../../../src/parsers/devops/gh.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAM,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAO,MAAM,CAAC;IACnB,MAAM,EAAM,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAO,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAS,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAM,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAM,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAO,OAAO,GAAG,IAAI,CAAC;CAC5B;AAyDD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAOjF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
function parseGhPrListFromJson(raw) {
|
|
2
|
+
try {
|
|
3
|
+
const parsed = JSON.parse(raw);
|
|
4
|
+
if (!Array.isArray(parsed))
|
|
5
|
+
return null;
|
|
6
|
+
const pullRequests = parsed.map((pr) => {
|
|
7
|
+
const author = pr.author;
|
|
8
|
+
const labels = Array.isArray(pr.labels) ? pr.labels : [];
|
|
9
|
+
return {
|
|
10
|
+
number: typeof pr.number === "number" ? pr.number : null,
|
|
11
|
+
title: typeof pr.title === "string" ? pr.title : "",
|
|
12
|
+
branch: typeof pr.headRefName === "string" ? pr.headRefName : null,
|
|
13
|
+
state: typeof pr.state === "string" ? pr.state : null,
|
|
14
|
+
age: null,
|
|
15
|
+
author: typeof author?.login === "string" ? author.login : null,
|
|
16
|
+
labels: labels.map((label) => String(label.name ?? "")).filter(Boolean),
|
|
17
|
+
updated_at: typeof pr.updatedAt === "string" ? pr.updatedAt : null,
|
|
18
|
+
draft: typeof pr.isDraft === "boolean" ? pr.isDraft : null,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
return { resource: "pr_list", pull_requests: pullRequests };
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function parseGhPrListFromTable(raw) {
|
|
28
|
+
const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
29
|
+
const pullRequests = [];
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
const cols = line.includes("\t")
|
|
32
|
+
? line.split(/\t+/).map((v) => v.trim())
|
|
33
|
+
: line.split(/\s{2,}/).map((v) => v.trim());
|
|
34
|
+
if (cols.length < 2)
|
|
35
|
+
continue;
|
|
36
|
+
pullRequests.push({
|
|
37
|
+
number: parseInt(cols[0] ?? "", 10) || null,
|
|
38
|
+
title: cols[1] ?? "",
|
|
39
|
+
branch: cols[2] ?? null,
|
|
40
|
+
state: cols[3] ?? null,
|
|
41
|
+
age: cols[4] ?? null,
|
|
42
|
+
author: null,
|
|
43
|
+
labels: [],
|
|
44
|
+
updated_at: null,
|
|
45
|
+
draft: null,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return { resource: "pr_list", pull_requests: pullRequests };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* gh 서브커맨드별 출력 파싱.
|
|
52
|
+
* 현재 지원:
|
|
53
|
+
* - gh pr list (table/json)
|
|
54
|
+
*/
|
|
55
|
+
export function parseGh(_cmd, args, raw) {
|
|
56
|
+
const sub1 = args[0];
|
|
57
|
+
const sub2 = args[1];
|
|
58
|
+
if (!(sub1 === "pr" && sub2 === "list"))
|
|
59
|
+
return null;
|
|
60
|
+
return parseGhPrListFromJson(raw) ?? parseGhPrListFromTable(raw);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=gh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gh.js","sourceRoot":"","sources":["../../../src/parsers/devops/gh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/parsers/devops/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAO,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAW,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/parsers/devops/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAO,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAW,SAAS,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface KubectlPodEntry {
|
|
2
|
+
name: string;
|
|
3
|
+
ready: {
|
|
4
|
+
current: number;
|
|
5
|
+
total: number;
|
|
6
|
+
} | null;
|
|
7
|
+
status: string;
|
|
8
|
+
restarts: number;
|
|
9
|
+
age: string;
|
|
10
|
+
ip: string | null;
|
|
11
|
+
node: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface KubectlEventEntry {
|
|
14
|
+
last_seen: string;
|
|
15
|
+
type: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
object: string;
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* kubectl 서브커맨드별 출력 파싱.
|
|
22
|
+
* 현재 지원:
|
|
23
|
+
* - kubectl get pods
|
|
24
|
+
* - kubectl get events
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseKubectl(_cmd: string, args: string[], raw: string): unknown | null;
|
|
27
|
+
//# sourceMappingURL=kubectl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubectl.d.ts","sourceRoot":"","sources":["../../../src/parsers/devops/kubectl.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAO,MAAM,CAAC;IAClB,KAAK,EAAM;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrD,MAAM,EAAK,MAAM,CAAC;IAClB,QAAQ,EAAG,MAAM,CAAC;IAClB,GAAG,EAAQ,MAAM,CAAC;IAClB,EAAE,EAAS,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAO,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAO,MAAM,CAAC;IAClB,MAAM,EAAK,MAAM,CAAC;IAClB,MAAM,EAAK,MAAM,CAAC;IAClB,OAAO,EAAI,MAAM,CAAC;CACnB;AA2DD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAStF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function parseReady(value) {
|
|
2
|
+
const match = value.match(/^(\d+)\/(\d+)$/);
|
|
3
|
+
if (!match)
|
|
4
|
+
return null;
|
|
5
|
+
return {
|
|
6
|
+
current: parseInt(match[1], 10),
|
|
7
|
+
total: parseInt(match[2], 10),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function parseKubectlPods(raw) {
|
|
11
|
+
const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
12
|
+
if (lines.length <= 1)
|
|
13
|
+
return { resource: "pods", pods: [] };
|
|
14
|
+
const pods = [];
|
|
15
|
+
for (const line of lines.slice(1)) {
|
|
16
|
+
const cols = line.split(/\s+/);
|
|
17
|
+
if (cols.length < 5)
|
|
18
|
+
continue;
|
|
19
|
+
pods.push({
|
|
20
|
+
name: cols[0] ?? "",
|
|
21
|
+
ready: parseReady(cols[1] ?? ""),
|
|
22
|
+
status: cols[2] ?? "",
|
|
23
|
+
restarts: parseInt((cols[3] ?? "0").replace(/[^0-9]/g, ""), 10) || 0,
|
|
24
|
+
age: cols[4] ?? "",
|
|
25
|
+
ip: cols[5] ?? null,
|
|
26
|
+
node: cols[6] ?? null,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return { resource: "pods", pods };
|
|
30
|
+
}
|
|
31
|
+
function parseKubectlEvents(raw) {
|
|
32
|
+
const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
33
|
+
if (lines.length <= 1)
|
|
34
|
+
return { resource: "events", events: [] };
|
|
35
|
+
const events = [];
|
|
36
|
+
for (const line of lines.slice(1)) {
|
|
37
|
+
const cols = line.split(/\s+/);
|
|
38
|
+
if (cols.length < 5)
|
|
39
|
+
continue;
|
|
40
|
+
const [lastSeen, type, reason, object, ...messageParts] = cols;
|
|
41
|
+
events.push({
|
|
42
|
+
last_seen: lastSeen ?? "",
|
|
43
|
+
type: type ?? "",
|
|
44
|
+
reason: reason ?? "",
|
|
45
|
+
object: object ?? "",
|
|
46
|
+
message: messageParts.join(" "),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return { resource: "events", events };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* kubectl 서브커맨드별 출력 파싱.
|
|
53
|
+
* 현재 지원:
|
|
54
|
+
* - kubectl get pods
|
|
55
|
+
* - kubectl get events
|
|
56
|
+
*/
|
|
57
|
+
export function parseKubectl(_cmd, args, raw) {
|
|
58
|
+
const sub = args[0];
|
|
59
|
+
const resource = args[1];
|
|
60
|
+
if (sub !== "get")
|
|
61
|
+
return null;
|
|
62
|
+
if (resource === "pods")
|
|
63
|
+
return parseKubectlPods(raw);
|
|
64
|
+
if (resource === "events")
|
|
65
|
+
return parseKubectlEvents(raw);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=kubectl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubectl.js","sourceRoot":"","sources":["../../../src/parsers/devops/kubectl.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAmD,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAmD,eAAe,CAAC;AAY5F;;GAEG;AACH,eAAO,MAAM,eAAe,gBAAuB,CAAC"}
|
package/dist/parsers/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { parseGitStatus, parseGitLog, parseGitDiff, parseGitBranch } from "./git
|
|
|
7
7
|
import { parseEnv, parsePwd, parseWhich } from "./env/index.js";
|
|
8
8
|
import { parseFree, parseUname, parseId } from "./system/index.js";
|
|
9
9
|
import { parseDir, parseTasklist, parseIpconfig, parseSysteminfo } from "./windows/index.js";
|
|
10
|
+
import { parseKubectl, parseDocker, parseGh } from "./devops/index.js";
|
|
10
11
|
/**
|
|
11
12
|
* 전역 싱글턴 Parser Registry. 서버 시작 시 한 번 초기화된다.
|
|
12
13
|
*/
|
|
@@ -40,6 +41,9 @@ defaultRegistry.register("dir", parseDir);
|
|
|
40
41
|
defaultRegistry.register("tasklist", parseTasklist);
|
|
41
42
|
defaultRegistry.register("ipconfig", parseIpconfig);
|
|
42
43
|
defaultRegistry.register("systeminfo", parseSysteminfo);
|
|
44
|
+
defaultRegistry.register("kubectl", parseKubectl);
|
|
45
|
+
defaultRegistry.register("docker", parseDocker);
|
|
46
|
+
defaultRegistry.register("gh", parseGh);
|
|
43
47
|
// git은 서브커맨드 기반 — args[0]으로 파서를 선택
|
|
44
48
|
defaultRegistry.register("git", (cmd, args, raw) => {
|
|
45
49
|
const sub = args[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAmD,eAAe,CAAC;AAC5F,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAA+C,oBAAoB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EACtD,QAAQ,EAAE,MAAyD,oBAAoB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAc,iBAAiB,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAO,gBAAgB,CAAC;AAC5F,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAkC,gBAAgB,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAkC,mBAAmB,CAAC;AAC/F,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAS,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-passthrough.d.ts","sourceRoot":"","sources":["../../src/parsers/json-passthrough.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAY9D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdout이 네이티브 JSON 출력인지 감지하고, 맞으면 파싱 결과를 반환한다.
|
|
3
|
+
* 감지 조건: trim 후 { 또는 [ 로 시작하고 전체가 유효한 JSON일 것.
|
|
4
|
+
*/
|
|
5
|
+
export function tryParseNativeJson(raw) {
|
|
6
|
+
const trimmed = raw.trim();
|
|
7
|
+
if (!trimmed)
|
|
8
|
+
return null;
|
|
9
|
+
const first = trimmed[0];
|
|
10
|
+
if (first !== "{" && first !== "[")
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(trimmed);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=json-passthrough.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-passthrough.js","sourceRoot":"","sources":["../../src/parsers/json-passthrough.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAEhD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 출력 형식. json=기존 객체 배열, compact=schema+rows 컬럼 기반.
|
|
3
|
+
*/
|
|
4
|
+
export type OutputFormat = "json" | "compact";
|
|
1
5
|
/**
|
|
2
6
|
* 파서가 항목 수를 제한할 때 사용하는 컨텍스트.
|
|
3
7
|
* maxItems=0 이면 무제한.
|
|
4
8
|
*/
|
|
5
9
|
export interface ParseContext {
|
|
6
10
|
maxItems: number;
|
|
11
|
+
format: OutputFormat;
|
|
7
12
|
}
|
|
8
13
|
/**
|
|
9
14
|
* 파서 함수 시그니처.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAI,YAAY,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC;AAEjG;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IAEvD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI;IAIzC;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI;CAUpF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAEvD,QAAQ,CAAC,GAAW,EAAE,EAAY;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAW,EAAE,IAAc,EAAE,GAAW,EAAE,GAAkB;QAChE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAErB,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { PrismConfig } from "./config/loader.js";
|
|
3
|
+
import type { OutputFormat } from "./parsers/registry.js";
|
|
4
|
+
export declare const PACKAGE_VERSION = "0.2.0";
|
|
3
5
|
/**
|
|
4
6
|
* Guard 검사 → 실행 → JSON 직렬화까지의 파이프라인.
|
|
5
7
|
* MCP 서버와 테스트 코드가 공통으로 사용한다.
|
|
6
8
|
*/
|
|
7
|
-
export declare function buildRunResult(cmd: string, args: string[], cwd: string, config: PrismConfig): Promise<string>;
|
|
9
|
+
export declare function buildRunResult(cmd: string, args: string[], cwd: string, config: PrismConfig, format?: OutputFormat): Promise<string>;
|
|
8
10
|
/**
|
|
9
11
|
* Guard 검사 → 실행 → 페이지 분할 → JSON 직렬화.
|
|
10
12
|
* parsed는 항상 null (부분 출력은 구조화 파싱 불가).
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAmB,yCAAyC,CAAC;AAOjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAY,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAmB,yCAAyC,CAAC;AAOjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAY,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAW,uBAAuB,CAAC;AAI/D,eAAO,MAAM,eAAe,UAAU,CAAC;AAsBvC;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAK,MAAM,EACd,IAAI,EAAI,MAAM,EAAE,EAChB,GAAG,EAAK,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,MAAM,GAAE,YAAqB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAO,MAAM,EAChB,IAAI,EAAM,MAAM,EAAE,EAClB,GAAG,EAAO,MAAM,EAChB,IAAI,EAAM,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAI,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CA8C3D"}
|
package/dist/server.js
CHANGED
|
@@ -4,36 +4,45 @@ import { execute } from "./engine/executor.js";
|
|
|
4
4
|
import { checkGuard, GuardError } from "./engine/guard.js";
|
|
5
5
|
import { defaultRegistry } from "./parsers/index.js";
|
|
6
6
|
import { paginateLines } from "./engine/paginator.js";
|
|
7
|
-
|
|
7
|
+
import { toCompact } from "./parsers/compact.js";
|
|
8
|
+
import { tryParseNativeJson } from "./parsers/json-passthrough.js";
|
|
9
|
+
export const PACKAGE_VERSION = "0.2.0";
|
|
10
|
+
/**
|
|
11
|
+
* Guard 차단 시 반환하는 에러 봉투를 생성한다.
|
|
12
|
+
*/
|
|
13
|
+
function buildGuardErrorEnvelope(cmd, args, cwd, err) {
|
|
14
|
+
return JSON.stringify({
|
|
15
|
+
ok: false,
|
|
16
|
+
exitCode: -1,
|
|
17
|
+
cmd,
|
|
18
|
+
args,
|
|
19
|
+
cwd,
|
|
20
|
+
duration_ms: 0,
|
|
21
|
+
stdout: { raw: "", parsed: null },
|
|
22
|
+
stderr: { raw: err.message, parsed: null },
|
|
23
|
+
diff: null,
|
|
24
|
+
guard_error: { reason: err.reason, message: err.message },
|
|
25
|
+
}, null, 2);
|
|
26
|
+
}
|
|
8
27
|
/**
|
|
9
28
|
* Guard 검사 → 실행 → JSON 직렬화까지의 파이프라인.
|
|
10
29
|
* MCP 서버와 테스트 코드가 공통으로 사용한다.
|
|
11
30
|
*/
|
|
12
|
-
export async function buildRunResult(cmd, args, cwd, config) {
|
|
31
|
+
export async function buildRunResult(cmd, args, cwd, config, format = "json") {
|
|
13
32
|
try {
|
|
14
33
|
checkGuard(cmd, args, cwd, config);
|
|
15
34
|
}
|
|
16
35
|
catch (err) {
|
|
17
|
-
if (err instanceof GuardError)
|
|
18
|
-
|
|
19
|
-
ok: false,
|
|
20
|
-
exitCode: -1,
|
|
21
|
-
cmd,
|
|
22
|
-
args,
|
|
23
|
-
cwd,
|
|
24
|
-
duration_ms: 0,
|
|
25
|
-
stdout: { raw: "", parsed: null },
|
|
26
|
-
stderr: { raw: err.message, parsed: null },
|
|
27
|
-
diff: null,
|
|
28
|
-
guard_error: { reason: err.reason, message: err.message },
|
|
29
|
-
};
|
|
30
|
-
return JSON.stringify(envelope, null, 2);
|
|
31
|
-
}
|
|
36
|
+
if (err instanceof GuardError)
|
|
37
|
+
return buildGuardErrorEnvelope(cmd, args, cwd, err);
|
|
32
38
|
throw err;
|
|
33
39
|
}
|
|
34
40
|
const envelope = await execute(cmd, args, cwd, config.guard.env_secret_patterns, config.guard.timeout_ms, config.guard.max_output_bytes);
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
let parsed = defaultRegistry.parse(cmd, args, envelope.stdout.raw, { maxItems: config.guard.max_items, format });
|
|
42
|
+
if (parsed == null)
|
|
43
|
+
parsed = tryParseNativeJson(envelope.stdout.raw);
|
|
44
|
+
const final = format === "compact" ? toCompact(parsed) : parsed;
|
|
45
|
+
const enriched = { ...envelope, stdout: { ...envelope.stdout, parsed: final } };
|
|
37
46
|
return JSON.stringify(enriched, null, 2);
|
|
38
47
|
}
|
|
39
48
|
/**
|
|
@@ -45,21 +54,8 @@ export async function buildPagedResult(cmd, args, cwd, page, pageSize, config) {
|
|
|
45
54
|
checkGuard(cmd, args, cwd, config);
|
|
46
55
|
}
|
|
47
56
|
catch (err) {
|
|
48
|
-
if (err instanceof GuardError)
|
|
49
|
-
|
|
50
|
-
ok: false,
|
|
51
|
-
exitCode: -1,
|
|
52
|
-
cmd,
|
|
53
|
-
args,
|
|
54
|
-
cwd,
|
|
55
|
-
duration_ms: 0,
|
|
56
|
-
stdout: { raw: "", parsed: null },
|
|
57
|
-
stderr: { raw: err.message, parsed: null },
|
|
58
|
-
diff: null,
|
|
59
|
-
guard_error: { reason: err.reason, message: err.message },
|
|
60
|
-
};
|
|
61
|
-
return JSON.stringify(envelope, null, 2);
|
|
62
|
-
}
|
|
57
|
+
if (err instanceof GuardError)
|
|
58
|
+
return buildGuardErrorEnvelope(cmd, args, cwd, err);
|
|
63
59
|
throw err;
|
|
64
60
|
}
|
|
65
61
|
// 전체 stdout이 필요하므로 max_output_bytes 비활성 (0)
|
|
@@ -81,13 +77,16 @@ export function createServer(config) {
|
|
|
81
77
|
name: "parism",
|
|
82
78
|
version: PACKAGE_VERSION,
|
|
83
79
|
});
|
|
84
|
-
server.tool("run", "Execute a shell command and receive structured
|
|
85
|
-
"All commands are filtered through an execution guard (whitelist + injection prevention)."
|
|
80
|
+
server.tool("run", "Execute a shell command and receive structured output. " +
|
|
81
|
+
"All commands are filtered through an execution guard (whitelist + injection prevention). " +
|
|
82
|
+
"Use format='compact' for token-efficient columnar output.", {
|
|
86
83
|
cmd: z.string().describe("Command name (e.g. 'ls', 'git')"),
|
|
87
84
|
args: z.array(z.string()).default([]).describe("Command arguments"),
|
|
88
85
|
cwd: z.string().default(process.cwd()).describe("Working directory"),
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
format: z.enum(["json", "compact"]).default("json")
|
|
87
|
+
.describe("Output format. 'compact' uses columnar schema+rows for lower token cost"),
|
|
88
|
+
}, async ({ cmd, args, cwd, format }) => {
|
|
89
|
+
const result = await buildRunResult(cmd, args, cwd, config, format);
|
|
91
90
|
return {
|
|
92
91
|
content: [{ type: "text", text: result }],
|
|
93
92
|
};
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAmB,yCAAyC,CAAC;AAEjF,OAAO,EAAE,CAAC,EAAE,MAA2B,KAAK,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAqB,sBAAsB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAa,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAe,uBAAuB,CAAC;AAG/D,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nerdvana/parism",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Structured shell output wrapper for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"start": "node dist/index.js",
|
|
14
14
|
"test": "vitest run",
|
|
15
15
|
"test:watch": "vitest",
|
|
16
|
-
"test:coverage": "vitest run --coverage"
|
|
16
|
+
"test:coverage": "vitest run --coverage",
|
|
17
|
+
"benchmark": "npx tsx benchmarks/index.ts"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@modelcontextprotocol/sdk": "^1.10.0",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/node": "^22.0.0",
|
|
24
25
|
"@vitest/coverage-v8": "^3.0.0",
|
|
26
|
+
"gpt-tokenizer": "^3.4.0",
|
|
25
27
|
"typescript": "^5.7.0",
|
|
26
28
|
"vitest": "^3.0.0"
|
|
27
29
|
},
|
|
@@ -32,5 +34,9 @@
|
|
|
32
34
|
"engines": {
|
|
33
35
|
"node": ">=20"
|
|
34
36
|
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/JinHo-von-Choi/parism"
|
|
40
|
+
},
|
|
35
41
|
"license": "MIT"
|
|
36
42
|
}
|
package/prism.config.json
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"free", "uname", "id",
|
|
11
11
|
"echo", "date", "hostname",
|
|
12
12
|
"npm", "node", "npx",
|
|
13
|
-
"dir", "tasklist", "ipconfig", "systeminfo"
|
|
13
|
+
"dir", "tasklist", "ipconfig", "systeminfo",
|
|
14
|
+
"kubectl", "docker", "gh"
|
|
14
15
|
],
|
|
15
16
|
"allowed_paths": [],
|
|
16
17
|
"timeout_ms": 10000,
|