@tienne/gestalt 0.102.0 → 0.103.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 (169) 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 +177 -113
  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 +408 -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/src/cli/commands/digest.d.ts +57 -0
  21. package/dist/src/cli/commands/digest.d.ts.map +1 -0
  22. package/dist/src/cli/commands/digest.js +368 -0
  23. package/dist/src/cli/commands/digest.js.map +1 -0
  24. package/dist/src/cli/index.d.ts.map +1 -1
  25. package/dist/src/cli/index.js +77 -0
  26. package/dist/src/cli/index.js.map +1 -1
  27. package/dist/src/digest/blocks.d.ts +1853 -0
  28. package/dist/src/digest/blocks.d.ts.map +1 -0
  29. package/dist/src/digest/blocks.js +148 -0
  30. package/dist/src/digest/blocks.js.map +1 -0
  31. package/dist/src/digest/captions.d.ts +37 -0
  32. package/dist/src/digest/captions.d.ts.map +1 -0
  33. package/dist/src/digest/captions.js +138 -0
  34. package/dist/src/digest/captions.js.map +1 -0
  35. package/dist/src/digest/comments.d.ts +113 -0
  36. package/dist/src/digest/comments.d.ts.map +1 -0
  37. package/dist/src/digest/comments.js +153 -0
  38. package/dist/src/digest/comments.js.map +1 -0
  39. package/dist/src/digest/format.d.ts +9 -0
  40. package/dist/src/digest/format.d.ts.map +1 -0
  41. package/dist/src/digest/format.js +26 -0
  42. package/dist/src/digest/format.js.map +1 -0
  43. package/dist/src/digest/frames.d.ts +26 -0
  44. package/dist/src/digest/frames.d.ts.map +1 -0
  45. package/dist/src/digest/frames.js +109 -0
  46. package/dist/src/digest/frames.js.map +1 -0
  47. package/dist/src/digest/index.d.ts +25 -0
  48. package/dist/src/digest/index.d.ts.map +1 -0
  49. package/dist/src/digest/index.js +25 -0
  50. package/dist/src/digest/index.js.map +1 -0
  51. package/dist/src/digest/ingest.d.ts +65 -0
  52. package/dist/src/digest/ingest.d.ts.map +1 -0
  53. package/dist/src/digest/ingest.js +303 -0
  54. package/dist/src/digest/ingest.js.map +1 -0
  55. package/dist/src/digest/lint-extension.d.ts +57 -0
  56. package/dist/src/digest/lint-extension.d.ts.map +1 -0
  57. package/dist/src/digest/lint-extension.js +395 -0
  58. package/dist/src/digest/lint-extension.js.map +1 -0
  59. package/dist/src/digest/lint.d.ts +40 -0
  60. package/dist/src/digest/lint.d.ts.map +1 -0
  61. package/dist/src/digest/lint.js +517 -0
  62. package/dist/src/digest/lint.js.map +1 -0
  63. package/dist/src/digest/merge.d.ts +40 -0
  64. package/dist/src/digest/merge.d.ts.map +1 -0
  65. package/dist/src/digest/merge.js +104 -0
  66. package/dist/src/digest/merge.js.map +1 -0
  67. package/dist/src/digest/ocr.d.ts +96 -0
  68. package/dist/src/digest/ocr.d.ts.map +1 -0
  69. package/dist/src/digest/ocr.js +168 -0
  70. package/dist/src/digest/ocr.js.map +1 -0
  71. package/dist/src/digest/prose.d.ts +43 -0
  72. package/dist/src/digest/prose.d.ts.map +1 -0
  73. package/dist/src/digest/prose.js +112 -0
  74. package/dist/src/digest/prose.js.map +1 -0
  75. package/dist/src/digest/render-blocks.d.ts +32 -0
  76. package/dist/src/digest/render-blocks.d.ts.map +1 -0
  77. package/dist/src/digest/render-blocks.js +292 -0
  78. package/dist/src/digest/render-blocks.js.map +1 -0
  79. package/dist/src/digest/render-html.d.ts +22 -0
  80. package/dist/src/digest/render-html.d.ts.map +1 -0
  81. package/dist/src/digest/render-html.js +466 -0
  82. package/dist/src/digest/render-html.js.map +1 -0
  83. package/dist/src/digest/render-md.d.ts +18 -0
  84. package/dist/src/digest/render-md.d.ts.map +1 -0
  85. package/dist/src/digest/render-md.js +113 -0
  86. package/dist/src/digest/render-md.js.map +1 -0
  87. package/dist/src/digest/render.d.ts +47 -0
  88. package/dist/src/digest/render.d.ts.map +1 -0
  89. package/dist/src/digest/render.js +123 -0
  90. package/dist/src/digest/render.js.map +1 -0
  91. package/dist/src/digest/reports.d.ts +26 -0
  92. package/dist/src/digest/reports.d.ts.map +1 -0
  93. package/dist/src/digest/reports.js +70 -0
  94. package/dist/src/digest/reports.js.map +1 -0
  95. package/dist/src/digest/schema-base.d.ts +31 -0
  96. package/dist/src/digest/schema-base.d.ts.map +1 -0
  97. package/dist/src/digest/schema-base.js +19 -0
  98. package/dist/src/digest/schema-base.js.map +1 -0
  99. package/dist/src/digest/schema.d.ts +5713 -0
  100. package/dist/src/digest/schema.d.ts.map +1 -0
  101. package/dist/src/digest/schema.js +229 -0
  102. package/dist/src/digest/schema.js.map +1 -0
  103. package/dist/src/digest/server.d.ts +36 -0
  104. package/dist/src/digest/server.d.ts.map +1 -0
  105. package/dist/src/digest/server.js +278 -0
  106. package/dist/src/digest/server.js.map +1 -0
  107. package/dist/src/digest/slice.d.ts +20 -0
  108. package/dist/src/digest/slice.d.ts.map +1 -0
  109. package/dist/src/digest/slice.js +48 -0
  110. package/dist/src/digest/slice.js.map +1 -0
  111. package/dist/src/digest/store.d.ts +67 -0
  112. package/dist/src/digest/store.d.ts.map +1 -0
  113. package/dist/src/digest/store.js +152 -0
  114. package/dist/src/digest/store.js.map +1 -0
  115. package/dist/src/digest/svg.d.ts +44 -0
  116. package/dist/src/digest/svg.d.ts.map +1 -0
  117. package/dist/src/digest/svg.js +264 -0
  118. package/dist/src/digest/svg.js.map +1 -0
  119. package/dist/src/digest/templates.d.ts +38 -0
  120. package/dist/src/digest/templates.d.ts.map +1 -0
  121. package/dist/src/digest/templates.js +125 -0
  122. package/dist/src/digest/templates.js.map +1 -0
  123. package/dist/src/digest/translate.d.ts +46 -0
  124. package/dist/src/digest/translate.d.ts.map +1 -0
  125. package/dist/src/digest/translate.js +50 -0
  126. package/dist/src/digest/translate.js.map +1 -0
  127. package/dist/src/digest/viewer-js.d.ts +4 -0
  128. package/dist/src/digest/viewer-js.d.ts.map +1 -0
  129. package/dist/src/digest/viewer-js.js +710 -0
  130. package/dist/src/digest/viewer-js.js.map +1 -0
  131. package/dist/src/digest/viewer-logic.d.ts +46 -0
  132. package/dist/src/digest/viewer-logic.d.ts.map +1 -0
  133. package/dist/src/digest/viewer-logic.js +89 -0
  134. package/dist/src/digest/viewer-logic.js.map +1 -0
  135. package/dist/src/digest/ytdlp.d.ts +34 -0
  136. package/dist/src/digest/ytdlp.d.ts.map +1 -0
  137. package/dist/src/digest/ytdlp.js +64 -0
  138. package/dist/src/digest/ytdlp.js.map +1 -0
  139. package/dist/src/mcp/schemas.d.ts +48 -0
  140. package/dist/src/mcp/schemas.d.ts.map +1 -1
  141. package/dist/src/mcp/schemas.js +25 -0
  142. package/dist/src/mcp/schemas.js.map +1 -1
  143. package/dist/src/mcp/server.d.ts.map +1 -1
  144. package/dist/src/mcp/server.js +7 -1
  145. package/dist/src/mcp/server.js.map +1 -1
  146. package/dist/src/mcp/tools/digest-passthrough.d.ts +3 -0
  147. package/dist/src/mcp/tools/digest-passthrough.d.ts.map +1 -0
  148. package/dist/src/mcp/tools/digest-passthrough.js +148 -0
  149. package/dist/src/mcp/tools/digest-passthrough.js.map +1 -0
  150. package/package.json +1 -1
  151. package/plugin/.codex-plugin/plugin.json +1 -1
  152. package/plugin/.mcp.json +1 -1
  153. package/plugin/mcp.json +1 -1
  154. package/plugin/role-agents/video-summarizer/AGENT.md +177 -113
  155. package/plugin/skills/_shared/proactive-routing.md +2 -1
  156. package/plugin/skills/research/references/design.md +1 -1
  157. package/plugin/skills/video-digest/SKILL.md +408 -0
  158. package/plugin/skills/video-digest/templates/background.md +15 -0
  159. package/plugin/skills/video-digest/templates/blog.md +16 -0
  160. package/plugin/skills/video-digest/templates/comments.md +19 -0
  161. package/plugin/skills/video-digest/templates/counterpoints.md +15 -0
  162. package/plugin/skills/video-digest/templates/flashcards.md +15 -0
  163. package/plugin/skills/video-digest/templates/interview.md +15 -0
  164. package/plugin/skills/video-digest/templates/meeting.md +15 -0
  165. package/plugin/skills/video-digest/templates/mindmap.md +16 -0
  166. package/plugin/skills/video-digest/templates/quiz.md +16 -0
  167. package/plugin/skills/video-digest/templates/quotes.md +16 -0
  168. package/plugin/skills/video-digest/templates/resources.md +14 -0
  169. package/plugin/skills/video-digest/templates/timestamps.md +14 -0
@@ -0,0 +1,38 @@
1
+ import { type BlockType } from './blocks.js';
2
+ /** 템플릿이 요약 전에 따로 받아 둬야 하는 자료. 없으면 스킬이 먼저 받는다 */
3
+ export declare const TEMPLATE_NEEDS: readonly ["comments"];
4
+ export interface DigestTemplate {
5
+ id: string;
6
+ title: string;
7
+ description: string;
8
+ blocks: BlockType[];
9
+ needs: (typeof TEMPLATE_NEEDS)[number][];
10
+ order: number;
11
+ /** 요약 에이전트에게 넘기는 지시. frontmatter 아래 본문이다 */
12
+ prompt: string;
13
+ source: 'builtin' | 'user';
14
+ path: string;
15
+ /** 레포의 사용자 템플릿이 같은 id의 기본 템플릿을 대신했다 */
16
+ overridesBuiltin?: boolean;
17
+ }
18
+ export interface TemplateLoad {
19
+ templates: DigestTemplate[];
20
+ warnings: string[];
21
+ }
22
+ export declare function parseTemplate(content: string, source: DigestTemplate['source'], path: string): DigestTemplate;
23
+ /**
24
+ * 기본 템플릿과 레포의 사용자 템플릿을 읽는다. 같은 id면 사용자 것이 이긴다.
25
+ * 깨진 파일은 건너뛰고 warnings에 적는다. 템플릿 하나가 깨졌다고 나머지를 못 쓰게 하지 않는다
26
+ */
27
+ export declare function loadTemplates(builtinDir: string | null, repoRoot: string): TemplateLoad;
28
+ /** 스킬 디렉토리 아래 video-digest 스킬의 기본 템플릿 자리 */
29
+ export declare const builtinTemplatesDir: (skillsDir: string) => string;
30
+ /**
31
+ * 기본 템플릿 폴더를 찾는다. config.skillsDir은 cwd에 plugin/skills가 있으면 그쪽으로 풀려서
32
+ * 남의 레포에서는 video-digest가 없을 수 있다. 그때는 패키지에 실린 폴더로 내려간다
33
+ */
34
+ export declare function findBuiltinTemplatesDir(skillsDir?: string): string | null;
35
+ export declare const loadDigestTemplates: (repoRoot: string, skillsDir?: string) => TemplateLoad;
36
+ /** lint가 받는 꼴로 바꾼다 */
37
+ export declare const templateMap: (templates: DigestTemplate[]) => Map<string, DigestTemplate>;
38
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/digest/templates.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAM5E,gDAAgD;AAChD,eAAO,MAAM,cAAc,uBAAwB,CAAC;AA2BpD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,EAChC,IAAI,EAAE,MAAM,GACX,cAAc,CAahB;AAkCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAgBvF;AAED,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,GAAI,WAAW,MAAM,KAAG,MACV,CAAC;AAK/C;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzE;AAED,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,EAAE,YAAY,MAAM,KAAG,YACd,CAAC;AAE9D,sBAAsB;AACtB,eAAO,MAAM,WAAW,GAAI,WAAW,cAAc,EAAE,KAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAC1C,CAAC"}
@@ -0,0 +1,125 @@
1
+ import { existsSync, lstatSync, readdirSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import matter from 'gray-matter';
5
+ import { z } from 'zod';
6
+ import { BLOCK_TYPES, templateIdSchema } from './blocks.js';
7
+ import { DigestStore } from './store.js';
8
+ /** 템플릿 하나는 프롬프트 한 장이라 이보다 크면 잘못 넣은 파일로 본다 */
9
+ const TEMPLATE_MAX_BYTES = 64 * 1024;
10
+ /** 템플릿이 요약 전에 따로 받아 둬야 하는 자료. 없으면 스킬이 먼저 받는다 */
11
+ export const TEMPLATE_NEEDS = ['comments'];
12
+ // src/research/source-schema.ts와 같은 이유로 js 엔진을 막는다. 사용자 폴더 파일이라도 frontmatter가 코드로 돌면 안 된다
13
+ const SAFE_MATTER_OPTIONS = {
14
+ engines: {
15
+ js: () => {
16
+ throw new Error('js frontmatter는 쓰지 않는다');
17
+ },
18
+ javascript: () => {
19
+ throw new Error('js frontmatter는 쓰지 않는다');
20
+ },
21
+ },
22
+ };
23
+ const frontmatterSchema = z.object({
24
+ id: templateIdSchema,
25
+ title: z.string().trim().min(1).max(40),
26
+ description: z.string().trim().min(1).max(200),
27
+ blocks: z
28
+ .array(z.enum(BLOCK_TYPES))
29
+ .min(1)
30
+ .transform((list) => [...new Set(list)]),
31
+ needs: z.array(z.enum(TEMPLATE_NEEDS)).default([]),
32
+ /** 탭과 메뉴에 놓이는 순서. 작을수록 앞이다 */
33
+ order: z.number().int().default(100),
34
+ });
35
+ export function parseTemplate(content, source, path) {
36
+ if (Buffer.byteLength(content, 'utf-8') > TEMPLATE_MAX_BYTES) {
37
+ throw new Error('템플릿이 64KB를 넘는다');
38
+ }
39
+ const parsed = matter(content, SAFE_MATTER_OPTIONS);
40
+ const fm = frontmatterSchema.safeParse(parsed.data);
41
+ if (!fm.success) {
42
+ const issues = fm.error.issues.map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`);
43
+ throw new Error(`frontmatter 형식 오류: ${issues.join('; ')}`);
44
+ }
45
+ const prompt = parsed.content.trim();
46
+ if (!prompt)
47
+ throw new Error('본문(요약 지시)이 비어 있다');
48
+ return { ...fm.data, prompt, source, path };
49
+ }
50
+ function readDir(dir, source, warnings) {
51
+ if (!existsSync(dir))
52
+ return [];
53
+ const out = [];
54
+ for (const name of readdirSync(dir).sort()) {
55
+ if (!name.endsWith('.md'))
56
+ continue;
57
+ const path = join(dir, name);
58
+ // 심링크는 레포 밖 파일을 템플릿 지시로 끌어올 수 있어 따라가지 않는다
59
+ const st = lstatSync(path);
60
+ if (st.isSymbolicLink()) {
61
+ warnings.push(`${path}: 심링크라 건너뛰었다`);
62
+ continue;
63
+ }
64
+ if (!st.isFile())
65
+ continue;
66
+ if (st.size > TEMPLATE_MAX_BYTES) {
67
+ warnings.push(`${path}: 템플릿이 64KB를 넘어 건너뛰었다`);
68
+ continue;
69
+ }
70
+ try {
71
+ const t = parseTemplate(readFileSync(path, 'utf-8'), source, path);
72
+ // 파일 이름과 id가 다르면 템플릿을 찾을 때 둘 중 무엇을 써야 할지 헷갈린다
73
+ if (`${t.id}.md` !== name) {
74
+ warnings.push(`${path}: 파일 이름이 id(${t.id})와 달라 건너뛰었다`);
75
+ continue;
76
+ }
77
+ out.push(t);
78
+ }
79
+ catch (e) {
80
+ warnings.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
81
+ }
82
+ }
83
+ return out;
84
+ }
85
+ /**
86
+ * 기본 템플릿과 레포의 사용자 템플릿을 읽는다. 같은 id면 사용자 것이 이긴다.
87
+ * 깨진 파일은 건너뛰고 warnings에 적는다. 템플릿 하나가 깨졌다고 나머지를 못 쓰게 하지 않는다
88
+ */
89
+ export function loadTemplates(builtinDir, repoRoot) {
90
+ const warnings = [];
91
+ const byId = new Map();
92
+ if (builtinDir)
93
+ for (const t of readDir(builtinDir, 'builtin', warnings))
94
+ byId.set(t.id, t);
95
+ for (const t of readDir(new DigestStore(repoRoot).templatesDir(), 'user', warnings)) {
96
+ if (byId.has(t.id)) {
97
+ warnings.push(`${t.path}: 기본 템플릿 ${t.id}를 대신한다`);
98
+ byId.set(t.id, { ...t, overridesBuiltin: true });
99
+ }
100
+ else {
101
+ byId.set(t.id, t);
102
+ }
103
+ }
104
+ const templates = [...byId.values()].sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
105
+ return { templates, warnings };
106
+ }
107
+ /** 스킬 디렉토리 아래 video-digest 스킬의 기본 템플릿 자리 */
108
+ export const builtinTemplatesDir = (skillsDir) => join(skillsDir, 'video-digest', 'templates');
109
+ // src/digest와 dist/digest 둘 다 두 칸 위가 패키지 루트다
110
+ const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
111
+ /**
112
+ * 기본 템플릿 폴더를 찾는다. config.skillsDir은 cwd에 plugin/skills가 있으면 그쪽으로 풀려서
113
+ * 남의 레포에서는 video-digest가 없을 수 있다. 그때는 패키지에 실린 폴더로 내려간다
114
+ */
115
+ export function findBuiltinTemplatesDir(skillsDir) {
116
+ const candidates = [
117
+ skillsDir ? builtinTemplatesDir(skillsDir) : null,
118
+ builtinTemplatesDir(join(PACKAGE_ROOT, 'plugin', 'skills')),
119
+ ];
120
+ return candidates.find((d) => d !== null && existsSync(d)) ?? null;
121
+ }
122
+ export const loadDigestTemplates = (repoRoot, skillsDir) => loadTemplates(findBuiltinTemplatesDir(skillsDir), repoRoot);
123
+ /** lint가 받는 꼴로 바꾼다 */
124
+ export const templateMap = (templates) => new Map(templates.map((t) => [t.id, t]));
125
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/digest/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod';
2
+ import { type Transcript } from './schema.js';
3
+ /**
4
+ * 스크립트 번역 한 벌. 세션이 쓰는 파일이라 영상 자막만큼 믿지 않는다.
5
+ * 번역문은 뷰어에 글자로만 나가고 HTML로 해석되지 않는다
6
+ */
7
+ export declare const translationInputSchema: z.ZodObject<{
8
+ lang: z.ZodString;
9
+ items: z.ZodArray<z.ZodObject<{
10
+ i: z.ZodNumber;
11
+ translation: z.ZodString;
12
+ }, "strip", z.ZodTypeAny, {
13
+ translation: string;
14
+ i: number;
15
+ }, {
16
+ translation: string;
17
+ i: number;
18
+ }>, "many">;
19
+ }, "strip", z.ZodTypeAny, {
20
+ items: {
21
+ translation: string;
22
+ i: number;
23
+ }[];
24
+ lang: string;
25
+ }, {
26
+ items: {
27
+ translation: string;
28
+ i: number;
29
+ }[];
30
+ lang: string;
31
+ }>;
32
+ export type TranslationInput = z.infer<typeof translationInputSchema>;
33
+ export interface TranslationResult {
34
+ transcript: Transcript;
35
+ applied: number;
36
+ /** 스크립트에 없는 문장 번호. 이 항목은 넣지 않는다 */
37
+ unknown: number[];
38
+ /** 번역이 안 붙은 문장 번호 */
39
+ missing: number[];
40
+ }
41
+ /**
42
+ * 번역을 문장 번호로 붙인다. 이미 다른 언어 번역이 붙어 있으면 통째로 갈아 끼운다.
43
+ * 언어가 섞이면 토글 하나로 어느 언어를 보는지 알 수 없어서다
44
+ */
45
+ export declare function applyTranslation(transcript: Transcript, input: unknown): TranslationResult;
46
+ //# sourceMappingURL=translate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../../../src/digest/translate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAUjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qBAAqB;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA2B1F"}
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+ import { LANG_TAG_PATTERN } from './schema.js';
3
+ /**
4
+ * 스크립트 번역 한 벌. 세션이 쓰는 파일이라 영상 자막만큼 믿지 않는다.
5
+ * 번역문은 뷰어에 글자로만 나가고 HTML로 해석되지 않는다
6
+ */
7
+ export const translationInputSchema = z.object({
8
+ lang: z.string().regex(LANG_TAG_PATTERN, '언어 태그(ko, en, pt-BR) 꼴이어야 한다'),
9
+ items: z
10
+ .array(z.object({
11
+ i: z.number().int().nonnegative(),
12
+ translation: z.string().trim().min(1).max(2000),
13
+ }))
14
+ .min(1),
15
+ });
16
+ /**
17
+ * 번역을 문장 번호로 붙인다. 이미 다른 언어 번역이 붙어 있으면 통째로 갈아 끼운다.
18
+ * 언어가 섞이면 토글 하나로 어느 언어를 보는지 알 수 없어서다
19
+ */
20
+ export function applyTranslation(transcript, input) {
21
+ const parsed = translationInputSchema.safeParse(input);
22
+ if (!parsed.success) {
23
+ const issues = parsed.error.issues
24
+ .slice(0, 3)
25
+ .map((i) => `${i.path.join('.') || '(루트)'}: ${i.message}`);
26
+ throw new Error(`번역 형식 오류: ${issues.join('; ')}`);
27
+ }
28
+ const { lang, items } = parsed.data;
29
+ const sameLang = transcript.meta.translationLang === lang;
30
+ const byIndex = new Map();
31
+ const unknown = [];
32
+ for (const item of items) {
33
+ if (item.i >= transcript.segments.length)
34
+ unknown.push(item.i);
35
+ else
36
+ byIndex.set(item.i, item.translation);
37
+ }
38
+ const segments = transcript.segments.map((s) => {
39
+ const next = byIndex.get(s.i) ?? (sameLang ? s.translation : undefined);
40
+ const { translation: _old, ...rest } = s;
41
+ return next === undefined ? rest : { ...rest, translation: next };
42
+ });
43
+ return {
44
+ transcript: { ...transcript, meta: { ...transcript.meta, translationLang: lang }, segments },
45
+ applied: byIndex.size,
46
+ unknown,
47
+ missing: segments.filter((s) => s.translation === undefined).map((s) => s.i),
48
+ };
49
+ }
50
+ //# sourceMappingURL=translate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate.js","sourceRoot":"","sources":["../../../src/digest/translate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const VIEWER_JS: string;
2
+ /** CSP script-src에 싣는 VIEWER_JS 해시. 렌더가 이 문자열을 그대로 인라인으로 싣는다 */
3
+ export declare const VIEWER_JS_SHA256: string;
4
+ //# sourceMappingURL=viewer-js.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewer-js.d.ts","sourceRoot":"","sources":["../../../src/digest/viewer-js.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,SAAS,QAgsBrB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,QAAkE,CAAC"}