@tienne/gestalt 0.103.0 → 0.105.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 (96) hide show
  1. package/dist/package.json +1 -1
  2. package/dist/plugin/role-agents/video-summarizer/AGENT.md +75 -15
  3. package/dist/plugin/skills/_shared/proactive-routing.md +1 -1
  4. package/dist/plugin/skills/video-digest/SKILL.md +121 -49
  5. package/dist/plugin/skills/video-digest/templates/visual.md +22 -0
  6. package/dist/src/cli/commands/digest.d.ts +3 -0
  7. package/dist/src/cli/commands/digest.d.ts.map +1 -1
  8. package/dist/src/cli/commands/digest.js +34 -1
  9. package/dist/src/cli/commands/digest.js.map +1 -1
  10. package/dist/src/cli/index.d.ts.map +1 -1
  11. package/dist/src/cli/index.js +6 -2
  12. package/dist/src/cli/index.js.map +1 -1
  13. package/dist/src/digest/blocks.d.ts +3875 -504
  14. package/dist/src/digest/blocks.d.ts.map +1 -1
  15. package/dist/src/digest/blocks.js +14 -6
  16. package/dist/src/digest/blocks.js.map +1 -1
  17. package/dist/src/digest/diagram-schema.d.ts +765 -0
  18. package/dist/src/digest/diagram-schema.d.ts.map +1 -0
  19. package/dist/src/digest/diagram-schema.js +72 -0
  20. package/dist/src/digest/diagram-schema.js.map +1 -0
  21. package/dist/src/digest/frames.d.ts +21 -1
  22. package/dist/src/digest/frames.d.ts.map +1 -1
  23. package/dist/src/digest/frames.js +124 -27
  24. package/dist/src/digest/frames.js.map +1 -1
  25. package/dist/src/digest/index.d.ts +1 -0
  26. package/dist/src/digest/index.d.ts.map +1 -1
  27. package/dist/src/digest/index.js +1 -0
  28. package/dist/src/digest/index.js.map +1 -1
  29. package/dist/src/digest/lint-extension.d.ts +16 -2
  30. package/dist/src/digest/lint-extension.d.ts.map +1 -1
  31. package/dist/src/digest/lint-extension.js +122 -5
  32. package/dist/src/digest/lint-extension.js.map +1 -1
  33. package/dist/src/digest/lint.d.ts +15 -5
  34. package/dist/src/digest/lint.d.ts.map +1 -1
  35. package/dist/src/digest/lint.js +93 -50
  36. package/dist/src/digest/lint.js.map +1 -1
  37. package/dist/src/digest/merge.d.ts.map +1 -1
  38. package/dist/src/digest/merge.js +4 -1
  39. package/dist/src/digest/merge.js.map +1 -1
  40. package/dist/src/digest/ocr.d.ts +4 -0
  41. package/dist/src/digest/ocr.d.ts.map +1 -1
  42. package/dist/src/digest/ocr.js +17 -6
  43. package/dist/src/digest/ocr.js.map +1 -1
  44. package/dist/src/digest/prose.d.ts +6 -2
  45. package/dist/src/digest/prose.d.ts.map +1 -1
  46. package/dist/src/digest/prose.js +61 -2
  47. package/dist/src/digest/prose.js.map +1 -1
  48. package/dist/src/digest/render-blocks.d.ts +7 -1
  49. package/dist/src/digest/render-blocks.d.ts.map +1 -1
  50. package/dist/src/digest/render-blocks.js +107 -21
  51. package/dist/src/digest/render-blocks.js.map +1 -1
  52. package/dist/src/digest/render-html.d.ts.map +1 -1
  53. package/dist/src/digest/render-html.js +62 -17
  54. package/dist/src/digest/render-html.js.map +1 -1
  55. package/dist/src/digest/render-md.d.ts.map +1 -1
  56. package/dist/src/digest/render-md.js +15 -2
  57. package/dist/src/digest/render-md.js.map +1 -1
  58. package/dist/src/digest/render.d.ts.map +1 -1
  59. package/dist/src/digest/render.js +4 -1
  60. package/dist/src/digest/render.js.map +1 -1
  61. package/dist/src/digest/reports.d.ts +9 -1
  62. package/dist/src/digest/reports.d.ts.map +1 -1
  63. package/dist/src/digest/reports.js +24 -1
  64. package/dist/src/digest/reports.js.map +1 -1
  65. package/dist/src/digest/scenes.d.ts +92 -0
  66. package/dist/src/digest/scenes.d.ts.map +1 -0
  67. package/dist/src/digest/scenes.js +182 -0
  68. package/dist/src/digest/scenes.js.map +1 -0
  69. package/dist/src/digest/schema.d.ts +10458 -3285
  70. package/dist/src/digest/schema.d.ts.map +1 -1
  71. package/dist/src/digest/schema.js +16 -30
  72. package/dist/src/digest/schema.js.map +1 -1
  73. package/dist/src/digest/svg.d.ts +30 -0
  74. package/dist/src/digest/svg.d.ts.map +1 -1
  75. package/dist/src/digest/svg.js +151 -0
  76. package/dist/src/digest/svg.js.map +1 -1
  77. package/dist/src/digest/viewer-js.d.ts.map +1 -1
  78. package/dist/src/digest/viewer-js.js +85 -51
  79. package/dist/src/digest/viewer-js.js.map +1 -1
  80. package/dist/src/digest/viewer-logic.d.ts +22 -5
  81. package/dist/src/digest/viewer-logic.d.ts.map +1 -1
  82. package/dist/src/digest/viewer-logic.js +23 -4
  83. package/dist/src/digest/viewer-logic.js.map +1 -1
  84. package/dist/src/mcp/schemas.js +1 -1
  85. package/dist/src/mcp/schemas.js.map +1 -1
  86. package/dist/src/mcp/tools/digest-passthrough.d.ts.map +1 -1
  87. package/dist/src/mcp/tools/digest-passthrough.js +3 -0
  88. package/dist/src/mcp/tools/digest-passthrough.js.map +1 -1
  89. package/package.json +1 -1
  90. package/plugin/.codex-plugin/plugin.json +1 -1
  91. package/plugin/.mcp.json +1 -1
  92. package/plugin/mcp.json +1 -1
  93. package/plugin/role-agents/video-summarizer/AGENT.md +75 -15
  94. package/plugin/skills/_shared/proactive-routing.md +1 -1
  95. package/plugin/skills/video-digest/SKILL.md +121 -49
  96. package/plugin/skills/video-digest/templates/visual.md +22 -0
@@ -0,0 +1,182 @@
1
+ import { existsSync, mkdtempSync, rmSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { z } from 'zod';
5
+ import { writeJsonAtomic } from '../core/json-file.js';
6
+ import { ensureVideo, parseShowinfo } from './frames.js';
7
+ import { OCR_FILE, ocrFileSchema } from './ocr.js';
8
+ import { DigestStore, readRaw } from './store.js';
9
+ import { findSegmentIndex } from './viewer-logic.js';
10
+ import { runCommand, timeoutFor } from './ytdlp.js';
11
+ /**
12
+ * 소섹션 shots가 고를 수 있는 후보 장면. 슬라이드가 넘어가거나 화면이 바뀐 시각이다.
13
+ * 요약 작성자는 장면을 보지 못하니 OCR 글자 앞부분을 붙여 무엇이 화면에 있었는지 짐작하게 한다
14
+ */
15
+ export const SCENES_FILE = 'scenes.json';
16
+ /** 이보다 글자가 적은 화면은 사람 얼굴이나 자막 한 줄일 때가 많아 슬라이드로 보지 않는다 */
17
+ export const SCENE_MIN_CHARS = 40;
18
+ /** 앞 항목과 단어가 이 비율보다 많이 달라야 다른 화면으로 본다 */
19
+ export const SCENE_CHANGE_RATIO = 0.5;
20
+ /** ffmpeg 장면 전환 점수 문턱 */
21
+ export const SCENE_THRESHOLD = 0.4;
22
+ // 대담 영상은 카메라가 몇 초마다 바뀌어서 장면 전환이 수백 번 잡힌다. 간격과 개수를 묶어 목록이 요약 입력을 덮지 않게 한다
23
+ export const SCENE_MIN_GAP_SEC = 3;
24
+ export const MAX_SCENES = 300;
25
+ const TEXT_HEAD = 80;
26
+ export const scenesFileSchema = z.object({
27
+ source: z.enum(['ocr', 'scene']),
28
+ items: z
29
+ .array(z.object({
30
+ sec: z.number().nonnegative(),
31
+ i: z.number().int().nonnegative(),
32
+ text: z.string().optional(),
33
+ }))
34
+ .max(MAX_SCENES),
35
+ /** 상한을 넘어 솎았을 때만 있다. 솎기 전 후보 수다 */
36
+ total: z.number().int().nonnegative().optional(),
37
+ });
38
+ const squash = (text) => text.replace(/\s+/g, '').toLowerCase();
39
+ const NO_SPACE_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u;
40
+ // 단어로 견준다. 두 글자 조각으로 견주면 영어 슬라이드끼리 흔한 조각이 겹쳐 다른 화면도 비슷하게 나온다.
41
+ // 띄어쓰기가 없는 중국어와 일본어 덩어리만 두 글자 조각으로 쪼갠다
42
+ function tokens(text) {
43
+ const out = new Set();
44
+ for (const word of text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? []) {
45
+ if (word.length <= 2 || !NO_SPACE_SCRIPT.test(word)) {
46
+ out.add(word);
47
+ continue;
48
+ }
49
+ for (let k = 0; k + 1 < word.length; k++)
50
+ out.add(word.slice(k, k + 2));
51
+ }
52
+ return out;
53
+ }
54
+ /** cur의 단어 가운데 prev에 없는 비율. 0이면 같은 화면, 1이면 전혀 다른 화면이다 */
55
+ export function textChange(prev, cur) {
56
+ const a = tokens(prev);
57
+ const b = tokens(cur);
58
+ if (b.size === 0)
59
+ return 0;
60
+ let fresh = 0;
61
+ for (const g of b)
62
+ if (!a.has(g))
63
+ fresh += 1;
64
+ return fresh / b.size;
65
+ }
66
+ export function textHead(text, max = TEXT_HEAD) {
67
+ const line = text.replace(/\s+/g, ' ').trim();
68
+ return line.length <= max ? line : `${line.slice(0, max - 1)}…`;
69
+ }
70
+ /** 글자가 넉넉하고 앞 항목과 절반 넘게 다른 화면만 남긴다. 슬라이드가 넘어간 자리다 */
71
+ export function ocrScenes(ocr) {
72
+ const out = [];
73
+ let prev = '';
74
+ for (const item of ocr.items) {
75
+ const enough = squash(item.text).length >= SCENE_MIN_CHARS;
76
+ if (enough && textChange(prev, item.text) > SCENE_CHANGE_RATIO) {
77
+ out.push({ sec: item.sec, i: item.i, text: textHead(item.text) });
78
+ }
79
+ prev = item.text;
80
+ }
81
+ return out;
82
+ }
83
+ /** 앞 후보와 minGap초 안에 붙은 전환은 버린다. 카메라가 연달아 바뀌는 자리는 하나만 남는다 */
84
+ export function thinSceneTimes(secs, minGap = SCENE_MIN_GAP_SEC) {
85
+ const out = [];
86
+ for (const sec of [...secs].sort((a, b) => a - b)) {
87
+ const last = out[out.length - 1];
88
+ if (last === undefined || sec - last >= minGap)
89
+ out.push(sec);
90
+ }
91
+ return out;
92
+ }
93
+ /** 시간순 후보가 max개를 넘으면 처음과 끝을 포함해 고르게 솎는다. 앞에서 자르면 영상 뒷부분 장면이 통째로 빠진다 */
94
+ export function spreadEvenly(items, max = MAX_SCENES) {
95
+ if (items.length <= max)
96
+ return [...items];
97
+ if (max <= 1)
98
+ return items.slice(0, max);
99
+ return Array.from({ length: max }, (_, k) => items[Math.round((k * (items.length - 1)) / (max - 1))]);
100
+ }
101
+ function scenesFile(source, all) {
102
+ const items = spreadEvenly(all);
103
+ return items.length < all.length ? { source, items, total: all.length } : { source, items };
104
+ }
105
+ export function readScenes(store, slug) {
106
+ const raw = readRaw(join(store.dir(slug), SCENES_FILE));
107
+ if (raw.kind === 'missing')
108
+ return raw;
109
+ if (raw.kind === 'invalid-json')
110
+ return { kind: 'invalid', message: raw.message };
111
+ const parsed = scenesFileSchema.safeParse(raw.value);
112
+ if (!parsed.success) {
113
+ const issues = parsed.error.issues
114
+ .slice(0, 3)
115
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`);
116
+ return { kind: 'invalid', message: issues.join('; ') };
117
+ }
118
+ return { kind: 'ok', value: parsed.data };
119
+ }
120
+ /** lint가 받는 꼴. 파일이 없거나 깨졌으면 null이다 */
121
+ export function sceneSecs(store, slug) {
122
+ const r = readScenes(store, slug);
123
+ return r.kind === 'ok' ? r.value.items.map((s) => s.sec) : null;
124
+ }
125
+ function readOcr(store, slug) {
126
+ const path = join(store.dir(slug), OCR_FILE);
127
+ if (!existsSync(path))
128
+ return null;
129
+ const raw = readRaw(path);
130
+ if (raw.kind !== 'ok')
131
+ return null;
132
+ const parsed = ocrFileSchema.safeParse(raw.value);
133
+ return parsed.success ? parsed.data : null;
134
+ }
135
+ function saveScenes(path, file) {
136
+ writeJsonAtomic(path, file);
137
+ const total = file.total ?? file.items.length;
138
+ return {
139
+ path,
140
+ source: file.source,
141
+ items: file.items.length,
142
+ total,
143
+ truncated: total > file.items.length,
144
+ };
145
+ }
146
+ /**
147
+ * 후보 장면을 scenes.json에 둔다. ocr.json이 있으면 글자로 고르고 없으면 ffmpeg 장면 전환을 쓴다.
148
+ * 장면 전환만으로는 슬라이드인지 얼굴인지 못 가려서 글자가 있으면 글자를 먼저 쓴다
149
+ */
150
+ export async function pickScenes(slug, opts) {
151
+ const store = new DigestStore(opts.repoRoot);
152
+ const t = store.readTranscript(slug);
153
+ if (!t.ok)
154
+ throw new Error(t.message);
155
+ const transcript = t.transcript;
156
+ const path = join(store.dir(slug), SCENES_FILE);
157
+ const ocr = readOcr(store, slug);
158
+ if (ocr) {
159
+ return saveScenes(path, scenesFile('ocr', ocrScenes(ocr)));
160
+ }
161
+ const run = opts.run ?? runCommand;
162
+ const cwd = mkdtempSync(join(tmpdir(), 'gestalt-digest-scenes-'));
163
+ try {
164
+ const video = await ensureVideo(run, transcript, store.videoCacheDir(slug), cwd);
165
+ // 점수만 보면 되니 작게 줄여서 디코딩을 가볍게 한다
166
+ const { stderr } = await run('ffmpeg', [
167
+ ...['-hide_banner', '-nostats', '-i', video, '-an'],
168
+ ...['-vf', `scale=320:-2,select='gt(scene,${SCENE_THRESHOLD})',showinfo`],
169
+ ...['-f', 'null', '-'],
170
+ ], { cwd, timeoutMs: timeoutFor(transcript.meta.durationSec, 0.5) });
171
+ const starts = transcript.segments.map((s) => s.startSec);
172
+ const items = thinSceneTimes(parseShowinfo(stderr)).map((raw) => {
173
+ const sec = Math.round(raw * 100) / 100;
174
+ return { sec, i: Math.max(0, findSegmentIndex(starts, sec)) };
175
+ });
176
+ return saveScenes(path, scenesFile('scene', items));
177
+ }
178
+ finally {
179
+ rmSync(cwd, { recursive: true, force: true });
180
+ }
181
+ }
182
+ //# sourceMappingURL=scenes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenes.js","sourceRoot":"","sources":["../../../src/digest/scenes.ts"],"names":[],"mappings":"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"}