@nerdvana/parism 0.1.2 → 0.1.3

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 ADDED
@@ -0,0 +1,256 @@
1
+ # Parism
2
+
3
+ > Refract the Shell. Every command, structured.
4
+
5
+ <p align="right"><a href="README.md">한국어</a> | <a href="README.en.md">English</a></p>
6
+
7
+ ---
8
+
9
+ ## The Shell Was Not Designed for You
10
+
11
+ In 1969, when Ken Thompson built Unix, he assumed the output would be read by a human — specifically, a creature with eyes sitting in front of a terminal.
12
+
13
+ Half a century later, that assumption no longer holds.
14
+
15
+ An AI agent runs `ls -la` and receives its output. Then the real work begins: split on whitespace, figure out that the first column is permissions, the third is the owner, infer where the filename starts — burning tokens to reason through what a human eye processes in 0.1 seconds.
16
+
17
+ This is not translation. It is decrypting a message that was never encrypted.
18
+
19
+ ---
20
+
21
+ ## Why This Is a Problem
22
+
23
+ Three translations happen.
24
+
25
+ First: the kernel manages filesystem metadata as `stat` structures — `inode`, `mode`, `uid`, `gid`, `size`, `mtime`. Already perfectly structured data.
26
+
27
+ Second: `ls` flattens that structure into human-readable text. `drwxr-xr-x 2 user group 4096 Mar 06 09:23 src`. Structure collapses into string.
28
+
29
+ Third: the agent tries to reconstruct that structure from the text. Rebuilding what was just torn down.
30
+
31
+ Parism intervenes between the second and third step. It recovers what was discarded.
32
+
33
+ This has a cost. Running `ls` once looks simple, but the agent may spend dozens of inference steps parsing the output — and often gets it wrong. Edge cases, unexpected whitespace, OS-specific formatting quirks. Wrong means retry. Retry means more tokens.
34
+
35
+ ---
36
+
37
+ ## What Parism Does
38
+
39
+ A prism does not destroy light. It decomposes it.
40
+
41
+ ```
42
+ "drwxr-xr-x 2 user group 4096 Mar 06 09:23 src"
43
+
44
+ ↓ Parism
45
+
46
+ {
47
+ "type": "directory",
48
+ "name": "src",
49
+ "permissions": { "owner": "rwx", "group": "r-x", "other": "r-x" },
50
+ "size_bytes": 4096,
51
+ "owner": "user",
52
+ "group": "group",
53
+ "modified_at": "2026-03-06T09:23:00"
54
+ }
55
+ ```
56
+
57
+ The information does not change. The shape does. The agent no longer parses. It reads.
58
+
59
+ ---
60
+
61
+ ## Why This Is Better
62
+
63
+ ### No More Parsing Errors
64
+
65
+ Text parsing breaks easily. `ps aux` has different column ordering on Linux and macOS. The `1K-blocks` header in `df -h` varies by environment. Filenames with spaces almost always break `ls` parsing. Parism's parsers handle these cases directly. The agent receives structured data.
66
+
67
+ ### Fewer Retries
68
+
69
+ When an agent misinterprets output, it re-queries, runs a second command to verify, or proceeds with bad data. All three cost tokens. Structured output reduces room for misinterpretation. The file count is not something to infer — it is `entries.length`.
70
+
71
+ ### `raw` Is Always Preserved
72
+
73
+ Parsers can be wrong. Some commands have no parser. So Parism always keeps `raw`. `parsed` is a bonus. `raw` is the fallback. The agent can always return to the original output.
74
+
75
+ ```json
76
+ "stdout": {
77
+ "raw": "drwxr-xr-x ...",
78
+ "parsed": { "entries": [ ... ] }
79
+ }
80
+ ```
81
+
82
+ ### Consistent Response Structure
83
+
84
+ Whether success or failure, `ok` and `exitCode` are always in the same place. The agent's branching logic becomes simple. Not "parse stdout to check for errors" — just `if (!result.ok)`.
85
+
86
+ ### Execution Time Is Recorded
87
+
88
+ Every response includes `duration_ms`. The agent can judge whether a command is slow or fast. Useful for debugging too.
89
+
90
+ ---
91
+
92
+ ## Guard — Why Not to Trust the Agent
93
+
94
+ `rm -rf /` can be written in three characters.
95
+
96
+ Agents make mistakes. They lose context, confuse paths, generate unintended commands. Guard is not about distrust — it is about designing so that agent mistakes do not become catastrophes.
97
+
98
+ There are four layers of defense.
99
+
100
+ **Command Whitelist**: Commands not in `allowed_commands` are never executed. No process is created. Rejected silently.
101
+
102
+ **Path Restriction**: When `allowed_paths` is set, commands referencing paths outside it are blocked. The agent cannot touch `/etc`.
103
+
104
+ **Injection Pattern Blocking**: If `;`, `$(`, `` ` ``, `&&`, `||`, or `|` appear in any argument, the command is not executed. Regardless of agent intent.
105
+
106
+ **Per-Command Argument Restrictions** *(v0.1.2)*: Specific flags can be blocked per command. `node -e` and `node --eval` allow arbitrary code execution — they are blocked by default. `npx --yes` silently installs packages from the internet — also blocked.
107
+
108
+ A blocked command returns this:
109
+
110
+ ```json
111
+ {
112
+ "ok": false,
113
+ "guard_error": {
114
+ "reason": "command_not_allowed",
115
+ "message": "Command 'rm' is not in the allowed list"
116
+ }
117
+ }
118
+ ```
119
+
120
+ The agent receives the block reason in the same envelope structure as any other result. No exceptions thrown. No pipeline broken.
121
+
122
+ ---
123
+
124
+ ## Supported Commands — 31 Built-in Parsers
125
+
126
+ | Category | Command | Parsed Output |
127
+ |---|---|---|
128
+ | Filesystem | `ls` | `entries[]` — name, type, permissions, size, modified time, owner |
129
+ | Filesystem | `find` | `paths[]` — list of paths |
130
+ | Filesystem | `stat` | `file`, `size_bytes`, `inode`, `permissions`, `uid`, `gid`, timestamps |
131
+ | Filesystem | `du` | `entries[]` — size, path |
132
+ | Filesystem | `df` | `filesystems[]` — partition, usage, mount point |
133
+ | Filesystem | `tree` | `root`, `tree{}` — hierarchical node map, `total_files`, `total_dirs` |
134
+ | Process | `ps` | `processes[]` — PID, CPU%, MEM%, command |
135
+ | Process | `kill` | raw pass-through |
136
+ | Network | `ping` | `target`, `packets_transmitted`, `packet_loss_percent`, `rtt_*_ms` |
137
+ | Network | `curl -I` | `status_code`, `headers{}` |
138
+ | Network | `netstat` | `connections[]` — proto, local/foreign address, state |
139
+ | Network | `lsof -i` | `entries[]` — PID, process name, protocol, local/remote address, state |
140
+ | Network | `ss` | `entries[]` — state, recv/send queue, local/peer address, process |
141
+ | Network | `dig` | `query`, `answers[]` — type, value, TTL, `query_time_ms` |
142
+ | Text | `grep` | `matches[]` — file, line number, text |
143
+ | Text | `wc` | `entries[]` — count, filename |
144
+ | Text | `head`, `tail`, `cat` | `lines[]` |
145
+ | Git | `git status` | `branch`, `staged[]`, `modified[]`, `untracked[]` |
146
+ | Git | `git log --oneline` | `commits[]` — hash, message |
147
+ | Git | `git diff` | `files_changed[]` |
148
+ | Git | `git branch -vv` | `branches[]` — name, current, upstream, ahead/behind |
149
+ | Env | `env` | `vars{}` — key-value map (secrets filtered) |
150
+ | Env | `pwd` | `path` |
151
+ | Env | `which` | `paths[]` |
152
+ | System | `free` | `mem`, `swap` — total, used, free, available in bytes |
153
+ | System | `uname` | `kernel_name`, `hostname`, `kernel_release`, `machine`, `os` |
154
+ | System | `id` | `uid`, `gid`, `user`, `group`, `groups[]` — id, name |
155
+ | Windows | `dir` | `directory`, `entries[]` — name, type, size, modified time, `free_bytes` |
156
+ | Windows | `tasklist` | `processes[]` — name, PID, session, memory. CSV format supported |
157
+ | Windows | `ipconfig` | `hostname`, `adapters[]` — IPv4/6, subnet, gateway, DNS, MAC |
158
+ | Windows | `systeminfo` | `hostname`, `os_name`, memory, `hotfixes[]`, `network_cards[]` |
159
+
160
+ Commands without a parser return `parsed: null`. `raw` is always present.
161
+
162
+ ---
163
+
164
+ ## Installation
165
+
166
+ ### npx
167
+
168
+ ```bash
169
+ npx @nerdvana/parism
170
+ ```
171
+
172
+ ### Local Build
173
+
174
+ ```bash
175
+ git clone https://github.com/your-org/parism
176
+ cd parism
177
+ npm install && npm run build
178
+ node dist/index.js
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Claude Desktop Integration
184
+
185
+ `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
186
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
187
+
188
+ ```json
189
+ {
190
+ "mcpServers": {
191
+ "parism": {
192
+ "command": "npx",
193
+ "args": ["-y", "@nerdvana/parism"]
194
+ }
195
+ }
196
+ }
197
+ ```
198
+
199
+ Claude Code (Linux):
200
+
201
+ ```json
202
+ {
203
+ "mcpServers": {
204
+ "parism": {
205
+ "command": "node",
206
+ "args": ["/path/to/parism/dist/index.js"],
207
+ "cwd": "/path/to/parism"
208
+ }
209
+ }
210
+ }
211
+ ```
212
+
213
+ Once connected, a single `run` tool is exposed. The agent uses it to execute commands and receive JSON.
214
+
215
+ ---
216
+
217
+ ## Configuration
218
+
219
+ Place `prism.config.json` in the project root to control Guard behavior.
220
+
221
+ ```json
222
+ {
223
+ "guard": {
224
+ "allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
225
+ "allowed_paths": ["/home/user/projects"],
226
+ "timeout_ms": 10000,
227
+ "block_patterns": [";", "$(", "`", "&&", "||", "|"],
228
+ "command_arg_restrictions": {
229
+ "node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print"] },
230
+ "npx": { "blocked_flags": ["--yes", "-y"] }
231
+ },
232
+ "env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "CREDENTIAL"]
233
+ }
234
+ }
235
+ ```
236
+
237
+ `allowed_paths` being empty means no path restriction. That decision is yours.
238
+
239
+ `env_secret_patterns` strips matching environment variables from child processes before execution. The `env` command will not expose them.
240
+
241
+ ---
242
+
243
+ ## What Parism Is Not
244
+
245
+ Parism is not a new shell. It does not replace bash. It sits above bash, receives output, and structures it.
246
+
247
+ Parism is not an operating system for AI. Its concern is singular: when an agent issues a command, return the result in a form the agent can understand.
248
+
249
+ The Unix philosophy was "do one thing well." Parism understands that.
250
+
251
+ ---
252
+
253
+ <p align="center">
254
+ Made by <a href="mailto:jinho.von.choi@nerdvana.kr">Jinho Choi</a> &nbsp;|&nbsp;
255
+ <a href="https://buymeacoffee.com/jinho.von.choi">Buy me a coffee</a>
256
+ </p>
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  > Refract the Shell. Every command, structured.
4
4
 
5
+ <p align="right"><a href="README.md">한국어</a> | <a href="README.en.md">English</a></p>
6
+
5
7
  ---
6
8
 
7
9
  ## 셸은 당신을 위해 설계되지 않았다
@@ -93,7 +95,7 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
93
95
 
94
96
  에이전트는 오류를 범한다. 문맥을 잃고, 경로를 착각하고, 의도하지 않은 명령을 생성한다. Guard는 에이전트를 불신하는 것이 아니다. 에이전트의 실수가 파국으로 이어지지 않도록 설계하는 것이다.
95
97
 
96
- 겹의 방어선이 있다.
98
+ 겹의 방어선이 있다.
97
99
 
98
100
  **화이트리스트**: `allowed_commands`에 없는 명령어는 실행되지 않는다. 프로세스를 만들지도 않는다. 설명 없이 거절한다.
99
101
 
@@ -101,6 +103,8 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
101
103
 
102
104
  **인젝션 패턴 차단**: `;`, `$(`, `` ` ``, `&&`, `||`, `|`가 인자에 포함되면 실행하지 않는다. 에이전트가 의도했든 아니든.
103
105
 
106
+ **명령별 인자 제한** *(v0.1.2)*: 명령마다 차단할 플래그를 지정할 수 있다. `node -e`와 `node --eval`은 임의 코드 실행 경로이므로 기본 차단된다. `npx --yes`는 인터넷에서 패키지를 설치하므로 마찬가지다.
107
+
104
108
  차단된 명령은 이런 응답을 반환한다.
105
109
 
106
110
  ```json
@@ -123,7 +127,7 @@ Parism이 개입하는 것은 두 번째와 세 번째 사이다. 한 번 버려
123
127
  |---|---|---|
124
128
  | 파일시스템 | `ls` | `entries[]` — 이름, 타입, 권한, 크기, 수정 시각, 소유자 |
125
129
  | 파일시스템 | `find` | `paths[]` — 경로 목록 |
126
- | 파일시스템 | `stat` | `lines[]` 원본 라인 배열 |
130
+ | 파일시스템 | `stat` | `file`, `size_bytes`, `inode`, `permissions`, `uid`, `gid`, 타임스탬프 |
127
131
  | 파일시스템 | `du` | `entries[]` — 크기, 경로 |
128
132
  | 파일시스템 | `df` | `filesystems[]` — 파티션, 사용량, 마운트 위치 |
129
133
  | 파일시스템 | `tree` | `root`, `tree{}` — 계층 구조 노드, `total_files`, `total_dirs` |
@@ -220,13 +224,20 @@ Claude Code (Linux):
220
224
  "allowed_commands": ["ls", "git", "find", "grep", "env", "ps"],
221
225
  "allowed_paths": ["/home/user/projects"],
222
226
  "timeout_ms": 10000,
223
- "block_patterns": [";", "$(", "`", "&&", "||", "|"]
227
+ "block_patterns": [";", "$(", "`", "&&", "||", "|"],
228
+ "command_arg_restrictions": {
229
+ "node": { "blocked_flags": ["-e", "--eval", "-r", "--require", "-p", "--print"] },
230
+ "npx": { "blocked_flags": ["--yes", "-y"] }
231
+ },
232
+ "env_secret_patterns": ["TOKEN", "SECRET", "AUTHZ", "PASSWORD", "CREDENTIAL"]
224
233
  }
225
234
  }
226
235
  ```
227
236
 
228
237
  `allowed_paths`가 비어 있으면 경로 제한 없이 실행된다. 판단은 당신 몫이다.
229
238
 
239
+ `env_secret_patterns`에 일치하는 환경 변수는 실행 전 자식 프로세스에서 제거된다. `env` 명령 실행 시 해당 변수가 노출되지 않는다.
240
+
230
241
  ---
231
242
 
232
243
  ## Parism이 아닌 것
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
2
2
  export const DEFAULT_CONFIG = {
3
3
  guard: {
4
4
  allowed_commands: [
5
- "ls", "find", "stat", "du", "df",
5
+ "ls", "find", "stat", "du", "df", "tree",
6
6
  "ps", "kill",
7
7
  "ping", "curl", "netstat",
8
8
  "grep", "wc", "head", "tail", "cat",
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAmB5C,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,EAAE;QACL,gBAAgB,EAAE;YAChB,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;YAChC,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;SACpC;QACD,aAAa,EAAG,EAAE;QAClB,UAAU,EAAM,KAAK;QACrB,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,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,OAAO;YACL,KAAK,EAAE,EAAE,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;SAC1D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAmB5C,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;SACpC;QACD,aAAa,EAAG,EAAE;QAClB,UAAU,EAAM,KAAK;QACrB,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,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,OAAO;YACL,KAAK,EAAE,EAAE,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;SAC1D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -5,5 +5,5 @@ import type { ResponseEnvelope } from "../types/envelope.js";
5
5
  * - secretPatterns에 해당하는 환경 변수는 자식 프로세스에 전달하지 않음
6
6
  * - 실행 실패(명령 없음 포함)는 예외 대신 ok=false 봉투로 반환
7
7
  */
8
- export declare function execute(cmd: string, args: string[], cwd: string, secretPatterns?: string[]): Promise<ResponseEnvelope>;
8
+ export declare function execute(cmd: string, args: string[], cwd: string, secretPatterns?: string[], timeoutMs?: number): Promise<ResponseEnvelope>;
9
9
  //# sourceMappingURL=executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAqB7D;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAa,MAAM,EACtB,IAAI,EAAY,MAAM,EAAE,EACxB,GAAG,EAAa,MAAM,EACtB,cAAc,GAAE,MAAM,EAAO,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA0C3B"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAsB7D;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAa,MAAM,EACtB,IAAI,EAAY,MAAM,EAAE,EACxB,GAAG,EAAa,MAAM,EACtB,cAAc,GAAE,MAAM,EAAO,EAC7B,SAAS,GAAO,MAAgB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CA+C3B"}
@@ -1,5 +1,6 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
+ import { takeSnapshot, computeDiff } from "./state-tracker.js";
3
4
  const execFileAsync = promisify(execFile);
4
5
  /**
5
6
  * process.env에서 시크릿 패턴과 일치하는 변수를 제거한 환경 객체를 반환한다.
@@ -23,14 +24,17 @@ function buildSanitizedEnv(secretPatterns) {
23
24
  * - secretPatterns에 해당하는 환경 변수는 자식 프로세스에 전달하지 않음
24
25
  * - 실행 실패(명령 없음 포함)는 예외 대신 ok=false 봉투로 반환
25
26
  */
26
- export async function execute(cmd, args, cwd, secretPatterns = []) {
27
+ export async function execute(cmd, args, cwd, secretPatterns = [], timeoutMs = 10000) {
27
28
  const start = Date.now();
29
+ const before = await takeSnapshot(cwd);
28
30
  try {
29
31
  const { stdout, stderr } = await execFileAsync(cmd, args, {
30
32
  cwd,
33
+ timeout: timeoutMs,
31
34
  maxBuffer: 10 * 1024 * 1024, // 10 MB
32
35
  env: { ...buildSanitizedEnv(secretPatterns), LC_ALL: "C", LANG: "C" },
33
36
  });
37
+ const after = await takeSnapshot(cwd);
34
38
  return {
35
39
  ok: true,
36
40
  exitCode: 0,
@@ -40,12 +44,13 @@ export async function execute(cmd, args, cwd, secretPatterns = []) {
40
44
  duration_ms: Date.now() - start,
41
45
  stdout: { raw: stdout, parsed: null },
42
46
  stderr: { raw: stderr, parsed: null },
43
- diff: null,
47
+ diff: computeDiff(before, after),
44
48
  };
45
49
  }
46
50
  catch (err) {
47
51
  const e = err;
48
52
  const exitCode = typeof e.code === "number" ? e.code : 1;
53
+ const after = await takeSnapshot(cwd);
49
54
  return {
50
55
  ok: false,
51
56
  exitCode,
@@ -55,7 +60,7 @@ export async function execute(cmd, args, cwd, secretPatterns = []) {
55
60
  duration_ms: Date.now() - start,
56
61
  stdout: { raw: e.stdout ?? "", parsed: null },
57
62
  stderr: { raw: e.stderr ?? e.message, parsed: null },
58
- diff: null,
63
+ diff: computeDiff(before, after),
59
64
  };
60
65
  }
61
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C;;;GAGG;AACH,SAAS,iBAAiB,CAAC,cAAwB;IACjD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC;IAEpD,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/D,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAsB,EACtB,IAAwB,EACxB,GAAsB,EACtB,iBAA2B,EAAE;IAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE;YACxD,GAAG;YACH,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ;YACrC,GAAG,EAAE,EAAE,GAAG,iBAAiB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;SACtE,CAAC,CAAC;QAEH,OAAO;YACL,EAAE,EAAW,IAAI;YACjB,QAAQ,EAAK,CAAC;YACd,GAAG;YACH,IAAI;YACJ,GAAG;YACH,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,MAAM,EAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;YAC1C,MAAM,EAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;YAC1C,IAAI,EAAS,IAAI;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAIT,CAAC;QAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO;YACL,EAAE,EAAW,KAAK;YAClB,QAAQ;YACR,GAAG;YACH,IAAI;YACJ,GAAG;YACH,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC/B,MAAM,EAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;YAClD,MAAM,EAAO,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;YACzD,IAAI,EAAS,IAAI;SAClB,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/engine/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { DiffField } from "../types/envelope.js";
2
+ /**
3
+ * 디렉토리 내 파일 경로 → mtime(ms) 맵.
4
+ */
5
+ export type FileSnapshot = Map<string, number>;
6
+ /**
7
+ * cwd 기준 depth 단계까지 재귀 스캔하여 파일 스냅샷을 반환한다.
8
+ */
9
+ export declare function takeSnapshot(cwd: string, depth?: number): Promise<FileSnapshot>;
10
+ /**
11
+ * 두 스냅샷을 비교하여 생성/삭제/수정된 경로 목록을 반환한다.
12
+ */
13
+ export declare function computeDiff(before: FileSnapshot, after: FileSnapshot): DiffField;
14
+ //# sourceMappingURL=state-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-tracker.d.ts","sourceRoot":"","sources":["../../src/engine/state-tracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAwB/C;;GAEG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAIhF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAgBhF"}
@@ -0,0 +1,53 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ async function walk(dir, depth, out) {
3
+ if (depth < 0)
4
+ return;
5
+ let entries;
6
+ try {
7
+ entries = await readdir(dir, { withFileTypes: true });
8
+ }
9
+ catch {
10
+ return; // 권한 없음 등
11
+ }
12
+ for (const entry of entries) {
13
+ const full = `${dir}/${entry.name}`;
14
+ try {
15
+ const s = await stat(full);
16
+ out.set(full, s.mtimeMs);
17
+ if (entry.isDirectory())
18
+ await walk(full, depth - 1, out);
19
+ }
20
+ catch {
21
+ // 개별 항목 오류 무시
22
+ }
23
+ }
24
+ }
25
+ /**
26
+ * cwd 기준 depth 단계까지 재귀 스캔하여 파일 스냅샷을 반환한다.
27
+ */
28
+ export async function takeSnapshot(cwd, depth = 2) {
29
+ const snap = new Map();
30
+ await walk(cwd, depth, snap);
31
+ return snap;
32
+ }
33
+ /**
34
+ * 두 스냅샷을 비교하여 생성/삭제/수정된 경로 목록을 반환한다.
35
+ */
36
+ export function computeDiff(before, after) {
37
+ const created = [];
38
+ const deleted = [];
39
+ const modified = [];
40
+ for (const [path, mtime] of after) {
41
+ const prev = before.get(path);
42
+ if (prev === undefined)
43
+ created.push(path);
44
+ else if (prev !== mtime)
45
+ modified.push(path);
46
+ }
47
+ for (const path of before.keys()) {
48
+ if (!after.has(path))
49
+ deleted.push(path);
50
+ }
51
+ return { created, deleted, modified };
52
+ }
53
+ //# sourceMappingURL=state-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-tracker.js","sourceRoot":"","sources":["../../src/engine/state-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAQjD,KAAK,UAAU,IAAI,CAAC,GAAW,EAAE,KAAa,EAAE,GAAiB;IAC/D,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO;IAEtB,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,UAAU;IACpB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;YACzB,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,MAAM,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,KAAK,GAAG,CAAC;IACvD,MAAM,IAAI,GAAiB,IAAI,GAAG,EAAE,CAAC;IACrC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAoB,EAAE,KAAmB;IACnE,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS;YAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACvC,IAAI,IAAI,KAAK,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACxC,CAAC"}
package/dist/server.js CHANGED
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  import { execute } from "./engine/executor.js";
4
4
  import { checkGuard, GuardError } from "./engine/guard.js";
5
5
  import { defaultRegistry } from "./parsers/index.js";
6
- const PACKAGE_VERSION = "0.1.2";
6
+ const PACKAGE_VERSION = "0.1.3";
7
7
  /**
8
8
  * Guard 검사 → 실행 → JSON 직렬화까지의 파이프라인.
9
9
  * MCP 서버와 테스트 코드가 공통으로 사용한다.
@@ -30,7 +30,7 @@ export async function buildRunResult(cmd, args, cwd, config) {
30
30
  }
31
31
  throw err;
32
32
  }
33
- const envelope = await execute(cmd, args, cwd, config.guard.env_secret_patterns);
33
+ const envelope = await execute(cmd, args, cwd, config.guard.env_secret_patterns, config.guard.timeout_ms);
34
34
  const parsed = defaultRegistry.parse(cmd, args, envelope.stdout.raw);
35
35
  const enriched = { ...envelope, stdout: { ...envelope.stdout, parsed } };
36
36
  return JSON.stringify(enriched, null, 2);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
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.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Structured shell output wrapper for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",