@tienne/gestalt 0.6.0 → 0.8.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 (129) hide show
  1. package/CLAUDE.md +13 -2
  2. package/README.ko.md +136 -3
  3. package/README.md +163 -11
  4. package/dist/package.json +2 -1
  5. package/dist/src/cli/commands/interview.d.ts +1 -0
  6. package/dist/src/cli/commands/interview.d.ts.map +1 -1
  7. package/dist/src/cli/commands/interview.js +12 -53
  8. package/dist/src/cli/commands/interview.js.map +1 -1
  9. package/dist/src/cli/index.d.ts.map +1 -1
  10. package/dist/src/cli/index.js +2 -1
  11. package/dist/src/cli/index.js.map +1 -1
  12. package/dist/src/core/types.d.ts +85 -0
  13. package/dist/src/core/types.d.ts.map +1 -1
  14. package/dist/src/execute/audit-engine.d.ts +20 -0
  15. package/dist/src/execute/audit-engine.d.ts.map +1 -0
  16. package/dist/src/execute/audit-engine.js +49 -0
  17. package/dist/src/execute/audit-engine.js.map +1 -0
  18. package/dist/src/execute/parallel-groups.d.ts +9 -0
  19. package/dist/src/execute/parallel-groups.d.ts.map +1 -0
  20. package/dist/src/execute/parallel-groups.js +39 -0
  21. package/dist/src/execute/parallel-groups.js.map +1 -0
  22. package/dist/src/execute/passthrough-engine.d.ts +2 -0
  23. package/dist/src/execute/passthrough-engine.d.ts.map +1 -1
  24. package/dist/src/execute/passthrough-engine.js +6 -0
  25. package/dist/src/execute/passthrough-engine.js.map +1 -1
  26. package/dist/src/execute/repository.d.ts.map +1 -1
  27. package/dist/src/execute/repository.js +3 -0
  28. package/dist/src/execute/repository.js.map +1 -1
  29. package/dist/src/execute/session.d.ts +3 -1
  30. package/dist/src/execute/session.d.ts.map +1 -1
  31. package/dist/src/execute/session.js +31 -0
  32. package/dist/src/execute/session.js.map +1 -1
  33. package/dist/src/interview/context-compressor.d.ts +17 -0
  34. package/dist/src/interview/context-compressor.d.ts.map +1 -0
  35. package/dist/src/interview/context-compressor.js +40 -0
  36. package/dist/src/interview/context-compressor.js.map +1 -0
  37. package/dist/src/interview/mini-interview-engine.d.ts +33 -0
  38. package/dist/src/interview/mini-interview-engine.d.ts.map +1 -0
  39. package/dist/src/interview/mini-interview-engine.js +103 -0
  40. package/dist/src/interview/mini-interview-engine.js.map +1 -0
  41. package/dist/src/interview/passthrough-engine.d.ts +7 -0
  42. package/dist/src/interview/passthrough-engine.d.ts.map +1 -1
  43. package/dist/src/interview/passthrough-engine.js +15 -1
  44. package/dist/src/interview/passthrough-engine.js.map +1 -1
  45. package/dist/src/interview/session.d.ts +2 -1
  46. package/dist/src/interview/session.d.ts.map +1 -1
  47. package/dist/src/interview/session.js +5 -0
  48. package/dist/src/interview/session.js.map +1 -1
  49. package/dist/src/mcp/schemas.d.ts +78 -9
  50. package/dist/src/mcp/schemas.d.ts.map +1 -1
  51. package/dist/src/mcp/schemas.js +26 -2
  52. package/dist/src/mcp/schemas.js.map +1 -1
  53. package/dist/src/mcp/server.d.ts.map +1 -1
  54. package/dist/src/mcp/server.js +5 -2
  55. package/dist/src/mcp/server.js.map +1 -1
  56. package/dist/src/mcp/tools/execute-passthrough.d.ts.map +1 -1
  57. package/dist/src/mcp/tools/execute-passthrough.js +174 -1
  58. package/dist/src/mcp/tools/execute-passthrough.js.map +1 -1
  59. package/dist/src/mcp/tools/interview-passthrough.d.ts.map +1 -1
  60. package/dist/src/mcp/tools/interview-passthrough.js +71 -3
  61. package/dist/src/mcp/tools/interview-passthrough.js.map +1 -1
  62. package/dist/src/mcp/tools/interview.d.ts.map +1 -1
  63. package/dist/src/mcp/tools/interview.js +34 -1
  64. package/dist/src/mcp/tools/interview.js.map +1 -1
  65. package/dist/src/mcp/tools/spec-passthrough.d.ts +2 -1
  66. package/dist/src/mcp/tools/spec-passthrough.d.ts.map +1 -1
  67. package/dist/src/mcp/tools/spec-passthrough.js +54 -3
  68. package/dist/src/mcp/tools/spec-passthrough.js.map +1 -1
  69. package/dist/src/mcp/tools/spec.d.ts.map +1 -1
  70. package/dist/src/mcp/tools/spec.js +2 -0
  71. package/dist/src/mcp/tools/spec.js.map +1 -1
  72. package/dist/src/memory/memory-context-injector.d.ts +26 -0
  73. package/dist/src/memory/memory-context-injector.d.ts.map +1 -0
  74. package/dist/src/memory/memory-context-injector.js +67 -0
  75. package/dist/src/memory/memory-context-injector.js.map +1 -0
  76. package/dist/src/memory/project-memory-store.d.ts +14 -0
  77. package/dist/src/memory/project-memory-store.d.ts.map +1 -0
  78. package/dist/src/memory/project-memory-store.js +105 -0
  79. package/dist/src/memory/project-memory-store.js.map +1 -0
  80. package/dist/src/memory/user-profile-store.d.ts +13 -0
  81. package/dist/src/memory/user-profile-store.d.ts.map +1 -0
  82. package/dist/src/memory/user-profile-store.js +89 -0
  83. package/dist/src/memory/user-profile-store.js.map +1 -0
  84. package/dist/src/recording/agg-converter.d.ts +25 -0
  85. package/dist/src/recording/agg-converter.d.ts.map +1 -0
  86. package/dist/src/recording/agg-converter.js +80 -0
  87. package/dist/src/recording/agg-converter.js.map +1 -0
  88. package/dist/src/recording/agg-installer.d.ts +6 -0
  89. package/dist/src/recording/agg-installer.d.ts.map +1 -0
  90. package/dist/src/recording/agg-installer.js +50 -0
  91. package/dist/src/recording/agg-installer.js.map +1 -0
  92. package/dist/src/recording/asciinema-installer.d.ts +6 -0
  93. package/dist/src/recording/asciinema-installer.d.ts.map +1 -0
  94. package/dist/src/recording/asciinema-installer.js +50 -0
  95. package/dist/src/recording/asciinema-installer.js.map +1 -0
  96. package/dist/src/recording/asciinema-recorder.d.ts +26 -0
  97. package/dist/src/recording/asciinema-recorder.d.ts.map +1 -0
  98. package/dist/src/recording/asciinema-recorder.js +52 -0
  99. package/dist/src/recording/asciinema-recorder.js.map +1 -0
  100. package/dist/src/recording/cast-generator.d.ts +7 -0
  101. package/dist/src/recording/cast-generator.d.ts.map +1 -0
  102. package/dist/src/recording/cast-generator.js +72 -0
  103. package/dist/src/recording/cast-generator.js.map +1 -0
  104. package/dist/src/recording/filename-generator.d.ts +1 -0
  105. package/dist/src/recording/filename-generator.d.ts.map +1 -1
  106. package/dist/src/recording/filename-generator.js +7 -0
  107. package/dist/src/recording/filename-generator.js.map +1 -1
  108. package/dist/src/recording/recording-orchestrator.d.ts +50 -0
  109. package/dist/src/recording/recording-orchestrator.d.ts.map +1 -0
  110. package/dist/src/recording/recording-orchestrator.js +98 -0
  111. package/dist/src/recording/recording-orchestrator.js.map +1 -0
  112. package/dist/src/scripts/postinstall.d.ts +2 -0
  113. package/dist/src/scripts/postinstall.d.ts.map +1 -0
  114. package/dist/src/scripts/postinstall.js +27 -0
  115. package/dist/src/scripts/postinstall.js.map +1 -0
  116. package/dist/src/spec/passthrough-generator.d.ts +2 -0
  117. package/dist/src/spec/passthrough-generator.d.ts.map +1 -1
  118. package/dist/src/spec/passthrough-generator.js +34 -0
  119. package/dist/src/spec/passthrough-generator.js.map +1 -1
  120. package/dist/src/spec/templates.d.ts +12 -0
  121. package/dist/src/spec/templates.d.ts.map +1 -0
  122. package/dist/src/spec/templates.js +103 -0
  123. package/dist/src/spec/templates.js.map +1 -0
  124. package/dist/src/spec/text-based-spec-generator.d.ts +15 -0
  125. package/dist/src/spec/text-based-spec-generator.d.ts.map +1 -0
  126. package/dist/src/spec/text-based-spec-generator.js +63 -0
  127. package/dist/src/spec/text-based-spec-generator.js.map +1 -0
  128. package/package.json +2 -1
  129. package/README.backup.md +0 -442
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agg-installer.js","sourceRoot":"","sources":["../../../src/recording/agg-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,OAAO,YAAY;IACvB,WAAW;QACT,IAAI,CAAC;YACH,QAAQ,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO;QAE/B,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAEtD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAC5E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAC;YAChH,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAC3F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,0FAA0F,CAC3F,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,mGAAmG,CACpG,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;QAC3G,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACjD,CAAC;IAEO,UAAU,CAAC,GAAW;QAC5B,IAAI,CAAC;YACH,QAAQ,CAAC,SAAS,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export declare class AsciinemaInstaller {
2
+ isInstalled(): boolean;
3
+ ensureInstalled(): Promise<void>;
4
+ private ensureBrewAvailable;
5
+ }
6
+ //# sourceMappingURL=asciinema-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asciinema-installer.d.ts","sourceRoot":"","sources":["../../../src/recording/asciinema-installer.ts"],"names":[],"mappings":"AAGA,qBAAa,kBAAkB;IAC7B,WAAW,IAAI,OAAO;IAShB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCtC,OAAO,CAAC,mBAAmB;CAS5B"}
@@ -0,0 +1,50 @@
1
+ import { execSync, spawnSync } from 'node:child_process';
2
+ import { platform } from 'node:os';
3
+ export class AsciinemaInstaller {
4
+ isInstalled() {
5
+ try {
6
+ execSync('which asciinema', { stdio: 'pipe' });
7
+ return true;
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ async ensureInstalled() {
14
+ if (this.isInstalled())
15
+ return;
16
+ const os = platform();
17
+ console.log('📦 asciinema is not installed. Installing...');
18
+ if (os === 'darwin') {
19
+ this.ensureBrewAvailable();
20
+ console.log(' → brew install asciinema');
21
+ const result = spawnSync('brew', ['install', 'asciinema'], { stdio: 'inherit' });
22
+ if (result.status !== 0) {
23
+ throw new Error('Failed to install asciinema via brew. Please install manually: brew install asciinema');
24
+ }
25
+ }
26
+ else if (os === 'linux') {
27
+ console.log(' → pip3 install asciinema');
28
+ const result = spawnSync('pip3', ['install', 'asciinema'], { stdio: 'inherit' });
29
+ if (result.status !== 0) {
30
+ throw new Error('Failed to install asciinema via pip3. Please install manually: pip3 install asciinema');
31
+ }
32
+ }
33
+ else {
34
+ throw new Error(`Unsupported platform for automatic asciinema installation: ${os}. Please install asciinema manually: https://docs.asciinema.org/manual/cli/installation/`);
35
+ }
36
+ if (!this.isInstalled()) {
37
+ throw new Error('asciinema installation failed. Please install it manually: https://docs.asciinema.org/manual/cli/installation/');
38
+ }
39
+ console.log('✅ asciinema installed successfully.\n');
40
+ }
41
+ ensureBrewAvailable() {
42
+ try {
43
+ execSync('which brew', { stdio: 'pipe' });
44
+ }
45
+ catch {
46
+ throw new Error('Homebrew is not installed. Please install it first: https://brew.sh, then run: brew install asciinema');
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=asciinema-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asciinema-installer.js","sourceRoot":"","sources":["../../../src/recording/asciinema-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,OAAO,kBAAkB;IAC7B,WAAW;QACT,IAAI,CAAC;YACH,QAAQ,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO;QAE/B,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAE5D,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACjF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;YAC3G,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACjF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;YAC3G,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,8DAA8D,EAAE,0FAA0F,CAC3J,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,gHAAgH,CACjH,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC;YACH,QAAQ,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AsciinemaRecorder: self-respawn 패턴으로 asciinema 녹화를 구현한다.
3
+ *
4
+ * --record 플래그가 있고 GESTALT_RECORDING 환경변수가 없으면,
5
+ * 현재 프로세스를 asciinema rec으로 감싸서 재실행한다.
6
+ * 재실행된 프로세스는 GESTALT_RECORDING=1로 실행되므로 일반 인터뷰 로직을 수행한다.
7
+ */
8
+ export declare class AsciinemaRecorder {
9
+ /** 이미 asciinema로 감싸진 상태인지 확인 */
10
+ static isInsideRecording(): boolean;
11
+ /** 현재 녹화 중인 cast 파일 경로 (GESTALT_CAST_PATH 환경변수) */
12
+ static getCurrentCastPath(): string | undefined;
13
+ /**
14
+ * 임시 cast 파일 경로를 생성한다.
15
+ * 실제 파일명은 인터뷰 완료 후 topic 기반으로 rename된다.
16
+ */
17
+ static createTempCastPath(recordingsDir?: string): string;
18
+ /**
19
+ * asciinema rec으로 현재 프로세스를 재실행한다.
20
+ * 이 함수는 return하지 않는다 (spawnSync가 블로킹).
21
+ *
22
+ * @param castPath - 녹화 결과를 저장할 .cast 파일 경로
23
+ */
24
+ static respawnWithAsciinema(castPath: string): void;
25
+ }
26
+ //# sourceMappingURL=asciinema-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asciinema-recorder.d.ts","sourceRoot":"","sources":["../../../src/recording/asciinema-recorder.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,gCAAgC;IAChC,MAAM,CAAC,iBAAiB,IAAI,OAAO;IAInC,mDAAmD;IACnD,MAAM,CAAC,kBAAkB,IAAI,MAAM,GAAG,SAAS;IAI/C;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,aAAa,SAAwB,GAAG,MAAM;IAKxE;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAmBpD"}
@@ -0,0 +1,52 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { mkdirSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ /**
6
+ * AsciinemaRecorder: self-respawn 패턴으로 asciinema 녹화를 구현한다.
7
+ *
8
+ * --record 플래그가 있고 GESTALT_RECORDING 환경변수가 없으면,
9
+ * 현재 프로세스를 asciinema rec으로 감싸서 재실행한다.
10
+ * 재실행된 프로세스는 GESTALT_RECORDING=1로 실행되므로 일반 인터뷰 로직을 수행한다.
11
+ */
12
+ export class AsciinemaRecorder {
13
+ /** 이미 asciinema로 감싸진 상태인지 확인 */
14
+ static isInsideRecording() {
15
+ return process.env['GESTALT_RECORDING'] === '1';
16
+ }
17
+ /** 현재 녹화 중인 cast 파일 경로 (GESTALT_CAST_PATH 환경변수) */
18
+ static getCurrentCastPath() {
19
+ return process.env['GESTALT_CAST_PATH'];
20
+ }
21
+ /**
22
+ * 임시 cast 파일 경로를 생성한다.
23
+ * 실제 파일명은 인터뷰 완료 후 topic 기반으로 rename된다.
24
+ */
25
+ static createTempCastPath(recordingsDir = '.gestalt/recordings') {
26
+ mkdirSync(recordingsDir, { recursive: true });
27
+ return `${recordingsDir}/tmp-${randomUUID()}.cast`;
28
+ }
29
+ /**
30
+ * asciinema rec으로 현재 프로세스를 재실행한다.
31
+ * 이 함수는 return하지 않는다 (spawnSync가 블로킹).
32
+ *
33
+ * @param castPath - 녹화 결과를 저장할 .cast 파일 경로
34
+ */
35
+ static respawnWithAsciinema(castPath) {
36
+ // 현재 process.argv에서 node 실행파일을 제외한 스크립트 + 인자
37
+ const [, ...scriptAndArgs] = process.argv;
38
+ // --record, -r 플래그 제거 (재실행 시 무한루프 방지)
39
+ const filteredArgs = (scriptAndArgs ?? []).filter((a) => a !== '--record' && a !== '-r');
40
+ mkdirSync(dirname(castPath), { recursive: true });
41
+ const result = spawnSync('asciinema', ['rec', '--overwrite', castPath, '--', 'node', ...filteredArgs], {
42
+ stdio: 'inherit',
43
+ env: {
44
+ ...process.env,
45
+ GESTALT_RECORDING: '1',
46
+ GESTALT_CAST_PATH: castPath,
47
+ },
48
+ });
49
+ process.exit(result.status ?? 0);
50
+ }
51
+ }
52
+ //# sourceMappingURL=asciinema-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asciinema-recorder.js","sourceRoot":"","sources":["../../../src/recording/asciinema-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IAC5B,gCAAgC;IAChC,MAAM,CAAC,iBAAiB;QACtB,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,GAAG,CAAC;IAClD,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,kBAAkB;QACvB,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,aAAa,GAAG,qBAAqB;QAC7D,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,aAAa,QAAQ,UAAU,EAAE,OAAO,CAAC;IACrD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAgB;QAC1C,6CAA6C;QAC7C,MAAM,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1C,sCAAsC;QACtC,MAAM,YAAY,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAEzF,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAElD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,EAAE;YACrG,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,iBAAiB,EAAE,GAAG;gBACtB,iBAAiB,EAAE,QAAQ;aAC5B;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { InterviewSession } from '../core/types.js';
2
+ export declare function slugify(topic: string): string;
3
+ export declare function getDateString(date?: Date): string;
4
+ export declare class CastGenerator {
5
+ generate(session: InterviewSession, outputPath: string): void;
6
+ }
7
+ //# sourceMappingURL=cast-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cast-generator.d.ts","sourceRoot":"","sources":["../../../src/recording/cast-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAYzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED,wBAAgB,aAAa,CAAC,IAAI,OAAa,GAAG,MAAM,CAEvD;AAED,qBAAa,aAAa;IACxB,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAyD9D"}
@@ -0,0 +1,72 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ // ANSI color codes
4
+ const RESET = '\x1b[0m';
5
+ const BOLD = '\x1b[1m';
6
+ const CYAN = '\x1b[36m';
7
+ const YELLOW = '\x1b[33m';
8
+ const GREEN = '\x1b[32m';
9
+ const DIM = '\x1b[2m';
10
+ export function slugify(topic) {
11
+ return topic
12
+ .toLowerCase()
13
+ .replace(/[^a-z0-9]+/g, '-')
14
+ .replace(/^-+|-+$/g, '')
15
+ .slice(0, 50) || 'interview';
16
+ }
17
+ export function getDateString(date = new Date()) {
18
+ return date.toISOString().slice(0, 10).replace(/-/g, '');
19
+ }
20
+ export class CastGenerator {
21
+ generate(session, outputPath) {
22
+ const startTs = Math.floor(Date.parse(session.createdAt) / 1000);
23
+ const header = {
24
+ version: 2,
25
+ width: 100,
26
+ height: 40,
27
+ timestamp: startTs,
28
+ title: `Gestalt Interview: ${session.topic}`,
29
+ };
30
+ const events = [];
31
+ let t = 0;
32
+ // Banner
33
+ events.push([t, 'o', `\r\n${BOLD}${CYAN}╔══════════════════════════════════════════════╗${RESET}\r\n`]);
34
+ t += 0.05;
35
+ events.push([t, 'o', `${BOLD}${CYAN}║ 🎯 Gestalt Interview ║${RESET}\r\n`]);
36
+ t += 0.05;
37
+ events.push([t, 'o', `${BOLD}${CYAN}║ ${DIM}${session.topic.slice(0, 44).padEnd(44)}${RESET}${BOLD}${CYAN} ║${RESET}\r\n`]);
38
+ t += 0.05;
39
+ events.push([t, 'o', `${BOLD}${CYAN}╚══════════════════════════════════════════════╝${RESET}\r\n\r\n`]);
40
+ t += 0.5;
41
+ // Q&A rounds
42
+ for (const round of session.rounds) {
43
+ if (!round.userResponse)
44
+ continue;
45
+ // Question
46
+ events.push([t, 'o', `${BOLD}${YELLOW}Q${round.roundNumber} [${round.gestaltFocus}]${RESET}\r\n`]);
47
+ t += 0.1;
48
+ events.push([t, 'o', `${round.question}\r\n\r\n`]);
49
+ t += 1.2;
50
+ // Answer
51
+ events.push([t, 'o', `${BOLD}${GREEN}❯${RESET} `]);
52
+ t += 0.1;
53
+ events.push([t, 'o', `${round.userResponse}\r\n\r\n`]);
54
+ t += 0.8;
55
+ }
56
+ // Footer
57
+ events.push([t, 'o', `${BOLD}${CYAN}✅ Interview completed — ${session.rounds.length} rounds${RESET}\r\n`]);
58
+ t += 0.3;
59
+ if (session.ambiguityScore) {
60
+ events.push([t, 'o', `${DIM}Ambiguity score: ${session.ambiguityScore.overall.toFixed(2)}${RESET}\r\n`]);
61
+ }
62
+ events.push([t + 0.2, 'o', '\r\n']);
63
+ // Write file
64
+ mkdirSync(dirname(outputPath), { recursive: true });
65
+ const lines = [
66
+ JSON.stringify(header),
67
+ ...events.map((e) => JSON.stringify(e)),
68
+ ];
69
+ writeFileSync(outputPath, lines.join('\n') + '\n', 'utf8');
70
+ }
71
+ }
72
+ //# sourceMappingURL=cast-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cast-generator.js","sourceRoot":"","sources":["../../../src/recording/cast-generator.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ export declare class FilenameGenerator {
11
11
  * YYYYMMDD 날짜 접미사를 붙여 GIF 파일명을 생성한다.
12
12
  */
13
13
  generate(topic: string, sessionId: string): Promise<string>;
14
+ generateCast(topic: string, sessionId: string, outputDir?: string): Promise<string>;
14
15
  private requestSlugFromLLM;
15
16
  private fallbackSlug;
16
17
  private getDateString;
@@ -1 +1 @@
1
- {"version":3,"file":"filename-generator.d.ts","sourceRoot":"","sources":["../../../src/recording/filename-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,wBAA6B;IAGzD;;;OAGG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAQnD,kBAAkB;IA2BhC,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,aAAa;CAOtB"}
1
+ {"version":3,"file":"filename-generator.d.ts","sourceRoot":"","sources":["../../../src/recording/filename-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,GAAG,EAAE,UAAU,EACf,OAAO,GAAE,wBAA6B;IAGzD;;;OAGG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ3D,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAQ3E,kBAAkB;IA2BhC,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,aAAa;CAOtB"}
@@ -16,6 +16,13 @@ export class FilenameGenerator {
16
16
  const dir = this.options.outputDir ?? '.';
17
17
  return dir === '.' ? filename : `${dir}/${filename}`;
18
18
  }
19
+ async generateCast(topic, sessionId, outputDir) {
20
+ const slug = await this.requestSlugFromLLM(topic, sessionId);
21
+ const date = this.getDateString();
22
+ const filename = `${slug}-${date}.cast`;
23
+ const dir = outputDir ?? this.options.outputDir ?? '.gestalt/recordings';
24
+ return `${dir}/${filename}`;
25
+ }
19
26
  async requestSlugFromLLM(topic, sessionId) {
20
27
  try {
21
28
  const response = await this.llm.chat({
@@ -1 +1 @@
1
- {"version":3,"file":"filename-generator.js","sourceRoot":"","sources":["../../../src/recording/filename-generator.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,iBAAiB;IAET;IACA;IAFnB,YACmB,GAAe,EACf,UAAoC,EAAE;QADtC,QAAG,GAAH,GAAG,CAAY;QACf,YAAO,GAAP,OAAO,CAA+B;IACtD,CAAC;IAEJ;;;OAGG;IACH,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,SAAiB;QAC7C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,MAAM,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;QAC1C,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;IACvD,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,KAAa,EAAE,SAAiB;QAC/D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBACnC,MAAM,EAAE,uJAAuJ;gBAC/J,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,+FAA+F,KAAK,iBAAiB,SAAS,0DAA0D;qBAClM;iBACF;gBACD,SAAS,EAAE,EAAE;gBACb,WAAW,EAAE,GAAG;aACjB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO;iBAC1B,IAAI,EAAE;iBACN,WAAW,EAAE;iBACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;iBAC3B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;iBACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAEzB,OAAO,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,KAAa;QAChC,OAAO,KAAK;aACT,WAAW,EAAE;aACb,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;aAC3B,IAAI,EAAE;aACN,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;aACpB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC;IACjC,CAAC;IAEO,aAAa;QACnB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACnD,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,EAAE,CAAC;IACjC,CAAC;CACF"}
1
+ {"version":3,"file":"filename-generator.js","sourceRoot":"","sources":["../../../src/recording/filename-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { LLMAdapter } from '../llm/types.js';
2
+ export interface RecordingOptions {
3
+ /** --record 또는 -r 플래그 */
4
+ record?: boolean;
5
+ /** --mp4 플래그 — GIF와 함께 mp4도 생성 */
6
+ mp4?: boolean;
7
+ /** 출력 디렉토리 (기본값: 현재 디렉토리) */
8
+ outputDir?: string;
9
+ }
10
+ /**
11
+ * RecordingOrchestrator: asciinema 기반 녹화의 전체 생명주기를 조율한다.
12
+ *
13
+ * 사용 패턴 (interview CLI):
14
+ *
15
+ * 1. startIfNeeded() — interview 시작 전 호출. --record 플래그가 있고
16
+ * 아직 asciinema로 감싸지지 않았으면 self-respawn으로 재실행.
17
+ *
18
+ * 2. stopAndConvert() — interview 완료 후 호출. 백그라운드 비동기로
19
+ * .cast → GIF (→ mp4) 변환을 트리거한다.
20
+ */
21
+ export declare class RecordingOrchestrator {
22
+ private readonly llm;
23
+ private readonly asciinemaInstaller;
24
+ private readonly aggInstaller;
25
+ private readonly converter;
26
+ constructor(llm: LLMAdapter);
27
+ /**
28
+ * 필요하면 asciinema 녹화를 시작한다.
29
+ * - GESTALT_RECORDING=1이면 이미 asciinema 안에 있으므로 아무것도 하지 않음.
30
+ * - --record 플래그가 있으면 asciinema를 설치하고 self-respawn.
31
+ * - 재실행 후에는 process.exit()이 호출되므로 이 함수는 return하지 않을 수 있음.
32
+ */
33
+ startIfNeeded(options: RecordingOptions): Promise<void>;
34
+ /**
35
+ * 현재 프로세스가 asciinema로 녹화 중인지 확인.
36
+ * GESTALT_CAST_PATH 환경변수가 있으면 true.
37
+ */
38
+ isRecording(): boolean;
39
+ /**
40
+ * 녹화를 종료하고 GIF (+ mp4) 변환을 백그라운드로 트리거한다.
41
+ * asciinema는 부모 프로세스(respawned)에서 자동 종료되므로
42
+ * 여기서는 cast 파일 경로를 읽어 변환만 시작한다.
43
+ *
44
+ * @param topic - 인터뷰 주제 (파일명 생성용)
45
+ * @param sessionId - 세션 ID (파일명 생성용)
46
+ * @param options - 녹화 옵션
47
+ */
48
+ stopAndConvert(topic: string, sessionId: string, options?: RecordingOptions): Promise<void>;
49
+ }
50
+ //# sourceMappingURL=recording-orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recording-orchestrator.d.ts","sourceRoot":"","sources":["../../../src/recording/recording-orchestrator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,qBAAqB;IAKpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJhC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;gBAEnB,GAAG,EAAE,UAAU;IAE5C;;;;;OAKG;IACG,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D;;;OAGG;IACH,WAAW,IAAI,OAAO;IAItB;;;;;;;;OAQG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAyCtG"}
@@ -0,0 +1,98 @@
1
+ import { AsciinemaInstaller } from './asciinema-installer.js';
2
+ import { AsciinemaRecorder } from './asciinema-recorder.js';
3
+ import { AggInstaller } from './agg-installer.js';
4
+ import { AggConverter } from './agg-converter.js';
5
+ import { FilenameGenerator } from './filename-generator.js';
6
+ /**
7
+ * RecordingOrchestrator: asciinema 기반 녹화의 전체 생명주기를 조율한다.
8
+ *
9
+ * 사용 패턴 (interview CLI):
10
+ *
11
+ * 1. startIfNeeded() — interview 시작 전 호출. --record 플래그가 있고
12
+ * 아직 asciinema로 감싸지지 않았으면 self-respawn으로 재실행.
13
+ *
14
+ * 2. stopAndConvert() — interview 완료 후 호출. 백그라운드 비동기로
15
+ * .cast → GIF (→ mp4) 변환을 트리거한다.
16
+ */
17
+ export class RecordingOrchestrator {
18
+ llm;
19
+ asciinemaInstaller = new AsciinemaInstaller();
20
+ aggInstaller = new AggInstaller();
21
+ converter = new AggConverter();
22
+ constructor(llm) {
23
+ this.llm = llm;
24
+ }
25
+ /**
26
+ * 필요하면 asciinema 녹화를 시작한다.
27
+ * - GESTALT_RECORDING=1이면 이미 asciinema 안에 있으므로 아무것도 하지 않음.
28
+ * - --record 플래그가 있으면 asciinema를 설치하고 self-respawn.
29
+ * - 재실행 후에는 process.exit()이 호출되므로 이 함수는 return하지 않을 수 있음.
30
+ */
31
+ async startIfNeeded(options) {
32
+ if (!options.record)
33
+ return;
34
+ if (AsciinemaRecorder.isInsideRecording())
35
+ return;
36
+ await this.asciinemaInstaller.ensureInstalled();
37
+ const castPath = AsciinemaRecorder.createTempCastPath();
38
+ console.log('📹 Starting asciinema recording...\n');
39
+ AsciinemaRecorder.respawnWithAsciinema(castPath);
40
+ // respawnWithAsciinema calls process.exit() — 이 줄은 실행되지 않음
41
+ }
42
+ /**
43
+ * 현재 프로세스가 asciinema로 녹화 중인지 확인.
44
+ * GESTALT_CAST_PATH 환경변수가 있으면 true.
45
+ */
46
+ isRecording() {
47
+ return AsciinemaRecorder.isInsideRecording() && !!AsciinemaRecorder.getCurrentCastPath();
48
+ }
49
+ /**
50
+ * 녹화를 종료하고 GIF (+ mp4) 변환을 백그라운드로 트리거한다.
51
+ * asciinema는 부모 프로세스(respawned)에서 자동 종료되므로
52
+ * 여기서는 cast 파일 경로를 읽어 변환만 시작한다.
53
+ *
54
+ * @param topic - 인터뷰 주제 (파일명 생성용)
55
+ * @param sessionId - 세션 ID (파일명 생성용)
56
+ * @param options - 녹화 옵션
57
+ */
58
+ async stopAndConvert(topic, sessionId, options = {}) {
59
+ const castPath = AsciinemaRecorder.getCurrentCastPath();
60
+ if (!castPath)
61
+ return;
62
+ try {
63
+ await this.aggInstaller.ensureInstalled();
64
+ }
65
+ catch (err) {
66
+ const msg = err instanceof Error ? err.message : String(err);
67
+ console.error(`⚠️ agg installation failed: ${msg}`);
68
+ console.error(' GIF conversion skipped. The .cast file is preserved at:', castPath);
69
+ return;
70
+ }
71
+ const filenameGen = new FilenameGenerator(this.llm, { outputDir: options.outputDir });
72
+ const gifPath = await filenameGen.generate(topic, sessionId);
73
+ console.log('\n🎬 Converting recording to GIF in background...');
74
+ // 백그라운드 비동기 — await하지 않음
75
+ void this.converter
76
+ .convertAsync(castPath, gifPath, {
77
+ deleteCastAfter: true,
78
+ onComplete: (outputPath) => {
79
+ console.log(`✅ GIF saved: ${outputPath}\n`);
80
+ if (options.mp4) {
81
+ const mp4Path = outputPath.replace(/\.gif$/, '.mp4');
82
+ void this.converter.convertGifToMp4Async(outputPath, mp4Path, {
83
+ onComplete: (p) => console.log(`✅ MP4 saved: ${p}\n`),
84
+ onError: (e) => console.error(`⚠️ MP4 conversion failed: ${e.message}`),
85
+ });
86
+ }
87
+ },
88
+ onError: (err) => {
89
+ console.error(`⚠️ GIF conversion failed: ${err.message}`);
90
+ console.error(' The .cast file may be preserved at:', castPath);
91
+ },
92
+ })
93
+ .catch(() => {
94
+ // onError에서 처리됨
95
+ });
96
+ }
97
+ }
98
+ //# sourceMappingURL=recording-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recording-orchestrator.js","sourceRoot":"","sources":["../../../src/recording/recording-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,qBAAqB;IAKH;IAJZ,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC9C,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;IAClC,SAAS,GAAG,IAAI,YAAY,EAAE,CAAC;IAEhD,YAA6B,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IAAG,CAAC;IAEhD;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,OAAyB;QAC3C,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO;QAC5B,IAAI,iBAAiB,CAAC,iBAAiB,EAAE;YAAE,OAAO;QAElD,MAAM,IAAI,CAAC,kBAAkB,CAAC,eAAe,EAAE,CAAC;QAEhD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,iBAAiB,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QACjD,2DAA2D;IAC7D,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,OAAO,iBAAiB,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,CAAC;IAC3F,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,cAAc,CAAC,KAAa,EAAE,SAAiB,EAAE,UAA4B,EAAE;QACnF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,CAAC;QACxD,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QAC5C,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,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,KAAK,CAAC,2DAA2D,EAAE,QAAQ,CAAC,CAAC;YACrF,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACtF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QAEjE,yBAAyB;QACzB,KAAK,IAAI,CAAC,SAAS;aAChB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC/B,eAAe,EAAE,IAAI;YACrB,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE;gBACzB,OAAO,CAAC,GAAG,CAAC,gBAAgB,UAAU,IAAI,CAAC,CAAC;gBAC5C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;oBAChB,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBACrD,KAAK,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,UAAU,EAAE,OAAO,EAAE;wBAC5D,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC;wBACrD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,OAAO,EAAE,CAAC;qBACzE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC3D,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,QAAQ,CAAC,CAAC;YACnE,CAAC;SACF,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,gBAAgB;QAClB,CAAC,CAAC,CAAC;IACP,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=postinstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../../../src/scripts/postinstall.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Postinstall script: auto-setup agg for GIF recording support.
3
+ * Runs after: npm install @tienne/gestalt
4
+ *
5
+ * - Silently skips in CI or if GESTALT_SKIP_DEPS=1
6
+ * - Always exits 0 (never fails the install)
7
+ */
8
+ import { AggInstaller } from '../recording/agg-installer.js';
9
+ async function main() {
10
+ if (process.env['CI'] || process.env['GESTALT_SKIP_DEPS'] === '1') {
11
+ return;
12
+ }
13
+ const installer = new AggInstaller();
14
+ if (installer.isInstalled())
15
+ return;
16
+ process.stdout.write('\n[gestalt] agg not found — setting up GIF recording support...\n');
17
+ try {
18
+ await installer.ensureInstalled();
19
+ }
20
+ catch (err) {
21
+ const msg = err instanceof Error ? err.message : String(err);
22
+ process.stdout.write(`[gestalt] Skipping agg setup: ${msg}\n`);
23
+ process.stdout.write('[gestalt] Install manually later: https://github.com/asciinema/agg\n\n');
24
+ }
25
+ }
26
+ main().then(() => process.exit(0)).catch(() => process.exit(0));
27
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.js","sourceRoot":"","sources":["../../../src/scripts/postinstall.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,GAAG,EAAE,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,YAAY,EAAE,CAAC;IACrC,IAAI,SAAS,CAAC,WAAW,EAAE;QAAE,OAAO;IAEpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;IAE1F,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,eAAe,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,GAAG,IAAI,CAAC,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;IACjG,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -3,6 +3,7 @@ import { AmbiguityThresholdError, SpecGenerationError } from '../core/errors.js'
3
3
  import { type Result } from '../core/result.js';
4
4
  import { EventStore } from '../events/store.js';
5
5
  import type { AgentRegistry } from '../agent/registry.js';
6
+ export declare const TEXT_INPUT_SESSION_ID = "text-input";
6
7
  export interface SpecContext {
7
8
  systemPrompt: string;
8
9
  specPrompt: string;
@@ -30,5 +31,6 @@ export declare class PassthroughSpecGenerator {
30
31
  constructor(eventStore: EventStore, agentRegistry?: AgentRegistry);
31
32
  buildSpecContext(session: InterviewSession): SpecContext;
32
33
  validateAndStore(session: InterviewSession, externalSpec: ExternalSpec, force?: boolean): Result<Spec, SpecGenerationError | AmbiguityThresholdError>;
34
+ validateAndStoreFromText(externalSpec: ExternalSpec): Result<Spec, SpecGenerationError>;
33
35
  }
34
36
  //# sourceMappingURL=passthrough-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"passthrough-generator.d.ts","sourceRoot":"","sources":["../../../src/spec/passthrough-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1D,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,EAAE;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,SAAS,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAC9D,eAAe,EAAE,OAAO,EAAE,CAAC;CAC5B;AAID,qBAAa,wBAAwB;IAGvB,OAAO,CAAC,UAAU;IAF9B,OAAO,CAAC,aAAa,CAAC,CAAgB;gBAElB,UAAU,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,aAAa;IAIzE,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW;IA4BxD,gBAAgB,CACd,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,YAAY,EAC1B,KAAK,UAAQ,GACZ,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,uBAAuB,CAAC;CA6D/D"}
1
+ {"version":3,"file":"passthrough-generator.d.ts","sourceRoot":"","sources":["../../../src/spec/passthrough-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAkB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAIlD,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,EAAE;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,SAAS,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAC9D,eAAe,EAAE,OAAO,EAAE,CAAC;CAC5B;AAID,qBAAa,wBAAwB;IAGvB,OAAO,CAAC,UAAU;IAF9B,OAAO,CAAC,aAAa,CAAC,CAAgB;gBAElB,UAAU,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,aAAa;IAIzE,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW;IA4BxD,gBAAgB,CACd,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,YAAY,EAC1B,KAAK,UAAQ,GACZ,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,uBAAuB,CAAC;IA8D9D,wBAAwB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,mBAAmB,CAAC;CAgDxF"}
@@ -6,6 +6,7 @@ import { specSchema } from './schema.js';
6
6
  import { EventType } from '../events/types.js';
7
7
  import { INTERVIEW_SYSTEM_PROMPT, buildSpecPrompt } from '../llm/prompts.js';
8
8
  import { mergeSystemPrompt, getActiveAgentNames } from '../agent/prompt-resolver.js';
9
+ export const TEXT_INPUT_SESSION_ID = 'text-input';
9
10
  // ─── Generator ──────────────────────────────────────────────────
10
11
  export class PassthroughSpecGenerator {
11
12
  eventStore;
@@ -82,5 +83,38 @@ export class PassthroughSpecGenerator {
82
83
  return err(new SpecGenerationError(`Failed to validate spec: ${e instanceof Error ? e.message : String(e)}`));
83
84
  }
84
85
  }
86
+ validateAndStoreFromText(externalSpec) {
87
+ try {
88
+ const spec = {
89
+ version: '1.0.0',
90
+ goal: externalSpec.goal,
91
+ constraints: externalSpec.constraints,
92
+ acceptanceCriteria: externalSpec.acceptanceCriteria,
93
+ ontologySchema: externalSpec.ontologySchema,
94
+ gestaltAnalysis: externalSpec.gestaltAnalysis,
95
+ metadata: {
96
+ specId: randomUUID(),
97
+ interviewSessionId: TEXT_INPUT_SESSION_ID,
98
+ ambiguityScore: 0,
99
+ generatedAt: new Date().toISOString(),
100
+ },
101
+ };
102
+ const validation = specSchema.safeParse(spec);
103
+ if (!validation.success) {
104
+ return err(new SpecGenerationError(`Spec validation failed: ${validation.error.message}`));
105
+ }
106
+ this.eventStore.append('spec', spec.metadata.specId, EventType.SPEC_GENERATED, {
107
+ sessionId: TEXT_INPUT_SESSION_ID,
108
+ goal: spec.goal,
109
+ constraintCount: spec.constraints.length,
110
+ criteriaCount: spec.acceptanceCriteria.length,
111
+ source: 'text',
112
+ });
113
+ return ok(spec);
114
+ }
115
+ catch (e) {
116
+ return err(new SpecGenerationError(`Failed to validate spec: ${e instanceof Error ? e.message : String(e)}`));
117
+ }
118
+ }
85
119
  }
86
120
  //# sourceMappingURL=passthrough-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"passthrough-generator.js","sourceRoot":"","sources":["../../../src/spec/passthrough-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"passthrough-generator.js","sourceRoot":"","sources":["../../../src/spec/passthrough-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SpecTemplate } from '../core/types.js';
2
+ export declare class SpecTemplateRegistry {
3
+ get(id: string): SpecTemplate | undefined;
4
+ list(): SpecTemplate[];
5
+ has(id: string): boolean;
6
+ /**
7
+ * 템플릿을 기반으로 specPrompt를 위한 추가 컨텍스트 문자열 생성.
8
+ * TextBasedSpecGenerator.buildSpecContext()에서 주입된다.
9
+ */
10
+ buildTemplateContext(id: string): string | null;
11
+ }
12
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/spec/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA4ErD,qBAAa,oBAAoB;IAC/B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzC,IAAI,IAAI,YAAY,EAAE;IAItB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAoBhD"}