@tienne/gestalt 0.102.0 → 0.104.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 (179) hide show
  1. package/README.ko.md +2 -1
  2. package/README.md +2 -1
  3. package/dist/package.json +1 -1
  4. package/dist/plugin/role-agents/video-summarizer/AGENT.md +208 -108
  5. package/dist/plugin/skills/_shared/proactive-routing.md +2 -1
  6. package/dist/plugin/skills/research/references/design.md +1 -1
  7. package/dist/plugin/skills/video-digest/SKILL.md +430 -0
  8. package/dist/plugin/skills/video-digest/templates/background.md +15 -0
  9. package/dist/plugin/skills/video-digest/templates/blog.md +16 -0
  10. package/dist/plugin/skills/video-digest/templates/comments.md +19 -0
  11. package/dist/plugin/skills/video-digest/templates/counterpoints.md +15 -0
  12. package/dist/plugin/skills/video-digest/templates/flashcards.md +15 -0
  13. package/dist/plugin/skills/video-digest/templates/interview.md +15 -0
  14. package/dist/plugin/skills/video-digest/templates/meeting.md +15 -0
  15. package/dist/plugin/skills/video-digest/templates/mindmap.md +16 -0
  16. package/dist/plugin/skills/video-digest/templates/quiz.md +16 -0
  17. package/dist/plugin/skills/video-digest/templates/quotes.md +16 -0
  18. package/dist/plugin/skills/video-digest/templates/resources.md +14 -0
  19. package/dist/plugin/skills/video-digest/templates/timestamps.md +14 -0
  20. package/dist/plugin/skills/video-digest/templates/visual.md +22 -0
  21. package/dist/src/cli/commands/digest.d.ts +60 -0
  22. package/dist/src/cli/commands/digest.d.ts.map +1 -0
  23. package/dist/src/cli/commands/digest.js +401 -0
  24. package/dist/src/cli/commands/digest.js.map +1 -0
  25. package/dist/src/cli/index.d.ts.map +1 -1
  26. package/dist/src/cli/index.js +81 -0
  27. package/dist/src/cli/index.js.map +1 -1
  28. package/dist/src/digest/blocks.d.ts +5224 -0
  29. package/dist/src/digest/blocks.d.ts.map +1 -0
  30. package/dist/src/digest/blocks.js +156 -0
  31. package/dist/src/digest/blocks.js.map +1 -0
  32. package/dist/src/digest/captions.d.ts +37 -0
  33. package/dist/src/digest/captions.d.ts.map +1 -0
  34. package/dist/src/digest/captions.js +138 -0
  35. package/dist/src/digest/captions.js.map +1 -0
  36. package/dist/src/digest/comments.d.ts +113 -0
  37. package/dist/src/digest/comments.d.ts.map +1 -0
  38. package/dist/src/digest/comments.js +153 -0
  39. package/dist/src/digest/comments.js.map +1 -0
  40. package/dist/src/digest/diagram-schema.d.ts +765 -0
  41. package/dist/src/digest/diagram-schema.d.ts.map +1 -0
  42. package/dist/src/digest/diagram-schema.js +72 -0
  43. package/dist/src/digest/diagram-schema.js.map +1 -0
  44. package/dist/src/digest/format.d.ts +9 -0
  45. package/dist/src/digest/format.d.ts.map +1 -0
  46. package/dist/src/digest/format.js +26 -0
  47. package/dist/src/digest/format.js.map +1 -0
  48. package/dist/src/digest/frames.d.ts +46 -0
  49. package/dist/src/digest/frames.d.ts.map +1 -0
  50. package/dist/src/digest/frames.js +206 -0
  51. package/dist/src/digest/frames.js.map +1 -0
  52. package/dist/src/digest/index.d.ts +26 -0
  53. package/dist/src/digest/index.d.ts.map +1 -0
  54. package/dist/src/digest/index.js +26 -0
  55. package/dist/src/digest/index.js.map +1 -0
  56. package/dist/src/digest/ingest.d.ts +65 -0
  57. package/dist/src/digest/ingest.d.ts.map +1 -0
  58. package/dist/src/digest/ingest.js +303 -0
  59. package/dist/src/digest/ingest.js.map +1 -0
  60. package/dist/src/digest/lint-extension.d.ts +71 -0
  61. package/dist/src/digest/lint-extension.d.ts.map +1 -0
  62. package/dist/src/digest/lint-extension.js +512 -0
  63. package/dist/src/digest/lint-extension.js.map +1 -0
  64. package/dist/src/digest/lint.d.ts +50 -0
  65. package/dist/src/digest/lint.d.ts.map +1 -0
  66. package/dist/src/digest/lint.js +560 -0
  67. package/dist/src/digest/lint.js.map +1 -0
  68. package/dist/src/digest/merge.d.ts +40 -0
  69. package/dist/src/digest/merge.d.ts.map +1 -0
  70. package/dist/src/digest/merge.js +107 -0
  71. package/dist/src/digest/merge.js.map +1 -0
  72. package/dist/src/digest/ocr.d.ts +100 -0
  73. package/dist/src/digest/ocr.d.ts.map +1 -0
  74. package/dist/src/digest/ocr.js +179 -0
  75. package/dist/src/digest/ocr.js.map +1 -0
  76. package/dist/src/digest/prose.d.ts +47 -0
  77. package/dist/src/digest/prose.d.ts.map +1 -0
  78. package/dist/src/digest/prose.js +171 -0
  79. package/dist/src/digest/prose.js.map +1 -0
  80. package/dist/src/digest/render-blocks.d.ts +38 -0
  81. package/dist/src/digest/render-blocks.d.ts.map +1 -0
  82. package/dist/src/digest/render-blocks.js +378 -0
  83. package/dist/src/digest/render-blocks.js.map +1 -0
  84. package/dist/src/digest/render-html.d.ts +22 -0
  85. package/dist/src/digest/render-html.d.ts.map +1 -0
  86. package/dist/src/digest/render-html.js +505 -0
  87. package/dist/src/digest/render-html.js.map +1 -0
  88. package/dist/src/digest/render-md.d.ts +18 -0
  89. package/dist/src/digest/render-md.d.ts.map +1 -0
  90. package/dist/src/digest/render-md.js +126 -0
  91. package/dist/src/digest/render-md.js.map +1 -0
  92. package/dist/src/digest/render.d.ts +47 -0
  93. package/dist/src/digest/render.d.ts.map +1 -0
  94. package/dist/src/digest/render.js +126 -0
  95. package/dist/src/digest/render.js.map +1 -0
  96. package/dist/src/digest/reports.d.ts +26 -0
  97. package/dist/src/digest/reports.d.ts.map +1 -0
  98. package/dist/src/digest/reports.js +70 -0
  99. package/dist/src/digest/reports.js.map +1 -0
  100. package/dist/src/digest/scenes.d.ts +92 -0
  101. package/dist/src/digest/scenes.d.ts.map +1 -0
  102. package/dist/src/digest/scenes.js +182 -0
  103. package/dist/src/digest/scenes.js.map +1 -0
  104. package/dist/src/digest/schema-base.d.ts +31 -0
  105. package/dist/src/digest/schema-base.d.ts.map +1 -0
  106. package/dist/src/digest/schema-base.js +19 -0
  107. package/dist/src/digest/schema-base.js.map +1 -0
  108. package/dist/src/digest/schema.d.ts +12886 -0
  109. package/dist/src/digest/schema.d.ts.map +1 -0
  110. package/dist/src/digest/schema.js +215 -0
  111. package/dist/src/digest/schema.js.map +1 -0
  112. package/dist/src/digest/server.d.ts +36 -0
  113. package/dist/src/digest/server.d.ts.map +1 -0
  114. package/dist/src/digest/server.js +278 -0
  115. package/dist/src/digest/server.js.map +1 -0
  116. package/dist/src/digest/slice.d.ts +20 -0
  117. package/dist/src/digest/slice.d.ts.map +1 -0
  118. package/dist/src/digest/slice.js +48 -0
  119. package/dist/src/digest/slice.js.map +1 -0
  120. package/dist/src/digest/store.d.ts +67 -0
  121. package/dist/src/digest/store.d.ts.map +1 -0
  122. package/dist/src/digest/store.js +152 -0
  123. package/dist/src/digest/store.js.map +1 -0
  124. package/dist/src/digest/svg.d.ts +74 -0
  125. package/dist/src/digest/svg.d.ts.map +1 -0
  126. package/dist/src/digest/svg.js +415 -0
  127. package/dist/src/digest/svg.js.map +1 -0
  128. package/dist/src/digest/templates.d.ts +38 -0
  129. package/dist/src/digest/templates.d.ts.map +1 -0
  130. package/dist/src/digest/templates.js +125 -0
  131. package/dist/src/digest/templates.js.map +1 -0
  132. package/dist/src/digest/translate.d.ts +46 -0
  133. package/dist/src/digest/translate.d.ts.map +1 -0
  134. package/dist/src/digest/translate.js +50 -0
  135. package/dist/src/digest/translate.js.map +1 -0
  136. package/dist/src/digest/viewer-js.d.ts +4 -0
  137. package/dist/src/digest/viewer-js.d.ts.map +1 -0
  138. package/dist/src/digest/viewer-js.js +735 -0
  139. package/dist/src/digest/viewer-js.js.map +1 -0
  140. package/dist/src/digest/viewer-logic.d.ts +46 -0
  141. package/dist/src/digest/viewer-logic.d.ts.map +1 -0
  142. package/dist/src/digest/viewer-logic.js +89 -0
  143. package/dist/src/digest/viewer-logic.js.map +1 -0
  144. package/dist/src/digest/ytdlp.d.ts +34 -0
  145. package/dist/src/digest/ytdlp.d.ts.map +1 -0
  146. package/dist/src/digest/ytdlp.js +64 -0
  147. package/dist/src/digest/ytdlp.js.map +1 -0
  148. package/dist/src/mcp/schemas.d.ts +48 -0
  149. package/dist/src/mcp/schemas.d.ts.map +1 -1
  150. package/dist/src/mcp/schemas.js +25 -0
  151. package/dist/src/mcp/schemas.js.map +1 -1
  152. package/dist/src/mcp/server.d.ts.map +1 -1
  153. package/dist/src/mcp/server.js +7 -1
  154. package/dist/src/mcp/server.js.map +1 -1
  155. package/dist/src/mcp/tools/digest-passthrough.d.ts +3 -0
  156. package/dist/src/mcp/tools/digest-passthrough.d.ts.map +1 -0
  157. package/dist/src/mcp/tools/digest-passthrough.js +151 -0
  158. package/dist/src/mcp/tools/digest-passthrough.js.map +1 -0
  159. package/package.json +1 -1
  160. package/plugin/.codex-plugin/plugin.json +1 -1
  161. package/plugin/.mcp.json +1 -1
  162. package/plugin/mcp.json +1 -1
  163. package/plugin/role-agents/video-summarizer/AGENT.md +208 -108
  164. package/plugin/skills/_shared/proactive-routing.md +2 -1
  165. package/plugin/skills/research/references/design.md +1 -1
  166. package/plugin/skills/video-digest/SKILL.md +430 -0
  167. package/plugin/skills/video-digest/templates/background.md +15 -0
  168. package/plugin/skills/video-digest/templates/blog.md +16 -0
  169. package/plugin/skills/video-digest/templates/comments.md +19 -0
  170. package/plugin/skills/video-digest/templates/counterpoints.md +15 -0
  171. package/plugin/skills/video-digest/templates/flashcards.md +15 -0
  172. package/plugin/skills/video-digest/templates/interview.md +15 -0
  173. package/plugin/skills/video-digest/templates/meeting.md +15 -0
  174. package/plugin/skills/video-digest/templates/mindmap.md +16 -0
  175. package/plugin/skills/video-digest/templates/quiz.md +16 -0
  176. package/plugin/skills/video-digest/templates/quotes.md +16 -0
  177. package/plugin/skills/video-digest/templates/resources.md +14 -0
  178. package/plugin/skills/video-digest/templates/timestamps.md +14 -0
  179. package/plugin/skills/video-digest/templates/visual.md +22 -0
@@ -0,0 +1,14 @@
1
+ ---
2
+ id: resources
3
+ title: 언급된 리소스
4
+ description: 영상에 나온 책, 도구, 서비스, 사람, 자료를 모은다
5
+ blocks: [heading, list]
6
+ order: 80
7
+ ---
8
+
9
+ 강의나 리뷰 영상에서 언급된 리소스를 모은다.
10
+
11
+ - 종류별로 heading 블록을 둔다. 책, 도구와 서비스, 사람, 논문과 자료 가운데 실제로 나온 것만 쓴다
12
+ - 각 heading 아래 list 블록 하나에 항목을 둔다. 항목 text는 이름과 영상이 그걸 어떻게 소개했는지 한 문장이다
13
+ - 항목마다 처음 언급된 문장을 cite로 단다
14
+ - 링크나 URL은 쓰지 않는다. 영상에서 이름을 정확히 못 알아들었으면 들린 대로 적고 그렇다고 밝힌다
@@ -0,0 +1,14 @@
1
+ ---
2
+ id: timestamps
3
+ title: 타임스탬프
4
+ description: 주제가 바뀌는 자리마다 시각과 제목을 단 목차를 만든다
5
+ blocks: [timestamps]
6
+ order: 20
7
+ ---
8
+
9
+ 영상 전체를 훑는 목차를 만든다.
10
+
11
+ - timestamps 블록 하나만 쓴다. 주제가 바뀌는 자리마다 항목 하나를 둔다
12
+ - 10분 영상이면 6~10개, 1시간이면 15~30개 정도로 둔다. 너무 잘게 쪼개지 않는다
13
+ - cite.key는 그 주제가 시작되는 문장이고 from~to는 그 주제가 이어지는 구간이다. 항목끼리 구간이 겹치지 않게 시간 순으로 둔다
14
+ - title은 20자 안쪽 명사구로 쓴다. summary는 한 문장으로 그 구간에서 무슨 말을 하는지 적는다
@@ -0,0 +1,22 @@
1
+ ---
2
+ id: visual
3
+ title: 그림 해설
4
+ description: 핵심 개념마다 그림 하나와 짧은 설명을 짝지은 리포트
5
+ blocks: [text, figure]
6
+ order: 16
7
+ ---
8
+
9
+ 영상의 핵심 개념을 4~8개 골라 개념마다 그림 하나와 짧은 설명을 짝지어 보여준다. 요약 탭은 영상 순서를 따라가지만 이 탭은 개념 순서를 따라간다. 앞 개념을 알아야 뒤 개념이 읽히면 그 순서로 놓는다. 그림은 렌더러가 그리므로 도식 구조만 채운다. SVG나 HTML은 쓰지 않는다.
10
+
11
+ - 첫 text 블록에 어떤 개념을 골랐고 어떤 순서로 놓았는지 한두 문장으로 적는다
12
+ - 개념마다 figure 블록을 하나 둔다. title은 개념 이름을 명사구로 적는다
13
+ - diagram은 대섹션 도식과 같은 구조다. 개념의 모양에 맞는 종류를 고른다
14
+ - 차례로 이어지는 단계는 flow, 처음으로 돌아오는 고리는 cycle
15
+ - 둘 이상을 나란히 견주면 compare, 한 주제에서 가지가 뻗으면 tree
16
+ - 시점이 붙은 사건 흐름은 timeline, 두 기준으로 나눈 네 칸은 matrix
17
+ - 원인과 결과가 한 현상에 모이면 causal, 바뀌기 전과 후를 보여주면 beforeAfter
18
+ - 같은 종류만 이어 쓰지 않는다. 개념마다 맞는 모양이 다르다
19
+ - explanation은 2~4문장으로 그림이 말하지 않는 것을 적는다. 왜 그런지, 언제 쓰는지, 영상에서 어떤 예를 들었는지다. 그림 라벨을 그대로 다시 읊지 않는다
20
+ - cite는 그 개념을 가장 잘 설명한 구간을 단다. 대섹션 범위에 묶이지 않고 스크립트 안이면 된다
21
+ - 그림 라벨은 한 줄에 들어가는 짧은 명사구로 쓴다. 굵게(\*\*)를 쓰지 않는다
22
+ - 영상에서 그 내용이 나온 자리가 분명한 노드에는 cite를 단다. 누르면 영상이 그 자리로 간다
@@ -0,0 +1,60 @@
1
+ import { type OcrResult } from '../../digest/ocr.js';
2
+ import { type RenderFilesResult } from '../../digest/render.js';
3
+ /**
4
+ * `gestalt digest` — 영상 요약 CLI.
5
+ *
6
+ * yt-dlp와 ffmpeg, whisper를 부르는 셸 작업이라 MCP action이 아니라 여기 둔다.
7
+ * research가 slide-extract.mjs를 MCP로 올리지 않은 것과 같은 이유다.
8
+ */
9
+ export interface DigestCommonOptions {
10
+ repoRoot?: string;
11
+ json?: boolean;
12
+ }
13
+ export declare function digestIngestCommand(input: string, opts: DigestCommonOptions & {
14
+ lang?: string;
15
+ slug?: string;
16
+ whisper?: boolean;
17
+ whisperModel?: string;
18
+ ocr?: boolean;
19
+ ocrInterval?: string;
20
+ }): Promise<void>;
21
+ export declare function digestCommentsCommand(slug: string, opts: DigestCommonOptions & {
22
+ max?: string;
23
+ }): Promise<void>;
24
+ export declare function digestFramesCommand(slug: string, opts: DigestCommonOptions & {
25
+ force?: boolean;
26
+ }): Promise<void>;
27
+ export declare function digestScenesCommand(slug: string, opts: DigestCommonOptions): Promise<void>;
28
+ export declare function printOcr(r: OcrResult): void;
29
+ export declare function digestOcrCommand(slug: string, opts: DigestCommonOptions & {
30
+ interval?: string;
31
+ lang?: string;
32
+ }): Promise<void>;
33
+ export declare function digestValidateCommand(slug: string, opts: DigestCommonOptions): void;
34
+ export declare function renderDigestFiles(slug: string, opts: DigestCommonOptions & {
35
+ inlineFrames?: boolean;
36
+ }): RenderFilesResult;
37
+ export declare function digestRenderCommand(slug: string, opts: DigestCommonOptions & {
38
+ inlineFrames?: boolean;
39
+ }): void;
40
+ export declare function digestExportCommand(slug: string, opts: DigestCommonOptions & {
41
+ md?: boolean;
42
+ out?: string;
43
+ report?: string;
44
+ }): void;
45
+ export declare function digestMergeCommand(slug: string, reportFile: string, opts: DigestCommonOptions & {
46
+ extension?: boolean;
47
+ }): void;
48
+ export declare function digestTemplatesCommand(opts: DigestCommonOptions): void;
49
+ /** 요약 에이전트에게 넘길 템플릿 지시를 출력한다. --json이면 frontmatter까지 함께 준다 */
50
+ export declare function digestTemplateCommand(id: string, opts: DigestCommonOptions): void;
51
+ export declare function digestSliceCommand(slug: string, opts: DigestCommonOptions & {
52
+ range: string;
53
+ }): void;
54
+ export declare function digestTranslateApplyCommand(slug: string, file: string, opts: DigestCommonOptions): void;
55
+ export declare function parsePort(value: string): number;
56
+ export declare function digestServeCommand(slug: string, opts: DigestCommonOptions & {
57
+ port?: string;
58
+ browser?: boolean;
59
+ }): Promise<void>;
60
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,401 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { join, resolve } from 'node:path';
3
+ import { loadConfig } from '../../core/config.js';
4
+ import { COMMENTS_DEFAULT_MAX, commentsMap, fetchComments } from '../../digest/comments.js';
5
+ import { extractFrames } from '../../digest/frames.js';
6
+ import { ingest } from '../../digest/ingest.js';
7
+ import { lintDigest, lintErrors } from '../../digest/lint.js';
8
+ import { pickScenes, sceneSecs } from '../../digest/scenes.js';
9
+ import { mergeExtension, mergeReport } from '../../digest/merge.js';
10
+ import { runOcr } from '../../digest/ocr.js';
11
+ import { exportMarkdown, renderToFiles } from '../../digest/render.js';
12
+ import { parseDigest } from '../../digest/schema.js';
13
+ import { parseRangeArg, sliceFileName, sliceTranscript } from '../../digest/slice.js';
14
+ import { DigestServer, findDigestPort, openInBrowser } from '../../digest/server.js';
15
+ import { DigestStore } from '../../digest/store.js';
16
+ import { loadDigestTemplates, templateMap } from '../../digest/templates.js';
17
+ import { applyTranslation } from '../../digest/translate.js';
18
+ const rootOf = (opts) => resolve(opts.repoRoot ?? process.cwd());
19
+ function emit(value, json, human) {
20
+ if (json)
21
+ console.log(JSON.stringify(value, null, 2));
22
+ else
23
+ human();
24
+ }
25
+ function fail(e) {
26
+ console.error(e instanceof Error ? e.message : String(e));
27
+ process.exit(1);
28
+ }
29
+ // 깨진 템플릿 하나가 명령 전체를 막지 않게 경고만 stderr로 알린다. --json이면 결과에 싣는다
30
+ function templatesOf(opts) {
31
+ const load = loadDigestTemplates(rootOf(opts), loadConfig({}, { skipDotEnv: true }).skillsDir);
32
+ if (!opts.json)
33
+ for (const w of load.warnings)
34
+ console.error(`템플릿 경고: ${w}`);
35
+ return load;
36
+ }
37
+ const mmss = (sec) => `${Math.floor(sec / 60)}:${String(Math.floor(sec % 60)).padStart(2, '0')}`;
38
+ export async function digestIngestCommand(input, opts) {
39
+ try {
40
+ // 간격이 틀렸으면 수집을 다 마친 뒤가 아니라 시작하기 전에 알린다
41
+ const intervalSec = opts.ocr ? parseInterval(opts.ocrInterval) : undefined;
42
+ const r = await ingest(input, {
43
+ repoRoot: rootOf(opts),
44
+ lang: opts.lang,
45
+ slug: opts.slug,
46
+ whisper: opts.whisper,
47
+ whisperModel: opts.whisperModel,
48
+ });
49
+ // OCR이 실패해도 수집 결과는 남아 있어서 slug와 경로를 출력하고 종료 코드로만 알린다
50
+ let ocr;
51
+ if (opts.ocr) {
52
+ try {
53
+ ocr = await runOcr(r.slug, { repoRoot: rootOf(opts), intervalSec });
54
+ }
55
+ catch (e) {
56
+ ocr = { error: e.message };
57
+ process.exitCode = 1;
58
+ }
59
+ }
60
+ emit(ocr ? { ...r, ocr } : r, opts.json, () => {
61
+ console.log(`${r.title} (${mmss(r.durationSec)})`);
62
+ console.log(`자막: ${r.captionSource} [${r.captionTrack}] → 문장 ${r.segmentCount}개`);
63
+ console.log(`slug: ${r.slug}`);
64
+ console.log(`저장: ${r.transcriptPath}`);
65
+ if (r.staleDigest) {
66
+ const before = r.staleDigest.previousSegmentCount ?? '?';
67
+ console.log(`문장 번호가 바뀌어 기존 요약을 옮겼어요(문장 ${before}개 → ${r.segmentCount}개): ${r.staleDigest.movedTo}`);
68
+ }
69
+ if (ocr && 'error' in ocr)
70
+ console.log(`화면 글자를 못 읽었어요: ${ocr.error}`);
71
+ else if (ocr)
72
+ printOcr(ocr);
73
+ });
74
+ }
75
+ catch (e) {
76
+ fail(e);
77
+ }
78
+ }
79
+ export async function digestCommentsCommand(slug, opts) {
80
+ try {
81
+ const max = opts.max === undefined ? COMMENTS_DEFAULT_MAX : Number(opts.max);
82
+ const r = await fetchComments(slug, { repoRoot: rootOf(opts), max });
83
+ emit(r, opts.json, () => {
84
+ const total = r.commentCount === null ? '' : ` (영상 전체 ${r.commentCount}개)`;
85
+ console.log(`댓글 ${r.fetched}개를 받았어요${total}. 작성자 정보는 저장하지 않았어요.`);
86
+ console.log(`저장: ${r.path}`);
87
+ });
88
+ }
89
+ catch (e) {
90
+ fail(e);
91
+ }
92
+ }
93
+ export async function digestFramesCommand(slug, opts) {
94
+ try {
95
+ const r = await extractFrames(slug, { repoRoot: rootOf(opts), force: opts.force });
96
+ emit(r, opts.json, () => {
97
+ console.log(`프레임 ${r.total}장 중 ${r.extracted}장 새로 뽑음, ${r.skipped}장은 있던 것`);
98
+ if (r.missing.length > 0)
99
+ console.log(`못 뽑은 시각: ${r.missing.map(mmss).join(', ')}`);
100
+ const { shots } = r;
101
+ if (shots.total > 0) {
102
+ console.log(`장면 ${shots.total}장 중 ${shots.extracted}장 새로 뽑음(720p ${shots.hires}장), ${shots.skipped}장은 있던 것`);
103
+ if (shots.missing.length > 0) {
104
+ console.log(`못 뽑은 장면: ${shots.missing.map(mmss).join(', ')}`);
105
+ }
106
+ if (shots.extracted > shots.hires) {
107
+ // 사유 없이 저화질로 뽑았으면 720p 영상은 멀쩡한데 그 시각에서 파일이 안 생긴 것이다
108
+ const why = shots.hiresFailure ?? '720p 영상에서 그 시각을 못 뽑았어요';
109
+ console.log(`${why}. ${shots.extracted - shots.hires}장은 낮은 화질로 뽑았어요. 720p로 다시 뽑으려면 --force를 붙여 돌려 주세요.`);
110
+ }
111
+ }
112
+ console.log(`저장: ${r.framesDir}`);
113
+ });
114
+ }
115
+ catch (e) {
116
+ fail(e);
117
+ }
118
+ }
119
+ export async function digestScenesCommand(slug, opts) {
120
+ try {
121
+ const r = await pickScenes(slug, { repoRoot: rootOf(opts) });
122
+ emit(r, opts.json, () => {
123
+ const how = r.source === 'ocr' ? '화면 글자(ocr.json)' : 'ffmpeg 장면 전환';
124
+ console.log(`후보 장면 ${r.items}개 (${how})`);
125
+ if (r.truncated) {
126
+ console.log(`후보가 ${r.total}개라 영상 전체에서 고르게 ${r.items}개만 남겼어요.`);
127
+ }
128
+ console.log(`저장: ${r.path}`);
129
+ });
130
+ }
131
+ catch (e) {
132
+ fail(e);
133
+ }
134
+ }
135
+ function parseInterval(value) {
136
+ if (value === undefined)
137
+ return undefined;
138
+ if (!/^\d+$/.test(value.trim()))
139
+ throw new Error(`OCR 간격은 초 단위 정수여야 해요: ${value}`);
140
+ return Number(value);
141
+ }
142
+ export function printOcr(r) {
143
+ if (r.requestedIntervalSec !== undefined) {
144
+ console.log(`프레임이 너무 많아 간격을 ${r.requestedIntervalSec}초에서 ${r.intervalSec}초로 넓혔어요`);
145
+ }
146
+ console.log(`화면 글자: 프레임 ${r.frames}장(${r.intervalSec}초 간격, ${r.lang}) → ${r.items}개`);
147
+ if (r.truncated > 0)
148
+ console.log(`글자가 길어 줄 단위로 자른 항목: ${r.truncated}개`);
149
+ if (r.loggedTimes !== undefined) {
150
+ console.log(`프레임 ${r.frames}장 중 시각 로그가 ${r.loggedTimes}개뿐이라 나머지는 간격으로 시각을 어림했어요`);
151
+ }
152
+ console.log(`저장: ${r.path}`);
153
+ }
154
+ export async function digestOcrCommand(slug, opts) {
155
+ try {
156
+ const r = await runOcr(slug, {
157
+ repoRoot: rootOf(opts),
158
+ intervalSec: parseInterval(opts.interval),
159
+ lang: opts.lang,
160
+ });
161
+ emit(r, opts.json, () => printOcr(r));
162
+ }
163
+ catch (e) {
164
+ fail(e);
165
+ }
166
+ }
167
+ export function digestValidateCommand(slug, opts) {
168
+ try {
169
+ const store = new DigestStore(rootOf(opts));
170
+ const t = store.readTranscript(slug);
171
+ if (!t.ok)
172
+ throw new Error(t.message);
173
+ const transcript = t.transcript;
174
+ const raw = store.readDigestFile(slug);
175
+ if (raw.kind !== 'ok') {
176
+ throw new Error(raw.kind === 'missing' ? `digest.json이 없어요: ${slug}` : raw.message);
177
+ }
178
+ const parsed = parseDigest(raw.value);
179
+ if (!parsed.ok)
180
+ throw parsed.error;
181
+ const { templates } = templatesOf(opts);
182
+ const issues = lintDigest(parsed.value, transcript, {
183
+ templates: templateMap(templates),
184
+ comments: commentsMap(store, slug) ?? undefined,
185
+ scenes: sceneSecs(store, slug),
186
+ });
187
+ const errors = lintErrors(issues);
188
+ emit({ slug, ok: errors.length === 0, issues }, opts.json, () => {
189
+ for (const i of issues)
190
+ console.log(`${i.severity} ${i.code} ${i.path}: ${i.message}`);
191
+ console.log(errors.length === 0 ? `통과 (경고 ${issues.length}개)` : `오류 ${errors.length}개`);
192
+ });
193
+ if (errors.length > 0)
194
+ process.exitCode = 1;
195
+ }
196
+ catch (e) {
197
+ fail(e);
198
+ }
199
+ }
200
+ // serve도 render와 같은 템플릿 목록으로 그려야 '+ 더 만들기' 메뉴가 사라지지 않는다
201
+ export function renderDigestFiles(slug, opts) {
202
+ return renderToFiles(slug, {
203
+ repoRoot: rootOf(opts),
204
+ inlineFrames: opts.inlineFrames,
205
+ templates: templatesOf(opts).templates,
206
+ });
207
+ }
208
+ export function digestRenderCommand(slug, opts) {
209
+ try {
210
+ const r = renderDigestFiles(slug, opts);
211
+ emit(r, opts.json, () => {
212
+ console.log(`HTML: ${r.htmlPath}`);
213
+ console.log(`마크다운: ${r.mdPath}`);
214
+ for (const w of r.warnings)
215
+ console.log(`경고: ${w}`);
216
+ });
217
+ }
218
+ catch (e) {
219
+ fail(e);
220
+ }
221
+ }
222
+ export function digestExportCommand(slug, opts) {
223
+ try {
224
+ if (!opts.md)
225
+ throw new Error('지금은 --md 내보내기만 있어요.');
226
+ const r = exportMarkdown(slug, { repoRoot: rootOf(opts), out: opts.out, report: opts.report });
227
+ emit(r, opts.json, () => console.log(`마크다운: ${r.mdPath}`));
228
+ }
229
+ catch (e) {
230
+ fail(e);
231
+ }
232
+ }
233
+ export function digestMergeCommand(slug, reportFile, opts) {
234
+ try {
235
+ let input;
236
+ try {
237
+ input = JSON.parse(readFileSync(resolve(reportFile), 'utf-8'));
238
+ }
239
+ catch (e) {
240
+ throw new Error(`리포트 파일을 못 읽었어요: ${reportFile}`, { cause: e });
241
+ }
242
+ const r = opts.extension
243
+ ? mergeExtension(rootOf(opts), slug, input, {
244
+ templates: templateMap(templatesOf(opts).templates),
245
+ })
246
+ : mergeReport(rootOf(opts), slug, input);
247
+ emit(r, opts.json, () => {
248
+ for (const i of r.issues)
249
+ console.log(`${i.severity} ${i.code} ${i.path}: ${i.message}`);
250
+ if (r.saved) {
251
+ console.log(`${r.replaced ? '바꿔 끼움' : '추가'}: ${r.key} → ${r.digestPath}`);
252
+ }
253
+ else {
254
+ console.log(`lint 오류가 있어 저장하지 않았어요: ${r.key}`);
255
+ }
256
+ });
257
+ if (!r.saved)
258
+ process.exitCode = 1;
259
+ }
260
+ catch (e) {
261
+ fail(e);
262
+ }
263
+ }
264
+ export function digestTemplatesCommand(opts) {
265
+ try {
266
+ const load = templatesOf(opts);
267
+ const list = load.templates.map(({ prompt: _prompt, ...t }) => t);
268
+ emit({ templates: list, warnings: load.warnings }, opts.json, () => {
269
+ for (const t of list) {
270
+ const tag = t.overridesBuiltin
271
+ ? ' (사용자, 기본 템플릿을 대신함)'
272
+ : t.source === 'user'
273
+ ? ' (사용자)'
274
+ : '';
275
+ console.log(`${t.id}${tag} ${t.title} — ${t.description}`);
276
+ console.log(` 블록: ${t.blocks.join(', ')}${t.needs.length ? ` / 먼저 받을 자료: ${t.needs.join(', ')}` : ''}`);
277
+ }
278
+ if (list.length === 0)
279
+ console.log('템플릿이 없어요.');
280
+ });
281
+ }
282
+ catch (e) {
283
+ fail(e);
284
+ }
285
+ }
286
+ /** 요약 에이전트에게 넘길 템플릿 지시를 출력한다. --json이면 frontmatter까지 함께 준다 */
287
+ export function digestTemplateCommand(id, opts) {
288
+ try {
289
+ const t = templatesOf(opts).templates.find((x) => x.id === id);
290
+ if (!t)
291
+ throw new Error(`템플릿 ${id}가 없어요. gestalt digest templates로 목록을 보세요.`);
292
+ emit(t, opts.json, () => console.log(t.prompt));
293
+ }
294
+ catch (e) {
295
+ fail(e);
296
+ }
297
+ }
298
+ export function digestSliceCommand(slug, opts) {
299
+ try {
300
+ const store = new DigestStore(rootOf(opts));
301
+ const t = store.readTranscript(slug);
302
+ if (!t.ok)
303
+ throw new Error(t.message);
304
+ const range = parseRangeArg(opts.range);
305
+ const slice = sliceTranscript(t.transcript, range);
306
+ const path = join(store.dir(slug), sliceFileName(range));
307
+ writeFileSync(path, JSON.stringify(slice, null, 2) + '\n');
308
+ const result = {
309
+ path,
310
+ range: slice.range,
311
+ from: slice.from,
312
+ to: slice.to,
313
+ count: slice.segments.length,
314
+ };
315
+ emit(result, opts.json, () => {
316
+ console.log(`구간: ${mmss(range[0])}~${mmss(range[1])} → 문장 ${slice.from}~${slice.to} (${result.count}개)`);
317
+ console.log(`저장: ${path}`);
318
+ });
319
+ }
320
+ catch (e) {
321
+ fail(e);
322
+ }
323
+ }
324
+ export function digestTranslateApplyCommand(slug, file, opts) {
325
+ try {
326
+ let input;
327
+ try {
328
+ input = JSON.parse(readFileSync(resolve(file), 'utf-8'));
329
+ }
330
+ catch (e) {
331
+ throw new Error(`번역 파일을 못 읽었어요: ${file}`, { cause: e });
332
+ }
333
+ const store = new DigestStore(rootOf(opts));
334
+ const t = store.readTranscript(slug);
335
+ if (!t.ok)
336
+ throw new Error(t.message);
337
+ const r = applyTranslation(t.transcript, input);
338
+ const path = store.saveTranscript(r.transcript);
339
+ const result = {
340
+ path,
341
+ lang: r.transcript.meta.translationLang,
342
+ applied: r.applied,
343
+ unknown: r.unknown,
344
+ missing: r.missing,
345
+ };
346
+ emit(result, opts.json, () => {
347
+ console.log(`번역(${result.lang}) ${r.applied}문장 반영 → ${path}`);
348
+ if (r.unknown.length > 0)
349
+ console.log(`스크립트에 없는 문장 번호: ${r.unknown.join(', ')}`);
350
+ if (r.missing.length > 0)
351
+ console.log(`번역이 빠진 문장: ${r.missing.length}개`);
352
+ });
353
+ }
354
+ catch (e) {
355
+ fail(e);
356
+ }
357
+ }
358
+ export function parsePort(value) {
359
+ const n = Number(value);
360
+ if (!/^\d+$/.test(value.trim()) || n < 1 || n > 65535) {
361
+ throw new Error(`포트는 1~65535 정수여야 해요: ${value}`);
362
+ }
363
+ return n;
364
+ }
365
+ export async function digestServeCommand(slug, opts) {
366
+ try {
367
+ const repoRoot = rootOf(opts);
368
+ const r = renderDigestFiles(slug, opts);
369
+ const server = new DigestServer(new DigestStore(repoRoot).root);
370
+ const port = opts.port ? parsePort(opts.port) : await findDigestPort();
371
+ try {
372
+ await server.start(port);
373
+ }
374
+ catch (e) {
375
+ if (e.code === 'EADDRINUSE') {
376
+ throw new Error(`${port}번은 이미 쓰는 포트예요. --port를 비우면 빈 곳을 찾아요.`, {
377
+ cause: e,
378
+ });
379
+ }
380
+ throw e;
381
+ }
382
+ const url = `http://127.0.0.1:${server.port}/${slug}/`;
383
+ emit({ ...r, url }, opts.json, () => {
384
+ for (const w of r.warnings)
385
+ console.log(`경고: ${w}`);
386
+ console.log(`뷰어: ${url}`);
387
+ console.log('끝내려면 Ctrl+C');
388
+ });
389
+ if (opts.browser !== false)
390
+ await openInBrowser(url);
391
+ const stop = () => {
392
+ void server.stop().finally(() => process.exit(0));
393
+ };
394
+ process.once('SIGINT', stop);
395
+ process.once('SIGTERM', stop);
396
+ }
397
+ catch (e) {
398
+ fail(e);
399
+ }
400
+ }
401
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../../../../src/cli/commands/digest.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsDpC,wBAAgB,SAAS,IAAI,OAAO,CAsdnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsEpC,wBAAgB,SAAS,IAAI,OAAO,CAokBnC"}
@@ -17,6 +17,7 @@ import { reviewLoopDirCommand, reviewLoopParseCommand, reviewLoopResolveCommand,
17
17
  import { approveGateCommand, reviewRoundsCommand } from './commands/approve-gate.js';
18
18
  import { harnessRefsClonesPruneCommand, harnessRefsCollectCommand, } from './commands/harness-refs.js';
19
19
  import { harnessRefsFollowupBuildCommand, harnessRefsFollowupCheckCommand, harnessRefsFollowupFindCommand, harnessRefsRelatedPrsCommand, harnessRefsThreeStateCommand, } from './commands/harness-refs-cross-pr.js';
20
+ import { digestCommentsCommand, digestExportCommand, digestFramesCommand, digestOcrCommand, digestScenesCommand, digestIngestCommand, digestMergeCommand, digestTemplateCommand, digestTemplatesCommand, digestSliceCommand, digestTranslateApplyCommand, digestRenderCommand, digestServeCommand, digestValidateCommand, } from './commands/digest.js';
20
21
  import { getVersion } from '../core/version.js';
21
22
  import { prCheckoutCommand, prCloseCommand, prCommentCommand, prCommentsCommand, prCreateCommand, prDiffCommand, prEditCommand, prListCommand, prMergeCommand, prReposCommand, prResolveCommand, prReviewCommand, prPruneCommand, prServeCommand, prShowCommand, prUnregisterCommand, prUpdateCommand, } from './commands/pr.js';
22
23
  export function createCli() {
@@ -173,6 +174,86 @@ export function createCli() {
173
174
  pr.command('unregister <key>')
174
175
  .description('그 레포를 웹 UI 목록에서 뺀다. 레포 자체는 안 건드린다')
175
176
  .action((key, o, cmd) => prUnregisterCommand({ ...inherited(cmd), ...o, key }));
177
+ const digest = program
178
+ .command('digest')
179
+ .description('영상 요약 — 스크립트 수집, 프레임, 뷰어')
180
+ .option('--repo-root <path>', 'Repository root (defaults to cwd)')
181
+ .option('--json', '에이전트가 파싱할 JSON으로');
182
+ const digestInherited = (cmd) => (cmd.parent?.opts() ?? {});
183
+ digest
184
+ .command('ingest <input>')
185
+ .description('유튜브 주소나 영상 파일에서 문장 단위 스크립트(transcript.json)를 만든다')
186
+ .option('--lang <code>', '자막 언어 (기본: 영상 원어)')
187
+ .option('--slug <slug>', '저장 폴더 이름 (기본: 제목과 영상 id)')
188
+ .option('--whisper', '자막이 있어도 faster-whisper로 받아쓴다')
189
+ .option('--whisper-model <name>', 'faster-whisper 모델 (기본 large-v3)')
190
+ .option('--ocr', '스크립트를 만든 뒤 화면 글자도 읽어 ocr.json에 둔다 (tesseract 필요)')
191
+ .option('--ocr-interval <sec>', '화면 글자를 읽는 간격 (기본 10초)')
192
+ .action((input, o, cmd) => digestIngestCommand(input, { ...digestInherited(cmd), ...o }));
193
+ digest
194
+ .command('ocr <slug>')
195
+ .description('일정 간격으로 프레임을 뽑아 화면 글자를 읽고 ocr.json에 둔다 (tesseract 필요)')
196
+ .option('--interval <sec>', '읽는 간격 (기본 10초)')
197
+ .option('--lang <tess>', 'tesseract 언어, kor+eng 꼴 (기본: 스크립트 언어에서 고름)')
198
+ .action((slug, o, cmd) => digestOcrCommand(slug, { ...digestInherited(cmd), ...o }));
199
+ digest
200
+ .command('scenes <slug>')
201
+ .description('shots가 고를 후보 장면을 scenes.json에 둔다. ocr.json이 있으면 화면 글자로, 없으면 장면 전환으로 고른다')
202
+ .action((slug, o, cmd) => digestScenesCommand(slug, { ...digestInherited(cmd), ...o }));
203
+ digest
204
+ .command('comments <slug>')
205
+ .description('유튜브 댓글을 인기순으로 받아 comments.json에 둔다 (작성자 정보는 저장 안 함)')
206
+ .option('--max <n>', '받을 댓글 수, 1~1000 (기본 200)')
207
+ .action((slug, o, cmd) => digestCommentsCommand(slug, { ...digestInherited(cmd), ...o }));
208
+ digest
209
+ .command('frames <slug>')
210
+ .description('digest.json의 소섹션 frameSec마다 프레임을 뽑고 shots 장면은 720p로 뽑는다')
211
+ .option('--force', '이미 뽑은 프레임도 다시 뽑는다')
212
+ .action((slug, o, cmd) => digestFramesCommand(slug, { ...digestInherited(cmd), ...o }));
213
+ digest
214
+ .command('validate <slug>')
215
+ .description('digest.json을 스키마와 lint로 검사한다')
216
+ .action((slug, o, cmd) => digestValidateCommand(slug, { ...digestInherited(cmd), ...o }));
217
+ digest
218
+ .command('render <slug>')
219
+ .description('digest.json으로 뷰어 HTML과 마크다운을 만든다')
220
+ .option('--inline-frames', '프레임을 HTML 안에 넣는다 (파일 하나로 들고 다닐 때)')
221
+ .action((slug, o, cmd) => digestRenderCommand(slug, { ...digestInherited(cmd), ...o }));
222
+ digest
223
+ .command('export <slug>')
224
+ .description('요약을 다른 형식으로 내보낸다')
225
+ .option('--md', '마크다운으로')
226
+ .option('--out <path>', '저장 경로 (기본: 첫 리포트는 digest.md, 나머지는 digest.<키>.md)')
227
+ .option('--report <key>', '내보낼 리포트 키 (기본: 첫 리포트)')
228
+ .action((slug, o, cmd) => digestExportCommand(slug, { ...digestInherited(cmd), ...o }));
229
+ digest
230
+ .command('merge <slug> <reportFile>')
231
+ .description('리포트 한 벌을 digest.json에 합친다. 같은 키면 바꿔 끼운다')
232
+ .option('--extension', '템플릿으로 만든 확장 리포트를 합친다. 템플릿과 언어가 같으면 바꿔 끼운다')
233
+ .action((slug, reportFile, o, cmd) => digestMergeCommand(slug, reportFile, { ...digestInherited(cmd), ...o }));
234
+ digest
235
+ .command('templates')
236
+ .description('확장 리포트 템플릿 목록 (기본 템플릿과 .gestalt/digest/templates/)')
237
+ .action((o, cmd) => digestTemplatesCommand({ ...digestInherited(cmd), ...o }));
238
+ digest
239
+ .command('template <id>')
240
+ .description('템플릿의 요약 지시를 출력한다. 요약 에이전트에게 그대로 넘긴다')
241
+ .action((id, o, cmd) => digestTemplateCommand(id, { ...digestInherited(cmd), ...o }));
242
+ digest
243
+ .command('slice <slug>')
244
+ .description('구간 리포트용으로 스크립트를 그 구간 문장만 잘라 저장한다. 문장 번호는 그대로 둔다')
245
+ .requiredOption('--range <from-to>', '영상 시각 구간 (예: 1:30-5:00, 90-300)')
246
+ .action((slug, o, cmd) => digestSliceCommand(slug, { ...digestInherited(cmd), ...o }));
247
+ digest
248
+ .command('translate-apply <slug> <file>')
249
+ .description('스크립트 번역({ lang, items: [{ i, translation }] })을 문장 번호로 붙인다. 언어가 바뀌면 이전 번역을 지운다')
250
+ .action((slug, file, o, cmd) => digestTranslateApplyCommand(slug, file, { ...digestInherited(cmd), ...o }));
251
+ digest
252
+ .command('serve <slug>')
253
+ .description('뷰어를 로컬 서버(127.0.0.1)로 띄운다. 유튜브 재생과 따라가기는 여기서만 된다')
254
+ .option('--port <n>', '포트 (기본: 7893부터 빈 곳)')
255
+ .option('--no-browser', '브라우저를 열지 않는다')
256
+ .action((slug, o, cmd) => digestServeCommand(slug, { ...digestInherited(cmd), ...o }));
176
257
  const reviewLoop = program
177
258
  .command('review-loop')
178
259
  .description('남의 PR 리뷰 루프가 쓰는 조회 — 판정에 쓰는 수를 여기서 낸다');