@nerdvana/parism 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.en.md +56 -0
  2. package/README.md +58 -2
  3. package/dist/cli/add.d.ts +9 -0
  4. package/dist/cli/add.d.ts.map +1 -0
  5. package/dist/cli/add.js +25 -0
  6. package/dist/cli/add.js.map +1 -0
  7. package/dist/cli/auto-loader.d.ts +7 -0
  8. package/dist/cli/auto-loader.d.ts.map +1 -0
  9. package/dist/cli/auto-loader.js +33 -0
  10. package/dist/cli/auto-loader.js.map +1 -0
  11. package/dist/cli/capture.d.ts +9 -0
  12. package/dist/cli/capture.d.ts.map +1 -0
  13. package/dist/cli/capture.js +50 -0
  14. package/dist/cli/capture.js.map +1 -0
  15. package/dist/cli/init-parser.d.ts +9 -0
  16. package/dist/cli/init-parser.d.ts.map +1 -0
  17. package/dist/cli/init-parser.js +66 -0
  18. package/dist/cli/init-parser.js.map +1 -0
  19. package/dist/cli/inspect.d.ts +16 -0
  20. package/dist/cli/inspect.d.ts.map +1 -0
  21. package/dist/cli/inspect.js +28 -0
  22. package/dist/cli/inspect.js.map +1 -0
  23. package/dist/cli/loader.d.ts +6 -0
  24. package/dist/cli/loader.d.ts.map +1 -0
  25. package/dist/cli/loader.js +19 -0
  26. package/dist/cli/loader.js.map +1 -0
  27. package/dist/cli/paths.d.ts +9 -0
  28. package/dist/cli/paths.d.ts.map +1 -0
  29. package/dist/cli/paths.js +19 -0
  30. package/dist/cli/paths.js.map +1 -0
  31. package/dist/cli/test-runner.d.ts +21 -0
  32. package/dist/cli/test-runner.d.ts.map +1 -0
  33. package/dist/cli/test-runner.js +36 -0
  34. package/dist/cli/test-runner.js.map +1 -0
  35. package/dist/cli.d.ts +6 -0
  36. package/dist/cli.d.ts.map +1 -0
  37. package/dist/cli.js +81 -0
  38. package/dist/cli.js.map +1 -0
  39. package/dist/index.js +28 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/parsers/index.d.ts +7 -1
  42. package/dist/parsers/index.d.ts.map +1 -1
  43. package/dist/parsers/index.js +66 -57
  44. package/dist/parsers/index.js.map +1 -1
  45. package/dist/parsers/registry.d.ts +39 -0
  46. package/dist/parsers/registry.d.ts.map +1 -1
  47. package/dist/parsers/registry.js +20 -0
  48. package/dist/parsers/registry.js.map +1 -1
  49. package/dist/server.d.ts +4 -3
  50. package/dist/server.d.ts.map +1 -1
  51. package/dist/server.js +5 -6
  52. package/dist/server.js.map +1 -1
  53. package/package.json +6 -1
package/README.en.md CHANGED
@@ -323,6 +323,62 @@ Place `prism.config.json` in the project root to control Guard behavior.
323
323
 
324
324
  ---
325
325
 
326
+ ## Custom Parsers -- Build and Use Immediately
327
+
328
+ When 44 built-in parsers are not enough, build your own. Parism v0.5.0 includes a CLI toolkit.
329
+
330
+ ### Create a Parser in 5 Minutes
331
+
332
+ ```bash
333
+ # 1. Capture command output
334
+ parism capture "htop -b -n 1"
335
+
336
+ # 2. Scaffold a parser pack
337
+ parism init-parser htop
338
+
339
+ # 3. Edit parser.ts and test against fixtures
340
+ parism test htop
341
+
342
+ # 4. Register -- available immediately, no restart needed
343
+ parism add ./htop
344
+
345
+ # 5. Verify -- raw/parsed/compact comparison + token counts
346
+ parism inspect "htop -b -n 1"
347
+ ```
348
+
349
+ Registered parsers are stored in `~/.parism/parsers/` and automatically loaded when the MCP server starts.
350
+
351
+ ### CLI Commands
352
+
353
+ | Command | Description |
354
+ |---|---|
355
+ | `parism capture "<command>"` | Execute command and save raw output as fixture |
356
+ | `parism init-parser <name>` | Scaffold a TypeScript parser pack (parser.ts + schema.json + fixtures/) |
357
+ | `parism test [parser]` | Run fixture replay tests |
358
+ | `parism add <path>` | Register a local parser pack permanently to ~/.parism/parsers/ |
359
+ | `parism inspect "<command>"` | Compare raw / parsed / compact output + token counts |
360
+
361
+ ### ParserPack Interface
362
+
363
+ External parsers implement this interface:
364
+
365
+ ```typescript
366
+ import type { ParserPack } from "@nerdvana/parism/types";
367
+
368
+ const pack: ParserPack = {
369
+ name: "my-command",
370
+ parse(raw, args, ctx?) { /* return structured result */ },
371
+ schema: { /* JSON Schema */ },
372
+ fixtures: [{ input: "...", args: [], expected: { /* ... */ } }],
373
+ };
374
+
375
+ export default pack;
376
+ ```
377
+
378
+ Running `parism` without arguments starts the MCP server as before.
379
+
380
+ ---
381
+
326
382
  ## What Parism Is Not
327
383
 
328
384
  Parism is not a new shell. It does not replace bash. It sits above bash, receives output, and structures it.
package/README.md CHANGED
@@ -274,8 +274,8 @@ Claude Code (Linux):
274
274
  "mcpServers": {
275
275
  "parism": {
276
276
  "command": "node",
277
- "args": ["/home/nirna/job/nerdvana-prism/dist/index.js"],
278
- "cwd": "/home/nirna/job/nerdvana-prism"
277
+ "args": ["/path/to/parism/dist/index.js"],
278
+ "cwd": "/path/to/parism"
279
279
  }
280
280
  }
281
281
  }
@@ -364,6 +364,62 @@ compact 예시:
364
364
 
365
365
  ---
366
366
 
367
+ ## 커스텀 파서 -- 직접 만들고 바로 쓴다
368
+
369
+ 44개 내장 파서로 부족하면, 직접 만들면 된다. Parism v0.5.0부터 CLI 도구가 포함된다.
370
+
371
+ ### 5분 안에 파서 만들기
372
+
373
+ ```bash
374
+ # 1. 명령어 출력을 캡처한다
375
+ parism capture "htop -b -n 1"
376
+
377
+ # 2. 파서 팩 스캐폴드를 생성한다
378
+ parism init-parser htop
379
+
380
+ # 3. parser.ts를 편집하고 fixture를 테스트한다
381
+ parism test htop
382
+
383
+ # 4. 등록한다 -- 재시작 없이 즉시 사용 가능
384
+ parism add ./htop
385
+
386
+ # 5. 결과를 확인한다 -- raw/parsed/compact 비교 + 토큰 수
387
+ parism inspect "htop -b -n 1"
388
+ ```
389
+
390
+ 등록된 파서는 `~/.parism/parsers/`에 저장되고, MCP 서버 시작 시 자동으로 로드된다.
391
+
392
+ ### CLI 명령어
393
+
394
+ | 명령어 | 설명 |
395
+ |---|---|
396
+ | `parism capture "<command>"` | 명령어를 실행하고 raw 출력을 fixture로 저장 |
397
+ | `parism init-parser <name>` | TypeScript 파서 팩 스캐폴드 생성 (parser.ts + schema.json + fixtures/) |
398
+ | `parism test [parser]` | fixture replay 테스트 실행 |
399
+ | `parism add <path>` | 로컬 파서 팩을 ~/.parism/parsers/에 영구 등록 |
400
+ | `parism inspect "<command>"` | raw / parsed / compact 출력 비교 + 토큰 수 |
401
+
402
+ ### ParserPack 인터페이스
403
+
404
+ 외부 파서는 이 인터페이스를 구현한다.
405
+
406
+ ```typescript
407
+ import type { ParserPack } from "@nerdvana/parism/types";
408
+
409
+ const pack: ParserPack = {
410
+ name: "my-command",
411
+ parse(raw, args, ctx?) { /* 구조화된 결과 반환 */ },
412
+ schema: { /* JSON Schema */ },
413
+ fixtures: [{ input: "...", args: [], expected: { /* ... */ } }],
414
+ };
415
+
416
+ export default pack;
417
+ ```
418
+
419
+ 인자 없이 `parism`을 실행하면 기존과 동일하게 MCP 서버로 동작한다.
420
+
421
+ ---
422
+
367
423
  ## Parism이 아닌 것
368
424
 
369
425
  Parism은 새로운 셸이 아니다. bash를 대체하지 않는다. bash 위에 앉아서 출력을 받아 구조화할 뿐이다.
@@ -0,0 +1,9 @@
1
+ export interface AddResult {
2
+ name: string;
3
+ installedTo: string;
4
+ }
5
+ /**
6
+ * 파서 팩을 ~/.parism/parsers/에 복사하고 registry.json에 등록한다.
7
+ */
8
+ export declare function addParserPack(sourcePath: string, parismHome?: string): Promise<AddResult>;
9
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/cli/add.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAS,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,CAAC,CAsBpB"}
@@ -0,0 +1,25 @@
1
+ import { cpSync, mkdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { loadParserPack } from "./loader.js";
4
+ import { ensureParismDirs } from "./paths.js";
5
+ /**
6
+ * 파서 팩을 ~/.parism/parsers/에 복사하고 registry.json에 등록한다.
7
+ */
8
+ export async function addParserPack(sourcePath, parismHome) {
9
+ const pack = await loadParserPack(resolve(sourcePath));
10
+ const home = ensureParismDirs(parismHome);
11
+ const destDir = join(home, "parsers", pack.name);
12
+ mkdirSync(destDir, { recursive: true });
13
+ cpSync(resolve(sourcePath), destDir, { recursive: true });
14
+ const registryPath = join(home, "registry.json");
15
+ const registry = existsSync(registryPath)
16
+ ? JSON.parse(readFileSync(registryPath, "utf-8"))
17
+ : {};
18
+ registry[pack.name] = {
19
+ path: destDir,
20
+ addedAt: new Date().toISOString(),
21
+ };
22
+ writeFileSync(registryPath, JSON.stringify(registry, null, 2));
23
+ return { name: pack.name, installedTo: destDir };
24
+ }
25
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/cli/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAO9C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAAkB,EAClB,UAAmB;IAEnB,MAAM,IAAI,GAAM,MAAM,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjD,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACjD,MAAM,QAAQ,GACZ,UAAU,CAAC,YAAY,CAAC;QACtB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC,EAAE,CAAC;IAET,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACpB,IAAI,EAAK,OAAO;QAChB,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAClC,CAAC;IAEF,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE/D,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ParserRegistry } from "../parsers/registry.js";
2
+ /**
3
+ * ~/.parism/registry.json을 읽고 등록된 외부 파서를 레지스트리에 로드한다.
4
+ * 로드 실패한 파서는 건너뛰고 경고 출력. 반환값: 성공 로드 수.
5
+ */
6
+ export declare function loadExternalParsers(parismHome: string, registry: ParserRegistry): Promise<number>;
7
+ //# sourceMappingURL=auto-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-loader.d.ts","sourceRoot":"","sources":["../../src/cli/auto-loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAW,wBAAwB,CAAC;AAGlE;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAI,cAAc,GACzB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
@@ -0,0 +1,33 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadParserPack } from "./loader.js";
4
+ /**
5
+ * ~/.parism/registry.json을 읽고 등록된 외부 파서를 레지스트리에 로드한다.
6
+ * 로드 실패한 파서는 건너뛰고 경고 출력. 반환값: 성공 로드 수.
7
+ */
8
+ export async function loadExternalParsers(parismHome, registry) {
9
+ const registryPath = join(parismHome, "registry.json");
10
+ if (!existsSync(registryPath))
11
+ return 0;
12
+ let entries;
13
+ try {
14
+ entries = JSON.parse(readFileSync(registryPath, "utf-8"));
15
+ }
16
+ catch {
17
+ return 0;
18
+ }
19
+ let loaded = 0;
20
+ for (const [name, entry] of Object.entries(entries)) {
21
+ try {
22
+ const pack = await loadParserPack(entry.path);
23
+ registry.registerPack(pack);
24
+ loaded++;
25
+ }
26
+ catch (err) {
27
+ const msg = err instanceof Error ? err.message : String(err);
28
+ console.warn(`[parism] Failed to load parser "${name}": ${msg}`);
29
+ }
30
+ }
31
+ return loaded;
32
+ }
33
+ //# sourceMappingURL=auto-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-loader.js","sourceRoot":"","sources":["../../src/cli/auto-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAA0B,WAAW,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAgB,aAAa,CAAC;AAEvD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAAkB,EAClB,QAA0B;IAE1B,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,CAAC,CAAC;IAExC,IAAI,OAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC5B,MAAM,EAAE,CAAC;QACX,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,mCAAmC,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface CaptureResult {
2
+ exitCode: number;
3
+ fixturePath: string;
4
+ }
5
+ /**
6
+ * 명령어를 실행하고 stdout/stderr/exitCode를 fixture JSON으로 저장한다.
7
+ */
8
+ export declare function captureCommand(cmd: string, args: string[], fixturesDir?: string): Promise<CaptureResult>;
9
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/cli/capture.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAK,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AASD;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAG,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAqCxB"}
@@ -0,0 +1,50 @@
1
+ import { execFile } from "node:child_process";
2
+ import { writeFileSync, mkdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { parismHome } from "./paths.js";
6
+ const execFileAsync = promisify(execFile);
7
+ function timestamp() {
8
+ const d = new Date();
9
+ const pad = (n) => String(n).padStart(2, "0");
10
+ return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-` +
11
+ `${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
12
+ }
13
+ /**
14
+ * 명령어를 실행하고 stdout/stderr/exitCode를 fixture JSON으로 저장한다.
15
+ */
16
+ export async function captureCommand(cmd, args, fixturesDir) {
17
+ const dir = fixturesDir ?? join(parismHome(), "fixtures");
18
+ mkdirSync(dir, { recursive: true });
19
+ let stdout;
20
+ let stderr;
21
+ let exitCode;
22
+ try {
23
+ const result = await execFileAsync(cmd, args, {
24
+ timeout: 30_000,
25
+ maxBuffer: 10 * 1024 * 1024,
26
+ });
27
+ stdout = result.stdout;
28
+ stderr = result.stderr;
29
+ exitCode = 0;
30
+ }
31
+ catch (err) {
32
+ const execErr = err;
33
+ stdout = execErr.stdout ?? "";
34
+ stderr = execErr.stderr ?? "";
35
+ exitCode = execErr.code ?? 1;
36
+ }
37
+ const fixture = {
38
+ command: cmd,
39
+ args,
40
+ stdout,
41
+ stderr,
42
+ exitCode,
43
+ captured_at: new Date().toISOString(),
44
+ };
45
+ const filename = `${cmd}-${timestamp()}.json`;
46
+ const fixturePath = join(dir, filename);
47
+ writeFileSync(fixturePath, JSON.stringify(fixture, null, 2));
48
+ return { exitCode, fixturePath };
49
+ }
50
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/cli/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAS,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAa,WAAW,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAQ,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAO,YAAY,CAAC;AAEzC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAO1C,SAAS,SAAS;IAChB,MAAM,CAAC,GAAK,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG;QAChE,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAY,EACZ,IAAc,EACd,WAAoB;IAEpB,MAAM,GAAG,GAAG,WAAW,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,UAAU,CAAC,CAAC;IAC1D,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpC,IAAI,MAAgB,CAAC;IACrB,IAAI,MAAgB,CAAC;IACrB,IAAI,QAAgB,CAAC;IAErB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE;YAC5C,OAAO,EAAI,MAAM;YACjB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC,CAAC;QACH,MAAM,GAAK,MAAM,CAAC,MAAM,CAAC;QACzB,MAAM,GAAK,MAAM,CAAC,MAAM,CAAC;QACzB,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAA0D,CAAC;QAC3E,MAAM,GAAK,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;QAChC,MAAM,GAAK,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;QAChC,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,OAAO,GAAG;QACd,OAAO,EAAM,GAAG;QAChB,IAAI;QACJ,MAAM;QACN,MAAM;QACN,QAAQ;QACR,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC;IAEF,MAAM,QAAQ,GAAM,GAAG,GAAG,IAAI,SAAS,EAAE,OAAO,CAAC;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACxC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface InitResult {
2
+ name: string;
3
+ files: string[];
4
+ }
5
+ /**
6
+ * parser pack scaffold를 생성한다.
7
+ */
8
+ export declare function initParser(name: string, baseDir: string): InitResult;
9
+ //# sourceMappingURL=init-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-parser.d.ts","sourceRoot":"","sources":["../../src/cli/init-parser.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAG,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAoDD;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAoBpE"}
@@ -0,0 +1,66 @@
1
+ import { mkdirSync, writeFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /**
4
+ * parser.ts 템플릿을 생성한다.
5
+ */
6
+ function parserTemplate(name) {
7
+ return [
8
+ 'import type { ParserPack, ParseContext } from "@nerdvana/parism";',
9
+ "",
10
+ "const pack: ParserPack = {",
11
+ ' name: "' + name + '",',
12
+ "",
13
+ " parse(raw: string, args: string[], ctx?: ParseContext): unknown {",
14
+ ' const lines = raw.trim().split("\\n").filter(Boolean);',
15
+ "",
16
+ " // TODO: implement parsing logic",
17
+ " return {",
18
+ " items: lines,",
19
+ " };",
20
+ " },",
21
+ "",
22
+ " schema: {",
23
+ ' type: "object",',
24
+ " properties: {",
25
+ ' items: { type: "array", items: { type: "string" } },',
26
+ " },",
27
+ " },",
28
+ "",
29
+ " fixtures: [],",
30
+ "};",
31
+ "",
32
+ "export default pack;",
33
+ "",
34
+ ].join("\n");
35
+ }
36
+ /**
37
+ * schema.json 내용을 생성한다.
38
+ */
39
+ function schemaTemplate() {
40
+ return JSON.stringify({
41
+ type: "object",
42
+ properties: {
43
+ items: { type: "array", items: { type: "string" } },
44
+ },
45
+ }, null, 2);
46
+ }
47
+ /**
48
+ * parser pack scaffold를 생성한다.
49
+ */
50
+ export function initParser(name, baseDir) {
51
+ const packDir = join(baseDir, name);
52
+ if (existsSync(packDir)) {
53
+ throw new Error(`Parser pack "${name}" already exists at ${packDir}`);
54
+ }
55
+ mkdirSync(packDir, { recursive: true });
56
+ mkdirSync(join(packDir, "fixtures"), { recursive: true });
57
+ const parserPath = join(packDir, "parser.ts");
58
+ const schemaPath = join(packDir, "schema.json");
59
+ writeFileSync(parserPath, parserTemplate(name));
60
+ writeFileSync(schemaPath, schemaTemplate());
61
+ return {
62
+ name,
63
+ files: [parserPath, schemaPath],
64
+ };
65
+ }
66
+ //# sourceMappingURL=init-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-parser.js","sourceRoot":"","sources":["../../src/cli/init-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO;QACL,mEAAmE;QACnE,EAAE;QACF,4BAA4B;QAC5B,WAAW,GAAG,IAAI,GAAG,IAAI;QACzB,EAAE;QACF,qEAAqE;QACrE,4DAA4D;QAC5D,EAAE;QACF,sCAAsC;QACtC,cAAc;QACd,qBAAqB;QACrB,QAAQ;QACR,MAAM;QACN,EAAE;QACF,aAAa;QACb,qBAAqB;QACrB,mBAAmB;QACnB,4DAA4D;QAC5D,QAAQ;QACR,MAAM;QACN,EAAE;QACF,iBAAiB;QACjB,IAAI;QACJ,EAAE;QACF,sBAAsB;QACtB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;SACpD;KACF,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAEpC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,uBAAuB,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAEhD,aAAa,CAAC,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;IAE5C,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ParserRegistry } from "../parsers/registry.js";
2
+ export interface InspectResult {
3
+ raw: string;
4
+ parsed: unknown | null;
5
+ compact: unknown | null;
6
+ tokens: {
7
+ raw: number;
8
+ parsed: number;
9
+ compact: number;
10
+ };
11
+ }
12
+ /**
13
+ * 명령어 raw 출력을 파싱/컴팩트 변환하고, 각 형식의 토큰 수를 추정한다.
14
+ */
15
+ export declare function inspectOutput(cmd: string, args: string[], raw: string, registry: ParserRegistry): InspectResult;
16
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/cli/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAM,MAAM,CAAC;IAChB,MAAM,EAAG,OAAO,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE;QACN,GAAG,EAAM,MAAM,CAAC;QAChB,MAAM,EAAG,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AASD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAO,MAAM,EAChB,IAAI,EAAM,MAAM,EAAE,EAClB,GAAG,EAAO,MAAM,EAChB,QAAQ,EAAE,cAAc,GACvB,aAAa,CAmBf"}
@@ -0,0 +1,28 @@
1
+ import { toCompact } from "../parsers/compact.js";
2
+ /**
3
+ * 토큰 수 추정. Math.ceil(text.length / 4) -- 간단한 근사.
4
+ */
5
+ function estimateTokens(text) {
6
+ return Math.ceil(text.length / 4);
7
+ }
8
+ /**
9
+ * 명령어 raw 출력을 파싱/컴팩트 변환하고, 각 형식의 토큰 수를 추정한다.
10
+ */
11
+ export function inspectOutput(cmd, args, raw, registry) {
12
+ const { parsed } = registry.parse(cmd, args, raw);
13
+ const compact = parsed != null ? toCompact(parsed) : null;
14
+ const rawTokens = estimateTokens(raw);
15
+ const parsedTokens = parsed != null ? estimateTokens(JSON.stringify(parsed, null, 2)) : 0;
16
+ const compactTokens = compact != null ? estimateTokens(JSON.stringify(compact, null, 2)) : 0;
17
+ return {
18
+ raw,
19
+ parsed,
20
+ compact,
21
+ tokens: {
22
+ raw: rawTokens,
23
+ parsed: parsedTokens,
24
+ compact: compactTokens,
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/cli/inspect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAgB,uBAAuB,CAAC;AAa5D;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAgB,EAChB,IAAkB,EAClB,GAAgB,EAChB,QAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1D,MAAM,SAAS,GAAO,cAAc,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAI,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,aAAa,GAAG,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7F,OAAO;QACL,GAAG;QACH,MAAM;QACN,OAAO;QACP,MAAM,EAAE;YACN,GAAG,EAAM,SAAS;YAClB,MAAM,EAAG,YAAY;YACrB,OAAO,EAAE,aAAa;SACvB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ParserPack } from "../parsers/registry.js";
2
+ /**
3
+ * 디렉토리에서 parser.js를 동적 import로 로드한다.
4
+ */
5
+ export declare function loadParserPack(packDir: string): Promise<ParserPack>;
6
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/cli/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAezE"}
@@ -0,0 +1,19 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ /**
5
+ * 디렉토리에서 parser.js를 동적 import로 로드한다.
6
+ */
7
+ export async function loadParserPack(packDir) {
8
+ const parserPath = join(packDir, "parser.js");
9
+ if (!existsSync(parserPath)) {
10
+ throw new Error(`parser.js not found in ${packDir}`);
11
+ }
12
+ const mod = await import(pathToFileURL(parserPath).href);
13
+ const pack = mod.default;
14
+ if (!pack || typeof pack.name !== "string" || typeof pack.parse !== "function") {
15
+ throw new Error(`Invalid default export in ${parserPath} -- must be a ParserPack`);
16
+ }
17
+ return pack;
18
+ }
19
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/cli/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAS,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAe,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAE9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,GAAG,GAAI,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC;IAEzB,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,0BAA0B,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,IAAkB,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Parism 홈 디렉토리 경로. PARISM_HOME 환경변수 우선, 없으면 ~/.parism.
3
+ */
4
+ export declare function parismHome(): string;
5
+ /**
6
+ * ~/.parism/ 하위 디렉토리 구조를 보장한다.
7
+ */
8
+ export declare function ensureParismDirs(base?: string): string;
9
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/cli/paths.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtD"}
@@ -0,0 +1,19 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ /**
5
+ * Parism 홈 디렉토리 경로. PARISM_HOME 환경변수 우선, 없으면 ~/.parism.
6
+ */
7
+ export function parismHome() {
8
+ return process.env.PARISM_HOME ?? join(homedir(), ".parism");
9
+ }
10
+ /**
11
+ * ~/.parism/ 하위 디렉토리 구조를 보장한다.
12
+ */
13
+ export function ensureParismDirs(base) {
14
+ const home = base ?? parismHome();
15
+ mkdirSync(join(home, "fixtures"), { recursive: true });
16
+ mkdirSync(join(home, "parsers"), { recursive: true });
17
+ return home;
18
+ }
19
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/cli/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAQ,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAW,WAAW,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,UAAU,EAAE,CAAC;IAClC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ParserPack } from "../parsers/registry.js";
2
+ export interface FixtureTestDetail {
3
+ index: number;
4
+ status: "pass" | "fail" | "error";
5
+ expected: unknown;
6
+ actual?: unknown;
7
+ error?: string;
8
+ }
9
+ export interface FixtureTestResults {
10
+ name: string;
11
+ total: number;
12
+ passed: number;
13
+ failed: number;
14
+ errored: number;
15
+ details: FixtureTestDetail[];
16
+ }
17
+ /**
18
+ * ParserPack의 fixture를 순회하며 replay 테스트를 실행한다.
19
+ */
20
+ export declare function runFixtureTests(pack: ParserPack): FixtureTestResults;
21
+ //# sourceMappingURL=test-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../src/cli/test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAK,MAAM,CAAC;IACjB,MAAM,EAAI,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAG,OAAO,CAAC;IAClB,KAAK,CAAC,EAAI,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAK,MAAM,CAAC;IAChB,KAAK,EAAI,MAAM,CAAC;IAChB,MAAM,EAAG,MAAM,CAAC;IAChB,MAAM,EAAG,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB,CAkCpE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ParserPack의 fixture를 순회하며 replay 테스트를 실행한다.
3
+ */
4
+ export function runFixtureTests(pack) {
5
+ const details = [];
6
+ for (let i = 0; i < pack.fixtures.length; i++) {
7
+ const fixture = pack.fixtures[i];
8
+ try {
9
+ const actual = pack.parse(fixture.input, fixture.args);
10
+ const match = JSON.stringify(actual) === JSON.stringify(fixture.expected);
11
+ details.push({
12
+ index: i,
13
+ status: match ? "pass" : "fail",
14
+ expected: fixture.expected,
15
+ actual,
16
+ });
17
+ }
18
+ catch (err) {
19
+ details.push({
20
+ index: i,
21
+ status: "error",
22
+ expected: fixture.expected,
23
+ error: err instanceof Error ? err.message : String(err),
24
+ });
25
+ }
26
+ }
27
+ return {
28
+ name: pack.name,
29
+ total: details.length,
30
+ passed: details.filter(d => d.status === "pass").length,
31
+ failed: details.filter(d => d.status === "fail").length,
32
+ errored: details.filter(d => d.status === "error").length,
33
+ details,
34
+ };
35
+ }
36
+ //# sourceMappingURL=test-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../src/cli/test-runner.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAgB;IAC9C,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,KAAK,GAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAE3E,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAK,CAAC;gBACX,MAAM,EAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;gBACjC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,EAAK,CAAC;gBACX,MAAM,EAAI,OAAO;gBACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,KAAK,EAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC3D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAK,IAAI,CAAC,IAAI;QAClB,KAAK,EAAI,OAAO,CAAC,MAAM;QACvB,MAAM,EAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;QACxD,MAAM,EAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;QACxD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM;QACzD,OAAO;KACR,CAAC;AACJ,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * CLI 프로그램을 생성한다. 명령어 핸들러는 각 모듈에서 등록.
4
+ */
5
+ export declare function createCli(): Command;
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAoFnC"}
package/dist/cli.js ADDED
@@ -0,0 +1,81 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * CLI 프로그램을 생성한다. 명령어 핸들러는 각 모듈에서 등록.
4
+ */
5
+ export function createCli() {
6
+ const program = new Command();
7
+ program
8
+ .name("parism")
9
+ .description("Structured shell output for AI agents")
10
+ .version("0.5.0");
11
+ program
12
+ .command("capture <command>")
13
+ .description("Execute command and save raw output as fixture")
14
+ .option("-o, --output <dir>", "Output directory", "~/.parism/fixtures")
15
+ .action(async (command, options) => {
16
+ const { captureCommand } = await import("./cli/capture.js");
17
+ const parts = command.split(/\s+/);
18
+ const cmd = parts[0];
19
+ const args = parts.slice(1);
20
+ const result = await captureCommand(cmd, args, options.output);
21
+ console.log(`Fixture saved: ${result.fixturePath}`);
22
+ console.log(`Exit code: ${result.exitCode}`);
23
+ });
24
+ program
25
+ .command("init-parser <name>")
26
+ .description("Scaffold a new parser pack (TypeScript + schema + test)")
27
+ .option("-d, --dir <dir>", "Output directory", ".")
28
+ .action(async (name, options) => {
29
+ const { initParser } = await import("./cli/init-parser.js");
30
+ const result = initParser(name, options.dir ?? ".");
31
+ console.log(`Parser pack "${result.name}" created:`);
32
+ result.files.forEach(f => console.log(` ${f}`));
33
+ });
34
+ program
35
+ .command("test [parser]")
36
+ .description("Run fixture replay tests for a parser pack")
37
+ .action(async (_parser) => {
38
+ console.log("[parism] test: not yet implemented");
39
+ process.exit(1);
40
+ });
41
+ program
42
+ .command("add <path>")
43
+ .description("Register a local parser pack permanently")
44
+ .action(async (pathArg) => {
45
+ const { addParserPack } = await import("./cli/add.js");
46
+ const result = await addParserPack(pathArg);
47
+ console.log(`Parser "${result.name}" added to ${result.installedTo}`);
48
+ });
49
+ program
50
+ .command("inspect <command>")
51
+ .description("Show raw / parsed / compact output comparison")
52
+ .action(async (command) => {
53
+ const { inspectOutput } = await import("./cli/inspect.js");
54
+ const { createRegistry } = await import("./parsers/index.js");
55
+ const { execFile } = await import("node:child_process");
56
+ const { promisify } = await import("node:util");
57
+ const execFileAsync = promisify(execFile);
58
+ const parts = command.split(/\s+/);
59
+ const cmd = parts[0];
60
+ const args = parts.slice(1);
61
+ const registry = createRegistry();
62
+ let raw;
63
+ try {
64
+ const result = await execFileAsync(cmd, args, { timeout: 10_000 });
65
+ raw = result.stdout;
66
+ }
67
+ catch (err) {
68
+ raw = err.stdout ?? "";
69
+ }
70
+ const result = inspectOutput(cmd, args, raw, registry);
71
+ console.log("=== RAW ===");
72
+ console.log(result.raw);
73
+ console.log("\n=== PARSED ===");
74
+ console.log(JSON.stringify(result.parsed, null, 2));
75
+ console.log("\n=== COMPACT ===");
76
+ console.log(JSON.stringify(result.compact, null, 2));
77
+ console.log(`\nTokens: raw=${result.tokens.raw} parsed=${result.tokens.parsed} compact=${result.tokens.compact}`);
78
+ });
79
+ return program;
80
+ }
81
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,QAAQ,CAAC;SACd,WAAW,CAAC,uCAAuC,CAAC;SACpD,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,CAAC;SACtE,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAA4B,EAAE,EAAE;QAC9D,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,GAAG,GAAM,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,IAAI,GAAK,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,yDAAyD,CAAC;SACtE,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,GAAG,CAAC;SAClD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAAyB,EAAE,EAAE;QACxD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;QAC5C,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,EAAE;QAChC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,IAAI,cAAc,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,EAAE;QAChC,MAAM,EAAE,aAAa,EAAE,GAAI,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC9D,MAAM,EAAE,QAAQ,EAAE,GAAS,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC9D,MAAM,EAAE,SAAS,EAAE,GAAQ,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,KAAK,GAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,GAAG,GAAQ,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAElC,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACnE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;QACtB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,GAAG,GAAI,GAA2B,CAAC,MAAM,IAAI,EAAE,CAAC;QAClD,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,MAAM,CAAC,GAAG,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACpH,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.js CHANGED
@@ -2,14 +2,40 @@
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { createServer } from "./server.js";
4
4
  import { loadConfig } from "./config/loader.js";
5
+ import { createRegistry } from "./parsers/index.js";
6
+ import { createCli } from "./cli.js";
5
7
  import path from "node:path";
6
- async function main() {
8
+ const CLI_COMMANDS = ["capture", "init-parser", "test", "add", "inspect", "help", "--help", "-h", "--version", "-V"];
9
+ function isCliMode() {
10
+ const firstArg = process.argv[2];
11
+ return firstArg != null && CLI_COMMANDS.includes(firstArg);
12
+ }
13
+ async function startMcpServer() {
7
14
  const configPath = path.join(process.cwd(), "prism.config.json");
8
15
  const config = await loadConfig(configPath);
9
- const server = createServer(config);
16
+ const registry = createRegistry();
17
+ const { loadExternalParsers } = await import("./cli/auto-loader.js");
18
+ const { parismHome } = await import("./cli/paths.js");
19
+ const loaded = await loadExternalParsers(parismHome(), registry);
20
+ if (loaded > 0) {
21
+ console.error(`[parism] Loaded ${loaded} external parser(s)`);
22
+ }
23
+ const server = createServer(config, registry);
10
24
  const transport = new StdioServerTransport();
11
25
  await server.connect(transport);
12
26
  }
27
+ async function startCli() {
28
+ const program = createCli();
29
+ await program.parseAsync(process.argv);
30
+ }
31
+ async function main() {
32
+ if (isCliMode()) {
33
+ await startCli();
34
+ }
35
+ else {
36
+ await startMcpServer();
37
+ }
38
+ }
13
39
  main().catch((err) => {
14
40
  console.error("[parism] Fatal error:", err);
15
41
  process.exit(1);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAc,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAgB,oBAAoB,CAAC;AAC1D,OAAO,IAAI,MAA0B,WAAW,CAAC;AAEjD,KAAK,UAAU,IAAI;IACjB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAO,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAc,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAgB,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAY,oBAAoB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAiB,UAAU,CAAC;AAChD,OAAO,IAAI,MAA0B,WAAW,CAAC;AAEjD,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;AAErH,SAAS,SAAS;IAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO,QAAQ,IAAI,IAAI,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAO,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAK,cAAc,EAAE,CAAC;IAEpC,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACrE,MAAM,EAAE,UAAU,EAAE,GAAY,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC;IACjE,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,qBAAqB,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,MAAM,GAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,QAAQ;IACrB,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,SAAS,EAAE,EAAE,CAAC;QAChB,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC;SAAM,CAAC;QACN,MAAM,cAAc,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,6 +1,12 @@
1
1
  import { ParserRegistry } from "./registry.js";
2
2
  /**
3
- * 전역 싱글턴 Parser Registry. 서버 시작 한 번 초기화된다.
3
+ * 44개 내장 파서가 등록된 ParserRegistry 인스턴스를 생성한다.
4
+ * 호출할 때마다 새 인스턴스를 반환하므로, 테스트나 CLI에서 독립적으로 사용 가능.
5
+ */
6
+ export declare function createRegistry(): ParserRegistry;
7
+ /**
8
+ * 하위 호환용 전역 싱글턴. 기존 server.ts import를 깨지 않기 위해 유지.
9
+ * @deprecated 신규 코드는 createRegistry()를 사용할 것.
4
10
  */
5
11
  export declare const defaultRegistry: ParserRegistry;
6
12
  //# sourceMappingURL=index.d.ts.map
@@ -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;AAa5F;;GAEG;AACH,eAAO,MAAM,eAAe,gBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAmD,eAAe,CAAC;AAa5F;;;GAGG;AACH,wBAAgB,cAAc,IAAI,cAAc,CAyD/C;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,gBAAmB,CAAC"}
@@ -10,62 +10,71 @@ import { parseDir, parseTasklist, parseIpconfig, parseSysteminfo } from "./windo
10
10
  import { parseKubectl, parseDocker, parseGh, parseHelm, parseTerraform } from "./devops/index.js";
11
11
  import { parseNpm, parseCargo } from "./packages/index.js";
12
12
  /**
13
- * 전역 싱글턴 Parser Registry. 서버 시작 한 번 초기화된다.
13
+ * 44개 내장 파서가 등록된 ParserRegistry 인스턴스를 생성한다.
14
+ * 호출할 때마다 새 인스턴스를 반환하므로, 테스트나 CLI에서 독립적으로 사용 가능.
14
15
  */
15
- export const defaultRegistry = new ParserRegistry();
16
- defaultRegistry.register("ls", parseLs);
17
- defaultRegistry.register("find", parseFind);
18
- defaultRegistry.register("stat", parseStat);
19
- defaultRegistry.register("du", parseDu);
20
- defaultRegistry.register("df", parseDf);
21
- defaultRegistry.register("tree", parseTree);
22
- defaultRegistry.register("ps", parsePs);
23
- defaultRegistry.register("kill", parseKill);
24
- defaultRegistry.register("ping", parsePing);
25
- defaultRegistry.register("curl", parseCurl);
26
- defaultRegistry.register("netstat", parseNetstat);
27
- defaultRegistry.register("lsof", parseLsof);
28
- defaultRegistry.register("ss", parseSs);
29
- defaultRegistry.register("dig", parseDig);
30
- defaultRegistry.register("grep", parseGrep);
31
- defaultRegistry.register("wc", parseWc);
32
- defaultRegistry.register("head", parseHead);
33
- defaultRegistry.register("tail", parseTail);
34
- defaultRegistry.register("cat", parseCat);
35
- defaultRegistry.register("env", parseEnv);
36
- defaultRegistry.register("pwd", parsePwd);
37
- defaultRegistry.register("which", parseWhich);
38
- defaultRegistry.register("free", parseFree);
39
- defaultRegistry.register("uname", parseUname);
40
- defaultRegistry.register("id", parseId);
41
- defaultRegistry.register("systemctl", parseSystemctl);
42
- defaultRegistry.register("journalctl", parseJournalctl);
43
- defaultRegistry.register("dir", parseDir);
44
- defaultRegistry.register("tasklist", parseTasklist);
45
- defaultRegistry.register("ipconfig", parseIpconfig);
46
- defaultRegistry.register("systeminfo", parseSysteminfo);
47
- defaultRegistry.register("kubectl", parseKubectl);
48
- defaultRegistry.register("docker", parseDocker);
49
- defaultRegistry.register("gh", parseGh);
50
- defaultRegistry.register("helm", parseHelm);
51
- defaultRegistry.register("terraform", parseTerraform);
52
- defaultRegistry.register("apt", parseApt);
53
- defaultRegistry.register("brew", parseBrew);
54
- defaultRegistry.register("npm", parseNpm);
55
- defaultRegistry.register("pnpm", parseNpm);
56
- defaultRegistry.register("yarn", parseNpm);
57
- defaultRegistry.register("cargo", parseCargo);
58
- // git은 서브커맨드 기반 — args[0]으로 파서를 선택
59
- defaultRegistry.register("git", (cmd, args, raw) => {
60
- const sub = args[0];
61
- if (sub === "status")
62
- return parseGitStatus(cmd, args, raw);
63
- if (sub === "log")
64
- return parseGitLog(cmd, args, raw);
65
- if (sub === "diff")
66
- return parseGitDiff(cmd, args, raw);
67
- if (sub === "branch")
68
- return parseGitBranch(cmd, args, raw);
69
- return null;
70
- });
16
+ export function createRegistry() {
17
+ const registry = new ParserRegistry();
18
+ registry.register("ls", parseLs);
19
+ registry.register("find", parseFind);
20
+ registry.register("stat", parseStat);
21
+ registry.register("du", parseDu);
22
+ registry.register("df", parseDf);
23
+ registry.register("tree", parseTree);
24
+ registry.register("ps", parsePs);
25
+ registry.register("kill", parseKill);
26
+ registry.register("ping", parsePing);
27
+ registry.register("curl", parseCurl);
28
+ registry.register("netstat", parseNetstat);
29
+ registry.register("lsof", parseLsof);
30
+ registry.register("ss", parseSs);
31
+ registry.register("dig", parseDig);
32
+ registry.register("grep", parseGrep);
33
+ registry.register("wc", parseWc);
34
+ registry.register("head", parseHead);
35
+ registry.register("tail", parseTail);
36
+ registry.register("cat", parseCat);
37
+ registry.register("env", parseEnv);
38
+ registry.register("pwd", parsePwd);
39
+ registry.register("which", parseWhich);
40
+ registry.register("free", parseFree);
41
+ registry.register("uname", parseUname);
42
+ registry.register("id", parseId);
43
+ registry.register("systemctl", parseSystemctl);
44
+ registry.register("journalctl", parseJournalctl);
45
+ registry.register("dir", parseDir);
46
+ registry.register("tasklist", parseTasklist);
47
+ registry.register("ipconfig", parseIpconfig);
48
+ registry.register("systeminfo", parseSysteminfo);
49
+ registry.register("kubectl", parseKubectl);
50
+ registry.register("docker", parseDocker);
51
+ registry.register("gh", parseGh);
52
+ registry.register("helm", parseHelm);
53
+ registry.register("terraform", parseTerraform);
54
+ registry.register("apt", parseApt);
55
+ registry.register("brew", parseBrew);
56
+ registry.register("npm", parseNpm);
57
+ registry.register("pnpm", parseNpm);
58
+ registry.register("yarn", parseNpm);
59
+ registry.register("cargo", parseCargo);
60
+ // git 서브커맨드 기반 — args[0]으로 파서를 선택
61
+ registry.register("git", (cmd, args, raw) => {
62
+ const sub = args[0];
63
+ if (sub === "status")
64
+ return parseGitStatus(cmd, args, raw);
65
+ if (sub === "log")
66
+ return parseGitLog(cmd, args, raw);
67
+ if (sub === "diff")
68
+ return parseGitDiff(cmd, args, raw);
69
+ if (sub === "branch")
70
+ return parseGitBranch(cmd, args, raw);
71
+ return null;
72
+ });
73
+ return registry;
74
+ }
75
+ /**
76
+ * 하위 호환용 전역 싱글턴. 기존 server.ts import를 깨지 않기 위해 유지.
77
+ * @deprecated 신규 코드는 createRegistry()를 사용할 것.
78
+ */
79
+ export const defaultRegistry = createRegistry();
71
80
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,32 @@ export interface ParseContext {
17
17
  * 파서 함수 시그니처.
18
18
  */
19
19
  export type ParserFn = (cmd: string, args: string[], raw: string, ctx?: ParseContext) => unknown;
20
+ /**
21
+ * Fixture: 파서 검증용 입출력 쌍.
22
+ */
23
+ export interface Fixture {
24
+ input: string;
25
+ args: string[];
26
+ expected: unknown;
27
+ }
28
+ /**
29
+ * 파서 팩: 명령어 파서의 완전한 정의.
30
+ * name -- 대상 명령어 (예: "htop")
31
+ * parse -- raw stdout + args -> 구조화된 결과 (null이면 파싱 불가)
32
+ * schema -- 출력 JSON 스키마 (검증/문서 용도)
33
+ * fixtures -- 입출력 쌍 (테스트/검증 용도)
34
+ * meta -- 선택적 메타 정보
35
+ */
36
+ export interface ParserPack {
37
+ name: string;
38
+ parse: (raw: string, args: string[], ctx?: ParseContext) => unknown;
39
+ schema: Record<string, unknown>;
40
+ fixtures: Fixture[];
41
+ meta?: {
42
+ os?: string[];
43
+ version?: string;
44
+ };
45
+ }
20
46
  /**
21
47
  * 파서 실행 결과. parsed가 null일 때 parse_error가 있으면 파서 예외, 없으면 파서 없음.
22
48
  */
@@ -33,7 +59,20 @@ export interface ParseResult {
33
59
  */
34
60
  export declare class ParserRegistry {
35
61
  private readonly parsers;
62
+ private readonly packs;
36
63
  register(cmd: string, fn: ParserFn): void;
64
+ /**
65
+ * ParserPack을 등록한다. parsers Map에도 어댑터를 등록하여 기존 parse() 경로와 호환.
66
+ */
67
+ registerPack(pack: ParserPack): void;
68
+ /**
69
+ * 등록된 ParserPack을 이름으로 조회한다.
70
+ */
71
+ getPack(name: string): ParserPack | undefined;
72
+ /**
73
+ * 등록된 모든 ParserPack 이름 목록을 반환한다.
74
+ */
75
+ listPacks(): string[];
37
76
  /**
38
77
  * cmd에 등록된 파서를 찾아 실행한다.
39
78
  * 파서 없음 → { parsed: null }. 파서 예외 → { parsed: null, parse_error }.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAE9D;;;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;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAO,OAAO,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D;AAED;;;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,WAAW;CAYjF"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAE9D;;;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;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAK,MAAM,CAAC;IACjB,IAAI,EAAM,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAO,MAAM,CAAC;IAClB,KAAK,EAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC;IACxE,MAAM,EAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,EAAG,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAM;QAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAO,OAAO,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEzD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,GAAG,IAAI;IAIzC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAKpC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI7C;;OAEG;IACH,SAAS,IAAI,MAAM,EAAE;IAIrB;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,WAAW;CAYjF"}
@@ -4,9 +4,29 @@
4
4
  */
5
5
  export class ParserRegistry {
6
6
  parsers = new Map();
7
+ packs = new Map();
7
8
  register(cmd, fn) {
8
9
  this.parsers.set(cmd, fn);
9
10
  }
11
+ /**
12
+ * ParserPack을 등록한다. parsers Map에도 어댑터를 등록하여 기존 parse() 경로와 호환.
13
+ */
14
+ registerPack(pack) {
15
+ this.packs.set(pack.name, pack);
16
+ this.parsers.set(pack.name, (_cmd, args, raw, ctx) => pack.parse(raw, args, ctx));
17
+ }
18
+ /**
19
+ * 등록된 ParserPack을 이름으로 조회한다.
20
+ */
21
+ getPack(name) {
22
+ return this.packs.get(name);
23
+ }
24
+ /**
25
+ * 등록된 모든 ParserPack 이름 목록을 반환한다.
26
+ */
27
+ listPacks() {
28
+ return [...this.packs.keys()];
29
+ }
10
30
  /**
11
31
  * cmd에 등록된 파서를 찾아 실행한다.
12
32
  * 파서 없음 → { parsed: null }. 파서 예외 → { parsed: null, parse_error }.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AA8BA;;;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,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAAC;QAChF,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/parsers/registry.ts"],"names":[],"mappings":"AAuDA;;;GAGG;AACH,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IACtC,KAAK,GAAK,IAAI,GAAG,EAAsB,CAAC;IAEzD,QAAQ,CAAC,GAAW,EAAE,EAAY;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAgB;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACpF,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,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,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAAC;QAChF,CAAC;IACH,CAAC;CACF"}
package/dist/server.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import type { PrismConfig } from "./config/loader.js";
3
+ import type { ParserRegistry } from "./parsers/registry.js";
3
4
  import type { OutputFormat } from "./parsers/registry.js";
4
- export declare const PACKAGE_VERSION = "0.4.0";
5
+ export declare const PACKAGE_VERSION = "0.5.0";
5
6
  /**
6
7
  * Guard 검사 → 실행 → JSON 직렬화까지의 파이프라인.
7
8
  * MCP 서버와 테스트 코드가 공통으로 사용한다.
8
9
  */
9
- export declare function buildRunResult(cmd: string, args: string[], cwd: string, config: PrismConfig, format?: OutputFormat, includeDiff?: boolean): Promise<string>;
10
+ export declare function buildRunResult(cmd: string, args: string[], cwd: string, config: PrismConfig, registry: ParserRegistry, format?: OutputFormat, includeDiff?: boolean): Promise<string>;
10
11
  /**
11
12
  * Guard 검사 → 실행 → 페이지 분할 → JSON 직렬화.
12
13
  * parsed는 항상 null (부분 출력은 구조화 파싱 불가).
@@ -15,5 +16,5 @@ export declare function buildPagedResult(cmd: string, args: string[], cwd: strin
15
16
  /**
16
17
  * MCP 서버를 생성하고 `run` 도구를 등록한다.
17
18
  */
18
- export declare function createServer(config: PrismConfig): McpServer;
19
+ export declare function createServer(config: PrismConfig, registry: ParserRegistry): McpServer;
19
20
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,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,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EAAE,EACrB,GAAG,EAAU,MAAM,EACnB,MAAM,EAAO,WAAW,EACxB,MAAM,GAAO,YAAqB,EAClC,WAAW,GAAE,OAAkB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EAAE,EACrB,GAAG,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EACnB,QAAQ,EAAK,MAAM,EACnB,MAAM,EAAO,WAAW,EACxB,WAAW,GAAE,OAAc,GAC1B,OAAO,CAAC,MAAM,CAAC,CAwBjB;AA2BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAkD3D"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAY,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAQ,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAW,uBAAuB,CAAC;AAI/D,eAAO,MAAM,eAAe,UAAU,CAAC;AAsBvC;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EAAE,EACrB,GAAG,EAAU,MAAM,EACnB,MAAM,EAAO,WAAW,EACxB,QAAQ,EAAK,cAAc,EAC3B,MAAM,GAAO,YAAqB,EAClC,WAAW,GAAE,OAAkB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EAAE,EACrB,GAAG,EAAU,MAAM,EACnB,IAAI,EAAS,MAAM,EACnB,QAAQ,EAAK,MAAM,EACnB,MAAM,EAAO,WAAW,EACxB,WAAW,GAAE,OAAc,GAC1B,OAAO,CAAC,MAAM,CAAC,CAwBjB;AA2BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAkDrF"}
package/dist/server.js CHANGED
@@ -2,11 +2,10 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { z } from "zod";
3
3
  import { execute } from "./engine/executor.js";
4
4
  import { checkGuard, GuardError } from "./engine/guard.js";
5
- import { defaultRegistry } from "./parsers/index.js";
6
5
  import { paginateLines } from "./engine/paginator.js";
7
6
  import { toCompact } from "./parsers/compact.js";
8
7
  import { tryParseNativeJson } from "./parsers/json-passthrough.js";
9
- export const PACKAGE_VERSION = "0.4.0";
8
+ export const PACKAGE_VERSION = "0.5.0";
10
9
  /**
11
10
  * Guard 차단 시 반환하는 에러 봉투를 생성한다.
12
11
  */
@@ -28,7 +27,7 @@ function buildGuardErrorEnvelope(cmd, args, cwd, err) {
28
27
  * Guard 검사 → 실행 → JSON 직렬화까지의 파이프라인.
29
28
  * MCP 서버와 테스트 코드가 공통으로 사용한다.
30
29
  */
31
- export async function buildRunResult(cmd, args, cwd, config, format = "json", includeDiff = true) {
30
+ export async function buildRunResult(cmd, args, cwd, config, registry, format = "json", includeDiff = true) {
32
31
  try {
33
32
  checkGuard(cmd, args, cwd, config);
34
33
  }
@@ -39,7 +38,7 @@ export async function buildRunResult(cmd, args, cwd, config, format = "json", in
39
38
  }
40
39
  const envelope = await execute(cmd, args, cwd, config.guard.env_secret_patterns, config.guard.timeout_ms, config.guard.max_output_bytes, includeDiff);
41
40
  const parseFormat = format === "json-no-raw" ? "json" : format;
42
- const parseResult = defaultRegistry.parse(cmd, args, envelope.stdout.raw, { maxItems: config.guard.max_items, format: parseFormat });
41
+ const parseResult = registry.parse(cmd, args, envelope.stdout.raw, { maxItems: config.guard.max_items, format: parseFormat });
43
42
  let parsed = parseResult.parsed;
44
43
  if (parsed == null)
45
44
  parsed = tryParseNativeJson(envelope.stdout.raw);
@@ -101,7 +100,7 @@ Usage:
101
100
  /**
102
101
  * MCP 서버를 생성하고 `run` 도구를 등록한다.
103
102
  */
104
- export function createServer(config) {
103
+ export function createServer(config, registry) {
105
104
  const server = new McpServer({ name: "parism", version: PACKAGE_VERSION }, { instructions: MCP_INSTRUCTIONS });
106
105
  server.tool("run", "Execute a shell command and receive structured output. " +
107
106
  "All commands are filtered through an execution guard (whitelist + injection prevention). " +
@@ -114,7 +113,7 @@ export function createServer(config) {
114
113
  includeDiff: z.boolean().default(false)
115
114
  .describe("Include filesystem diff (created/deleted/modified). false=skip snapshot, lower latency."),
116
115
  }, async ({ cmd, args, cwd, format, includeDiff }) => {
117
- const result = await buildRunResult(cmd, args, cwd, config, format, includeDiff);
116
+ const result = await buildRunResult(cmd, args, cwd, config, registry, format, includeDiff);
118
117
  return {
119
118
  content: [{ type: "text", text: result }],
120
119
  };
@@ -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,9 +1,13 @@
1
1
  {
2
2
  "name": "@nerdvana/parism",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Structured shell output wrapper for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "exports": {
8
+ ".": "./dist/index.js",
9
+ "./types": "./dist/parsers/registry.js"
10
+ },
7
11
  "bin": {
8
12
  "parism": "dist/index.js"
9
13
  },
@@ -19,6 +23,7 @@
19
23
  },
20
24
  "dependencies": {
21
25
  "@modelcontextprotocol/sdk": "^1.10.0",
26
+ "commander": "^14.0.3",
22
27
  "zod": "^3.24.0"
23
28
  },
24
29
  "devDependencies": {