@tienne/gestalt 0.107.0 → 0.109.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 (219) hide show
  1. package/CLAUDE.md +2 -0
  2. package/README.ko.md +1 -0
  3. package/README.md +1 -0
  4. package/dist/package.json +1 -1
  5. package/dist/plugin/role-agents/lens-context/AGENT.md +94 -0
  6. package/dist/plugin/role-agents/lens-link/AGENT.md +83 -0
  7. package/dist/plugin/role-agents/lens-reader/AGENT.md +230 -0
  8. package/dist/plugin/skills/_shared/proactive-routing.md +1 -0
  9. package/dist/plugin/skills/lens/SKILL.md +375 -0
  10. package/dist/schemas/gestalt.schema.json +13 -0
  11. package/dist/src/cli/commands/digest.d.ts +2 -0
  12. package/dist/src/cli/commands/digest.d.ts.map +1 -1
  13. package/dist/src/cli/commands/digest.js +6 -0
  14. package/dist/src/cli/commands/digest.js.map +1 -1
  15. package/dist/src/cli/commands/lens.d.ts +27 -0
  16. package/dist/src/cli/commands/lens.d.ts.map +1 -0
  17. package/dist/src/cli/commands/lens.js +200 -0
  18. package/dist/src/cli/commands/lens.js.map +1 -0
  19. package/dist/src/cli/commands/peer.d.ts +19 -0
  20. package/dist/src/cli/commands/peer.d.ts.map +1 -0
  21. package/dist/src/cli/commands/peer.js +147 -0
  22. package/dist/src/cli/commands/peer.js.map +1 -0
  23. package/dist/src/cli/index.d.ts.map +1 -1
  24. package/dist/src/cli/index.js +72 -2
  25. package/dist/src/cli/index.js.map +1 -1
  26. package/dist/src/digest/format.d.ts.map +1 -1
  27. package/dist/src/digest/format.js +1 -0
  28. package/dist/src/digest/format.js.map +1 -1
  29. package/dist/src/digest/frames.d.ts.map +1 -1
  30. package/dist/src/digest/frames.js +1 -1
  31. package/dist/src/digest/frames.js.map +1 -1
  32. package/dist/src/digest/ingest.d.ts +8 -1
  33. package/dist/src/digest/ingest.d.ts.map +1 -1
  34. package/dist/src/digest/ingest.js +2 -1
  35. package/dist/src/digest/ingest.js.map +1 -1
  36. package/dist/src/digest/lens-schema.d.ts +542 -0
  37. package/dist/src/digest/lens-schema.d.ts.map +1 -0
  38. package/dist/src/digest/lens-schema.js +108 -0
  39. package/dist/src/digest/lens-schema.js.map +1 -0
  40. package/dist/src/digest/lens-source.d.ts +260 -0
  41. package/dist/src/digest/lens-source.d.ts.map +1 -0
  42. package/dist/src/digest/lens-source.js +92 -0
  43. package/dist/src/digest/lens-source.js.map +1 -0
  44. package/dist/src/digest/lens-widget-schema.d.ts +1225 -0
  45. package/dist/src/digest/lens-widget-schema.d.ts.map +1 -0
  46. package/dist/src/digest/lens-widget-schema.js +80 -0
  47. package/dist/src/digest/lens-widget-schema.js.map +1 -0
  48. package/dist/src/digest/lens-widgets.d.ts +25 -0
  49. package/dist/src/digest/lens-widgets.d.ts.map +1 -0
  50. package/dist/src/digest/lens-widgets.js +225 -0
  51. package/dist/src/digest/lens-widgets.js.map +1 -0
  52. package/dist/src/digest/lint-lens-context.d.ts +102 -0
  53. package/dist/src/digest/lint-lens-context.d.ts.map +1 -0
  54. package/dist/src/digest/lint-lens-context.js +192 -0
  55. package/dist/src/digest/lint-lens-context.js.map +1 -0
  56. package/dist/src/digest/lint-lens.d.ts +17 -0
  57. package/dist/src/digest/lint-lens.d.ts.map +1 -0
  58. package/dist/src/digest/lint-lens.js +237 -0
  59. package/dist/src/digest/lint-lens.js.map +1 -0
  60. package/dist/src/digest/lint.d.ts +14 -0
  61. package/dist/src/digest/lint.d.ts.map +1 -1
  62. package/dist/src/digest/lint.js +156 -2
  63. package/dist/src/digest/lint.js.map +1 -1
  64. package/dist/src/digest/merge.d.ts.map +1 -1
  65. package/dist/src/digest/merge.js +11 -2
  66. package/dist/src/digest/merge.js.map +1 -1
  67. package/dist/src/digest/prose.d.ts.map +1 -1
  68. package/dist/src/digest/prose.js +8 -0
  69. package/dist/src/digest/prose.js.map +1 -1
  70. package/dist/src/digest/render-html.d.ts +5 -0
  71. package/dist/src/digest/render-html.d.ts.map +1 -1
  72. package/dist/src/digest/render-html.js +93 -18
  73. package/dist/src/digest/render-html.js.map +1 -1
  74. package/dist/src/digest/render-lens.d.ts +61 -0
  75. package/dist/src/digest/render-lens.d.ts.map +1 -0
  76. package/dist/src/digest/render-lens.js +273 -0
  77. package/dist/src/digest/render-lens.js.map +1 -0
  78. package/dist/src/digest/render-md.d.ts +5 -0
  79. package/dist/src/digest/render-md.d.ts.map +1 -1
  80. package/dist/src/digest/render-md.js +116 -7
  81. package/dist/src/digest/render-md.js.map +1 -1
  82. package/dist/src/digest/render-widgets.d.ts +13 -0
  83. package/dist/src/digest/render-widgets.d.ts.map +1 -0
  84. package/dist/src/digest/render-widgets.js +197 -0
  85. package/dist/src/digest/render-widgets.js.map +1 -0
  86. package/dist/src/digest/render.d.ts +2 -0
  87. package/dist/src/digest/render.d.ts.map +1 -1
  88. package/dist/src/digest/render.js +17 -3
  89. package/dist/src/digest/render.js.map +1 -1
  90. package/dist/src/digest/schema.d.ts +14683 -2022
  91. package/dist/src/digest/schema.d.ts.map +1 -1
  92. package/dist/src/digest/schema.js +67 -6
  93. package/dist/src/digest/schema.js.map +1 -1
  94. package/dist/src/digest/server.d.ts +2 -1
  95. package/dist/src/digest/server.d.ts.map +1 -1
  96. package/dist/src/digest/server.js +26 -11
  97. package/dist/src/digest/server.js.map +1 -1
  98. package/dist/src/digest/viewer-js.d.ts.map +1 -1
  99. package/dist/src/digest/viewer-js.js +120 -4
  100. package/dist/src/digest/viewer-js.js.map +1 -1
  101. package/dist/src/lens/attach.d.ts +436 -0
  102. package/dist/src/lens/attach.d.ts.map +1 -0
  103. package/dist/src/lens/attach.js +46 -0
  104. package/dist/src/lens/attach.js.map +1 -0
  105. package/dist/src/lens/ingest.d.ts +75 -0
  106. package/dist/src/lens/ingest.d.ts.map +1 -0
  107. package/dist/src/lens/ingest.js +558 -0
  108. package/dist/src/lens/ingest.js.map +1 -0
  109. package/dist/src/lens/kind.d.ts +11 -0
  110. package/dist/src/lens/kind.d.ts.map +1 -0
  111. package/dist/src/lens/kind.js +59 -0
  112. package/dist/src/lens/kind.js.map +1 -0
  113. package/dist/src/lens/knowledge.d.ts +53 -0
  114. package/dist/src/lens/knowledge.d.ts.map +1 -0
  115. package/dist/src/lens/knowledge.js +202 -0
  116. package/dist/src/lens/knowledge.js.map +1 -0
  117. package/dist/src/lens/notes.d.ts +73 -0
  118. package/dist/src/lens/notes.d.ts.map +1 -0
  119. package/dist/src/lens/notes.js +276 -0
  120. package/dist/src/lens/notes.js.map +1 -0
  121. package/dist/src/lens/panels.d.ts +10 -0
  122. package/dist/src/lens/panels.d.ts.map +1 -0
  123. package/dist/src/lens/panels.js +25 -0
  124. package/dist/src/lens/panels.js.map +1 -0
  125. package/dist/src/lens/pdf-extract-py.d.ts +15 -0
  126. package/dist/src/lens/pdf-extract-py.d.ts.map +1 -0
  127. package/dist/src/lens/pdf-extract-py.js +414 -0
  128. package/dist/src/lens/pdf-extract-py.js.map +1 -0
  129. package/dist/src/lens/podcast.d.ts +36 -0
  130. package/dist/src/lens/podcast.d.ts.map +1 -0
  131. package/dist/src/lens/podcast.js +104 -0
  132. package/dist/src/lens/podcast.js.map +1 -0
  133. package/dist/src/lens/python.d.ts +33 -0
  134. package/dist/src/lens/python.d.ts.map +1 -0
  135. package/dist/src/lens/python.js +61 -0
  136. package/dist/src/lens/python.js.map +1 -0
  137. package/dist/src/lens/web-extract-py.d.ts +9 -0
  138. package/dist/src/lens/web-extract-py.d.ts.map +1 -0
  139. package/dist/src/lens/web-extract-py.js +114 -0
  140. package/dist/src/lens/web-extract-py.js.map +1 -0
  141. package/dist/src/mcp/schemas.d.ts +3 -0
  142. package/dist/src/mcp/schemas.d.ts.map +1 -1
  143. package/dist/src/mcp/schemas.js +4 -0
  144. package/dist/src/mcp/schemas.js.map +1 -1
  145. package/dist/src/mcp/server.js +1 -1
  146. package/dist/src/mcp/server.js.map +1 -1
  147. package/dist/src/mcp/tools/digest-passthrough.d.ts.map +1 -1
  148. package/dist/src/mcp/tools/digest-passthrough.js +5 -0
  149. package/dist/src/mcp/tools/digest-passthrough.js.map +1 -1
  150. package/dist/src/peer/client.d.ts +9 -0
  151. package/dist/src/peer/client.d.ts.map +1 -0
  152. package/dist/src/peer/client.js +51 -0
  153. package/dist/src/peer/client.js.map +1 -0
  154. package/dist/src/peer/daemon.d.ts +71 -0
  155. package/dist/src/peer/daemon.d.ts.map +1 -0
  156. package/dist/src/peer/daemon.js +407 -0
  157. package/dist/src/peer/daemon.js.map +1 -0
  158. package/dist/src/peer/errors.d.ts +2 -0
  159. package/dist/src/peer/errors.d.ts.map +1 -0
  160. package/dist/src/peer/errors.js +4 -0
  161. package/dist/src/peer/errors.js.map +1 -0
  162. package/dist/src/peer/index.d.ts +14 -0
  163. package/dist/src/peer/index.d.ts.map +1 -0
  164. package/dist/src/peer/index.js +9 -0
  165. package/dist/src/peer/index.js.map +1 -0
  166. package/dist/src/peer/locate.d.ts +44 -0
  167. package/dist/src/peer/locate.d.ts.map +1 -0
  168. package/dist/src/peer/locate.js +116 -0
  169. package/dist/src/peer/locate.js.map +1 -0
  170. package/dist/src/peer/paths.d.ts +23 -0
  171. package/dist/src/peer/paths.d.ts.map +1 -0
  172. package/dist/src/peer/paths.js +50 -0
  173. package/dist/src/peer/paths.js.map +1 -0
  174. package/dist/src/peer/protocol.d.ts +61 -0
  175. package/dist/src/peer/protocol.d.ts.map +1 -0
  176. package/dist/src/peer/protocol.js +7 -0
  177. package/dist/src/peer/protocol.js.map +1 -0
  178. package/dist/src/peer/redact.d.ts +30 -0
  179. package/dist/src/peer/redact.d.ts.map +1 -0
  180. package/dist/src/peer/redact.js +214 -0
  181. package/dist/src/peer/redact.js.map +1 -0
  182. package/dist/src/peer/share.d.ts +123 -0
  183. package/dist/src/peer/share.d.ts.map +1 -0
  184. package/dist/src/peer/share.js +204 -0
  185. package/dist/src/peer/share.js.map +1 -0
  186. package/dist/src/peer/state.d.ts +37 -0
  187. package/dist/src/peer/state.d.ts.map +1 -0
  188. package/dist/src/peer/state.js +99 -0
  189. package/dist/src/peer/state.js.map +1 -0
  190. package/dist/src/peer/tail.d.ts +55 -0
  191. package/dist/src/peer/tail.d.ts.map +1 -0
  192. package/dist/src/peer/tail.js +148 -0
  193. package/dist/src/peer/tail.js.map +1 -0
  194. package/dist/src/peer/transform.d.ts +79 -0
  195. package/dist/src/peer/transform.d.ts.map +1 -0
  196. package/dist/src/peer/transform.js +237 -0
  197. package/dist/src/peer/transform.js.map +1 -0
  198. package/dist/src/peer/viewer-html.d.ts +10 -0
  199. package/dist/src/peer/viewer-html.d.ts.map +1 -0
  200. package/dist/src/peer/viewer-html.js +157 -0
  201. package/dist/src/peer/viewer-html.js.map +1 -0
  202. package/dist/src/peer/viewer.d.ts +58 -0
  203. package/dist/src/peer/viewer.d.ts.map +1 -0
  204. package/dist/src/peer/viewer.js +249 -0
  205. package/dist/src/peer/viewer.js.map +1 -0
  206. package/dist/src/research/source-create.d.ts +6 -1
  207. package/dist/src/research/source-create.d.ts.map +1 -1
  208. package/dist/src/research/source-create.js +41 -10
  209. package/dist/src/research/source-create.js.map +1 -1
  210. package/package.json +1 -1
  211. package/plugin/.codex-plugin/plugin.json +1 -1
  212. package/plugin/.mcp.json +1 -1
  213. package/plugin/mcp.json +1 -1
  214. package/plugin/role-agents/lens-context/AGENT.md +94 -0
  215. package/plugin/role-agents/lens-link/AGENT.md +83 -0
  216. package/plugin/role-agents/lens-reader/AGENT.md +230 -0
  217. package/plugin/skills/_shared/proactive-routing.md +1 -0
  218. package/plugin/skills/lens/SKILL.md +375 -0
  219. package/schemas/gestalt.schema.json +13 -0
@@ -0,0 +1,558 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lookup as dnsLookup } from 'node:dns/promises';
3
+ import { closeSync, cpSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, renameSync, rmSync, writeSync, } from 'node:fs';
4
+ import { isIP } from 'node:net';
5
+ import { tmpdir } from 'node:os';
6
+ import { basename, dirname, extname, join, resolve } from 'node:path';
7
+ import { pathToFileURL } from 'node:url';
8
+ import { log } from '../core/log.js';
9
+ import { writeJsonAtomic } from '../core/json-file.js';
10
+ import { isPrivateAddress } from '../research/source-create.js';
11
+ import { LENS_SOURCE_SCHEMA_VERSION, lensSourcePath, lensSourceSchema, } from '../digest/lens-source.js';
12
+ import { moveStaleDigest } from '../digest/ingest.js';
13
+ import { parseTranscript } from '../digest/schema.js';
14
+ import { DigestStore, isValidSlug, slugFromMeta } from '../digest/store.js';
15
+ import { CommandError, runCommand } from '../digest/ytdlp.js';
16
+ import { AUDIO_EXTS, detectLensKind, pdfUrlOf } from './kind.js';
17
+ import { PDF_EXTRACT_PY } from './pdf-extract-py.js';
18
+ import { assignSpeakers, audioExt, DIARIZE_PY, pickEpisode, PODCAST_WHISPER_PY, } from './podcast.js';
19
+ import { WEB_EXTRACT_PY } from './web-extract-py.js';
20
+ import { DIARIZE_MODELS, lensModelsDir, lensPython, missingModuleHint } from './python.js';
21
+ const MAX_DOWNLOAD_BYTES = 300 * 1024 * 1024;
22
+ const MAX_FEED_BYTES = 10 * 1024 * 1024;
23
+ const MAX_REDIRECTS = 5;
24
+ const DOWNLOAD_TIMEOUT_MS = 120_000;
25
+ const EXTRACT_TIMEOUT_MS = 600_000;
26
+ /** 이보다 긴 PDF는 추출하지 않는다. 쪽마다 그림을 그려 메모리와 디스크를 쪽 수만큼 쓴다 */
27
+ export const PDF_MAX_PAGES = 300;
28
+ const USER_AGENT = 'gestalt-lens/1.0 (+https://github.com/tienne/gestalt)';
29
+ export const shortHash = (s) => createHash('sha256').update(s).digest('hex').slice(0, 8);
30
+ /** 한글이 본문 글자의 20%를 넘으면 ko, 아니면 en으로 본다. 요약 언어가 아니라 원문 언어다 */
31
+ export function guessLang(texts) {
32
+ const all = texts.join(' ');
33
+ const letters = all.match(/[\p{L}]/gu)?.length ?? 0;
34
+ const hangul = all.match(/[가-힣]/g)?.length ?? 0;
35
+ return letters > 0 && hangul / letters > 0.2 ? 'ko' : 'en';
36
+ }
37
+ const defaultLookup = async (host) => (await dnsLookup(host, { all: true })).map((r) => r.address);
38
+ /**
39
+ * 호스트가 루프백, 링크 로컬, 사설 대역으로 풀리면 막는다. 메타데이터 주소(169.254.169.254)도 여기 걸린다.
40
+ * 검사와 연결이 DNS를 따로 풀어서 이름을 풀 때마다 주소가 바뀌는 rebinding은 막지 못한다
41
+ */
42
+ async function assertPublicHost(url, lookup) {
43
+ const parsed = new URL(url);
44
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
45
+ throw new Error(`http(s)가 아닌 주소로 넘어가서 받지 않았어요: ${url}`);
46
+ }
47
+ const host = parsed.hostname.replace(/^\[(.*)\]$/, '$1');
48
+ const addresses = isIP(host) ? [host] : await lookup(host);
49
+ if (addresses.length === 0 || addresses.some(isPrivateAddress)) {
50
+ throw new Error(`피드의 오디오 주소가 내부망을 가리켜서 받지 않았어요: ${url}`);
51
+ }
52
+ }
53
+ /**
54
+ * lookup이 있으면 리다이렉트를 직접 따라가며 홉마다 호스트를 다시 푼다.
55
+ * fetch에 맡기면 중간 주소를 못 보고 마지막 응답만 받는다
56
+ */
57
+ async function fetchFollowing(url, init, fetchImpl, lookup) {
58
+ if (!lookup)
59
+ return fetchImpl(url, { ...init, redirect: 'follow' });
60
+ let current = url;
61
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
62
+ await assertPublicHost(current, lookup);
63
+ const res = await fetchImpl(current, { ...init, redirect: 'manual' });
64
+ const location = res.headers.get('location');
65
+ if (res.status < 300 || res.status >= 400 || !location)
66
+ return res;
67
+ await res.body?.cancel().catch(() => undefined);
68
+ current = new URL(location, current).href;
69
+ }
70
+ throw new Error(`리다이렉트가 ${MAX_REDIRECTS}번을 넘어서 멈췄어요: ${url}`);
71
+ }
72
+ /** 응답 본문을 조각으로 읽는다. 누적 크기가 상한을 넘으면 연결을 끊고 멈춘다 */
73
+ async function readCapped(res, limit, tooBig, onChunk) {
74
+ if (!res.body)
75
+ return;
76
+ const reader = res.body.getReader();
77
+ let total = 0;
78
+ for (;;) {
79
+ const { done, value } = await reader.read();
80
+ if (done)
81
+ return;
82
+ total += value.byteLength;
83
+ if (total > limit) {
84
+ await reader.cancel().catch(() => undefined);
85
+ throw new Error(tooBig);
86
+ }
87
+ onChunk(value);
88
+ }
89
+ }
90
+ /**
91
+ * 주소를 받아 파일로 저장한다. 크기 상한을 넘으면 멈추고 받던 파일을 지운다.
92
+ * lookup을 넘기면 사설 주소로 가는 요청을 막는다. 피드에서 뽑은 주소처럼 사용자가 직접 고르지 않은 주소에만 쓴다
93
+ */
94
+ export async function download(url, dest, fetchImpl = fetch, opts = {}) {
95
+ const limit = opts.maxBytes ?? MAX_DOWNLOAD_BYTES;
96
+ const tooBig = `파일이 ${Math.round(limit / 1024 / 1024)}MB를 넘어요: ${url}`;
97
+ const res = await fetchFollowing(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS), headers: { 'User-Agent': USER_AGENT } }, fetchImpl, opts.lookup);
98
+ if (!res.ok) {
99
+ await res.body?.cancel().catch(() => undefined);
100
+ throw new Error(`내려받기 실패(${res.status}): ${url}`);
101
+ }
102
+ const declared = Number(res.headers.get('content-length') ?? 0);
103
+ if (declared > limit) {
104
+ await res.body?.cancel().catch(() => undefined);
105
+ throw new Error(tooBig);
106
+ }
107
+ const fd = openSync(dest, 'w');
108
+ let complete = false;
109
+ try {
110
+ await readCapped(res, limit, tooBig, (chunk) => writeSync(fd, chunk));
111
+ complete = true;
112
+ }
113
+ finally {
114
+ closeSync(fd);
115
+ if (!complete)
116
+ rmSync(dest, { force: true });
117
+ }
118
+ return { contentType: res.headers.get('content-type') ?? '' };
119
+ }
120
+ /** 피드 XML을 받는다. 주소는 사용자가 넘긴 것이라 사설 주소를 막지 않고 크기만 묶는다 */
121
+ async function fetchFeed(url, fetchImpl) {
122
+ const res = await fetchImpl(url, {
123
+ redirect: 'follow',
124
+ signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS),
125
+ headers: { 'User-Agent': USER_AGENT },
126
+ });
127
+ if (!res.ok) {
128
+ await res.body?.cancel().catch(() => undefined);
129
+ throw new Error(`피드를 못 받았어요(${res.status}): ${url}`);
130
+ }
131
+ const chunks = [];
132
+ await readCapped(res, MAX_FEED_BYTES, `피드가 10MB를 넘어요: ${url}`, (c) => chunks.push(c));
133
+ return Buffer.concat(chunks).toString('utf-8');
134
+ }
135
+ async function runPython(run, python, script, args, cwd, timeoutMs) {
136
+ try {
137
+ // -I는 cwd와 사용자 site 경로를 import 경로에서 뺀다. 남의 레포 안 같은 이름 모듈이 대신 돌지 않게 한다
138
+ const { stdout } = await run(python, ['-I', '-c', script, ...args], { cwd, timeoutMs });
139
+ return stdout;
140
+ }
141
+ catch (e) {
142
+ const hint = e instanceof CommandError ? missingModuleHint(e.stderr) : null;
143
+ if (hint)
144
+ throw new Error(hint, { cause: e });
145
+ throw e;
146
+ }
147
+ }
148
+ function lastJsonLine(stdout, what) {
149
+ const last = stdout.trim().split('\n').pop() ?? '';
150
+ try {
151
+ return JSON.parse(last);
152
+ }
153
+ catch {
154
+ throw new Error(`${what} 결과를 JSON으로 못 읽었어요: ${stdout.trim().slice(0, 200)}`);
155
+ }
156
+ }
157
+ /** 쪽 그림과 크롭 폴더를 새로 갈아 끼운다. 다시 수집할 때 지난 크롭이 남지 않게 한다 */
158
+ function replaceAssets(from, to, dirs) {
159
+ for (const d of dirs) {
160
+ rmSync(join(to, d), { recursive: true, force: true });
161
+ if (existsSync(join(from, d)))
162
+ cpSync(join(from, d), join(to, d), { recursive: true });
163
+ }
164
+ }
165
+ function saveAll(store, transcript, source) {
166
+ const t = parseTranscript(transcript);
167
+ if (!t.ok)
168
+ throw t.error;
169
+ const s = lensSourceSchema.safeParse(source);
170
+ if (!s.success) {
171
+ throw new Error(`source.json 형식 오류: ${s.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`);
172
+ }
173
+ const staleDigest = moveStaleDigest(store, t.value);
174
+ const transcriptPath = store.saveTranscript(t.value);
175
+ const sourcePath = lensSourcePath(store, t.value.slug);
176
+ writeJsonAtomic(sourcePath, s.data);
177
+ return {
178
+ transcriptPath,
179
+ sourcePath,
180
+ transcript: t.value,
181
+ source: s.data,
182
+ ...(staleDigest ? { staleDigest } : {}),
183
+ };
184
+ }
185
+ async function ingestPdf(input, opts, work) {
186
+ const run = opts.run ?? runCommand;
187
+ const remote = /^https?:\/\//i.test(input);
188
+ const url = remote ? pdfUrlOf(input) : pathToFileURL(resolve(input)).href;
189
+ const pdfPath = join(work, 'source.pdf');
190
+ if (remote) {
191
+ await download(url, pdfPath, opts.fetchImpl);
192
+ }
193
+ else {
194
+ if (!existsSync(resolve(input)))
195
+ throw new Error(`파일이 없어요: ${input}`);
196
+ cpSync(resolve(input), pdfPath);
197
+ }
198
+ if (readFileSync(pdfPath).subarray(0, 5).toString('latin1') !== '%PDF-') {
199
+ throw new Error(`PDF가 아니에요. 웹 글이면 --kind web으로 다시 돌려 주세요: ${input}`);
200
+ }
201
+ const out = join(work, 'out');
202
+ mkdirSync(out, { recursive: true });
203
+ let stdout;
204
+ try {
205
+ stdout = await runPython(run, opts.python ?? lensPython(), PDF_EXTRACT_PY, [pdfPath, out, String(PDF_MAX_PAGES)], work, EXTRACT_TIMEOUT_MS);
206
+ }
207
+ catch (e) {
208
+ // 추출 스크립트가 쪽 수 상한에 걸리면 stderr에 정해 둔 꼴로 쪽 수를 남기고 멈춘다
209
+ const m = e instanceof CommandError ? /too-many-pages (\d+)/.exec(e.stderr) : null;
210
+ if (m) {
211
+ throw new Error(`PDF가 ${m[1]}쪽이라 한 번에 읽는 상한 ${PDF_MAX_PAGES}쪽을 넘어요. 필요한 쪽만 잘라 낸 PDF로 다시 돌려 주세요.`, { cause: e });
212
+ }
213
+ throw e;
214
+ }
215
+ const x = lastJsonLine(stdout, 'PDF 추출');
216
+ if (x.units.length === 0) {
217
+ throw new Error('PDF에서 글자를 하나도 못 뽑았어요. 스캔한 PDF면 OCR을 거친 파일로 다시 돌려 주세요.');
218
+ }
219
+ const firstHeading = x.units.find((u) => u.page === 1 && u.role === 'heading')?.text;
220
+ const title = (x.title || firstHeading || basename(input, '.pdf')).trim().slice(0, 200);
221
+ const slug = opts.slug ?? slugFromMeta(shortHash(url), title);
222
+ if (!isValidSlug(slug))
223
+ throw new Error(`slug가 올바르지 않아요: ${slug}`);
224
+ const store = new DigestStore(opts.repoRoot);
225
+ const dir = store.dir(slug);
226
+ mkdirSync(join(dir, 'cache'), { recursive: true });
227
+ replaceAssets(out, dir, ['pages', 'figures', 'tables']);
228
+ cpSync(pdfPath, join(dir, 'cache', 'source.pdf'));
229
+ const warnings = [];
230
+ const loose = x.tables.filter((t) => t.grid === 'loose').map((t) => t.id);
231
+ if (loose.length > 0) {
232
+ warnings.push(`칸 경계를 못 믿을 표: ${loose.join(', ')}. 뷰어가 원문에서 잘라낸 그림을 앞에 둬요`);
233
+ }
234
+ const noCrop = x.figures.filter((f) => !f.image).map((f) => f.id);
235
+ if (noCrop.length > 0)
236
+ warnings.push(`그림 자리를 못 찾은 그림: ${noCrop.join(', ')}`);
237
+ const saved = saveAll(store, {
238
+ slug,
239
+ meta: {
240
+ source: 'pdf',
241
+ url,
242
+ title,
243
+ durationSec: 0,
244
+ lang: guessLang(x.units.map((u) => u.text)),
245
+ captionSource: 'text',
246
+ },
247
+ segments: x.units.map((u) => ({
248
+ i: u.i,
249
+ startSec: 0,
250
+ text: u.text,
251
+ page: u.page,
252
+ role: u.role,
253
+ ...(u.ref ? { ref: u.ref } : {}),
254
+ rects: u.rects,
255
+ })),
256
+ }, {
257
+ schemaVersion: LENS_SOURCE_SCHEMA_VERSION,
258
+ slug,
259
+ kind: 'pdf',
260
+ pages: x.pages,
261
+ tables: x.tables,
262
+ figures: x.figures,
263
+ });
264
+ return {
265
+ slug,
266
+ kind: 'pdf',
267
+ title,
268
+ transcriptPath: saved.transcriptPath,
269
+ sourcePath: saved.sourcePath,
270
+ units: saved.transcript.segments.length,
271
+ pages: saved.source.pages.length,
272
+ tables: saved.source.tables.map((t) => ({ id: t.id, grid: t.grid })),
273
+ figures: saved.source.figures.map((f) => ({ id: f.id, cropped: Boolean(f.image) })),
274
+ warnings,
275
+ ...(saved.staleDigest ? { staleDigest: saved.staleDigest } : {}),
276
+ };
277
+ }
278
+ const isoDate = (s) => {
279
+ if (!s)
280
+ return undefined;
281
+ const d = new Date(s);
282
+ return Number.isNaN(d.getTime()) ? undefined : d.toISOString().slice(0, 10);
283
+ };
284
+ function hostOf(url) {
285
+ try {
286
+ return new URL(url).hostname;
287
+ }
288
+ catch {
289
+ return '';
290
+ }
291
+ }
292
+ async function ingestWeb(input, opts, work) {
293
+ const run = opts.run ?? runCommand;
294
+ const remote = /^https?:\/\//i.test(input);
295
+ if (opts.sourceUrl !== undefined && (remote || !/^https?:\/\//i.test(opts.sourceUrl))) {
296
+ throw new Error('--url은 로컬 HTML 파일과 함께, http(s) 주소로만 줄 수 있어요');
297
+ }
298
+ const url = remote ? input : (opts.sourceUrl ?? pathToFileURL(resolve(input)).href);
299
+ const htmlPath = join(work, 'page.html');
300
+ if (remote) {
301
+ const { contentType } = await download(url, htmlPath, opts.fetchImpl);
302
+ if (/application\/pdf/i.test(contentType)) {
303
+ throw new Error(`PDF를 돌려주는 주소예요. --kind pdf로 다시 돌려 주세요: ${input}`);
304
+ }
305
+ }
306
+ else {
307
+ if (!existsSync(resolve(input)))
308
+ throw new Error(`파일이 없어요: ${input}`);
309
+ cpSync(resolve(input), htmlPath);
310
+ }
311
+ const stdout = await runPython(run, opts.python ?? lensPython(), WEB_EXTRACT_PY, [htmlPath, /^https?:/i.test(url) ? url : ''], work, EXTRACT_TIMEOUT_MS);
312
+ const x = lastJsonLine(stdout, '웹 글 추출');
313
+ if (x.units.length === 0) {
314
+ throw new Error('본문을 못 찾았어요. 로그인이 필요한 페이지거나 스크립트로 그리는 페이지일 수 있어요.');
315
+ }
316
+ const title = (x.title || x.units.find((u) => u.role === 'heading')?.text || hostOf(url) || 'web')
317
+ .trim()
318
+ .slice(0, 200);
319
+ const slug = opts.slug ?? slugFromMeta(shortHash(url), title);
320
+ if (!isValidSlug(slug))
321
+ throw new Error(`slug가 올바르지 않아요: ${slug}`);
322
+ const store = new DigestStore(opts.repoRoot);
323
+ mkdirSync(join(store.dir(slug), 'cache'), { recursive: true });
324
+ cpSync(htmlPath, join(store.dir(slug), 'cache', 'page.html'));
325
+ const rescued = x.units.filter((u) => u.rescued).length;
326
+ const by = x.author || x.site || hostOf(url);
327
+ const published = isoDate(x.date);
328
+ const saved = saveAll(store, {
329
+ slug,
330
+ meta: {
331
+ source: 'web',
332
+ url,
333
+ title,
334
+ ...(by ? { channel: by } : {}),
335
+ ...(published ? { publishedAt: published } : {}),
336
+ durationSec: 0,
337
+ lang: /^[a-z]{2}$/i.test(x.lang)
338
+ ? x.lang.toLowerCase()
339
+ : guessLang(x.units.map((u) => u.text)),
340
+ captionSource: 'text',
341
+ },
342
+ segments: x.units.map((u) => ({
343
+ i: u.i,
344
+ startSec: 0,
345
+ text: u.text,
346
+ role: u.role,
347
+ ...(u.ref ? { ref: u.ref } : {}),
348
+ })),
349
+ }, { schemaVersion: LENS_SOURCE_SCHEMA_VERSION, slug, kind: 'web', tables: x.tables });
350
+ return {
351
+ slug,
352
+ kind: 'web',
353
+ title,
354
+ transcriptPath: saved.transcriptPath,
355
+ sourcePath: saved.sourcePath,
356
+ units: saved.transcript.segments.length,
357
+ pages: 0,
358
+ tables: saved.source.tables.map((t) => ({ id: t.id, grid: t.grid })),
359
+ figures: [],
360
+ warnings: rescued > 0 ? [`링크만으로 된 목록 ${rescued}개를 원문 HTML에서 되살렸어요`] : [],
361
+ ...(saved.staleDigest ? { staleDigest: saved.staleDigest } : {}),
362
+ };
363
+ }
364
+ /** 받은 파일의 sha256이 박아 둔 값과 다르면 멈춘다 */
365
+ function assertSha256(file, expected, what) {
366
+ const got = createHash('sha256').update(readFileSync(file)).digest('hex');
367
+ if (got !== expected) {
368
+ throw new Error(`${what} 파일의 해시가 맞지 않아 쓰지 않았어요(받은 값 ${got.slice(0, 12)})`);
369
+ }
370
+ }
371
+ /**
372
+ * 임시 이름으로 복사한 뒤 바꿔 단다. 복사가 끊기면 임시 파일을 지워서 모델 자리에는 끝까지 복사된 파일만 놓인다.
373
+ * copy는 테스트에서 복사 도중 실패를 흉내 낼 때 바꿔 끼운다
374
+ */
375
+ export function installModel(from, to, copy = cpSync) {
376
+ mkdirSync(dirname(to), { recursive: true });
377
+ const part = `${to}.part`;
378
+ try {
379
+ copy(from, part);
380
+ renameSync(part, to);
381
+ }
382
+ catch (e) {
383
+ rmSync(part, { force: true });
384
+ throw e;
385
+ }
386
+ }
387
+ /**
388
+ * 화자 구분 모델이 없으면 받아 둔다. 받는 곳은 sherpa-onnx의 GitHub 릴리스다.
389
+ * 받은 파일은 work에서 해시를 확인한 뒤에만 모델 폴더로 옮긴다. 이미 있는 모델은 다시 검사하지 않는다
390
+ */
391
+ async function ensureDiarizeModels(run, fetchImpl, work) {
392
+ const dir = lensModelsDir();
393
+ mkdirSync(dir, { recursive: true });
394
+ const seg = DIARIZE_MODELS.segmentation;
395
+ const emb = DIARIZE_MODELS.embedding;
396
+ const segmentation = join(dir, seg.file);
397
+ const embedding = join(dir, emb.file);
398
+ const missing = [
399
+ ...(existsSync(segmentation) ? [] : [seg.bytes]),
400
+ ...(existsSync(embedding) ? [] : [emb.bytes]),
401
+ ];
402
+ if (missing.length > 0) {
403
+ const mb = Math.round(missing.reduce((a, b) => a + b, 0) / 1024 / 1024);
404
+ log(`화자 구분 모델을 처음 한 번 받아요(약 ${mb}MB, sherpa-onnx GitHub 릴리스): ${dir}`);
405
+ }
406
+ if (!existsSync(segmentation)) {
407
+ const archive = join(work, 'segmentation.tar.bz2');
408
+ await download(seg.archive, archive, fetchImpl);
409
+ assertSha256(archive, seg.sha256, '구간 분할 모델');
410
+ const unpacked = join(work, 'segmentation');
411
+ mkdirSync(unpacked, { recursive: true });
412
+ await run('tar', ['xjf', archive, '--no-same-owner', '-C', unpacked], {
413
+ cwd: work,
414
+ timeoutMs: DOWNLOAD_TIMEOUT_MS,
415
+ });
416
+ installModel(join(unpacked, seg.file), segmentation);
417
+ }
418
+ if (!existsSync(embedding)) {
419
+ const fetched = join(work, 'embedding.onnx');
420
+ await download(emb.url, fetched, fetchImpl);
421
+ assertSha256(fetched, emb.sha256, '화자 임베딩 모델');
422
+ installModel(fetched, embedding);
423
+ }
424
+ return { segmentation, embedding };
425
+ }
426
+ /** 같은 화자로 묶는 거리 기준. 낮추면 화자가 더 잘게 갈린다. sherpa-onnx 예제의 기본값이다 */
427
+ const DIARIZE_THRESHOLD = 0.5;
428
+ export const DEFAULT_PODCAST_MODEL = 'small';
429
+ /**
430
+ * 팟캐스트는 오디오를 받아 faster-whisper로 받아쓰고 sherpa-onnx로 화자를 가른다. 화자 구분이 실패하면 시각만 출처로 쓴다.
431
+ * pyannote는 Hugging Face 토큰과 torch를 따로 깔아야 해서 쓰지 않는다
432
+ */
433
+ async function ingestPodcast(input, opts, work) {
434
+ const run = opts.run ?? runCommand;
435
+ const fetchImpl = opts.fetchImpl ?? fetch;
436
+ const remote = /^https?:\/\//i.test(input);
437
+ let audioUrl = input;
438
+ let title = '';
439
+ let show = '';
440
+ let pubDate;
441
+ // 오디오 확장자로 끝나는 주소는 바로 받고 나머지 주소는 피드로 읽는다
442
+ const isAudioUrl = remote && AUDIO_EXTS.includes(extname(new URL(input).pathname).toLowerCase());
443
+ const fromFeed = remote && !isAudioUrl;
444
+ if (fromFeed) {
445
+ const ep = pickEpisode(await fetchFeed(input, fetchImpl), opts.episode ?? 0);
446
+ audioUrl = ep.audioUrl;
447
+ title = ep.title;
448
+ show = ep.show;
449
+ pubDate = ep.pubDate;
450
+ }
451
+ const ext = audioExt(remote ? audioUrl : input);
452
+ const audioPath = join(work, `audio${ext}`);
453
+ // 피드가 적은 주소는 피드 주인이 고른 것이라 내부망으로 가는지 홉마다 본다. 사용자가 직접 넘긴 주소는 막지 않는다
454
+ if (remote) {
455
+ await download(audioUrl, audioPath, fetchImpl, fromFeed ? { lookup: opts.lookup ?? defaultLookup } : {});
456
+ }
457
+ else {
458
+ if (!existsSync(resolve(input)))
459
+ throw new Error(`파일이 없어요: ${input}`);
460
+ cpSync(resolve(input), audioPath);
461
+ }
462
+ const model = opts.whisperModel ?? DEFAULT_PODCAST_MODEL;
463
+ const stdout = await runPython(run, opts.python ?? lensPython(), PODCAST_WHISPER_PY, [audioPath, model, ''], work,
464
+ // CPU로 돌리면 오디오 길이보다 오래 걸릴 수 있다. 멈춘 프로세스만 끊을 만큼 넉넉히 둔다
465
+ 3 * 60 * 60 * 1000);
466
+ const w = lastJsonLine(stdout, '받아쓰기');
467
+ if (w.segments.length === 0)
468
+ throw new Error('받아쓴 문장이 없어요. 말소리가 없는 오디오일 수 있어요.');
469
+ // 화자 구분이 실패해도 받아쓴 문장은 살린다. 화자 없이 시각만 출처로 단다
470
+ let speakers = [];
471
+ let speakerNote;
472
+ if (opts.speakers) {
473
+ try {
474
+ const models = await ensureDiarizeModels(run, fetchImpl, work);
475
+ const out = await runPython(run, opts.python ?? lensPython(), DIARIZE_PY, [audioPath, models.segmentation, models.embedding, String(DIARIZE_THRESHOLD)], work, 3 * 60 * 60 * 1000);
476
+ speakers = assignSpeakers(w.segments, lastJsonLine(out, '화자 구분'));
477
+ const count = new Set(speakers.filter(Boolean)).size;
478
+ speakerNote = `화자 ${count}명으로 갈랐어요(sherpa-onnx). 이름은 붙이지 않았어요`;
479
+ }
480
+ catch (e) {
481
+ const reason = e instanceof Error ? e.message.split('\n')[0] : String(e);
482
+ speakerNote = `화자 구분이 실패해 시각만 출처로 달았어요: ${reason}`;
483
+ }
484
+ }
485
+ else {
486
+ speakerNote = `화자 구분 없이 시각만 출처로 달았어요(faster-whisper ${model})`;
487
+ }
488
+ const name = title || basename(input).replace(/\.[^.]+$/, '');
489
+ const slug = opts.slug ?? slugFromMeta(shortHash(audioUrl), name);
490
+ if (!isValidSlug(slug))
491
+ throw new Error(`slug가 올바르지 않아요: ${slug}`);
492
+ const store = new DigestStore(opts.repoRoot);
493
+ const cacheDir = join(store.dir(slug), 'cache');
494
+ mkdirSync(cacheDir, { recursive: true });
495
+ const kept = join(cacheDir, `audio${ext}`);
496
+ cpSync(audioPath, kept);
497
+ let prev = 0;
498
+ const published = isoDate(pubDate);
499
+ const saved = saveAll(store, {
500
+ slug,
501
+ meta: {
502
+ source: 'podcast',
503
+ url: remote ? input : pathToFileURL(resolve(input)).href,
504
+ media: pathToFileURL(kept).href,
505
+ title: name.slice(0, 200) || 'podcast',
506
+ ...(show ? { channel: show } : {}),
507
+ ...(published ? { publishedAt: published } : {}),
508
+ durationSec: Math.round(w.duration * 100) / 100,
509
+ lang: w.language || 'und',
510
+ captionSource: 'whisper',
511
+ },
512
+ segments: w.segments.map((s, i) => {
513
+ // VAD로 잘린 조각이 앞 시각보다 이르게 나오는 일이 있어 앞 문장에 맞춘다
514
+ prev = Math.max(prev, Math.round(s.start * 100) / 100);
515
+ const speaker = speakers[i];
516
+ return { i, startSec: prev, text: s.text, ...(speaker ? { speaker } : {}) };
517
+ }),
518
+ }, { schemaVersion: LENS_SOURCE_SCHEMA_VERSION, slug, kind: 'podcast' });
519
+ return {
520
+ slug,
521
+ kind: 'podcast',
522
+ title: saved.transcript.meta.title,
523
+ transcriptPath: saved.transcriptPath,
524
+ sourcePath: saved.sourcePath,
525
+ units: saved.transcript.segments.length,
526
+ pages: 0,
527
+ tables: [],
528
+ figures: [],
529
+ warnings: [speakerNote],
530
+ ...(saved.staleDigest ? { staleDigest: saved.staleDigest } : {}),
531
+ };
532
+ }
533
+ /**
534
+ * 읽을거리 하나를 문단 단위 원문으로 받아 `.gestalt/digest/<slug>/`에 둔다.
535
+ * transcript.json의 문장 자리에 문단이 들어가서 digest의 merge와 render, serve를 그대로 쓴다
536
+ */
537
+ export async function ingestLens(input, opts) {
538
+ const detected = opts.kind ?? detectLensKind(input);
539
+ if (detected === 'youtube') {
540
+ throw new Error('유튜브 영상은 렌즈가 아니라 video-digest로 요약해요: gestalt digest ingest');
541
+ }
542
+ if (detected === null) {
543
+ throw new Error(`자료 종류를 모르겠어요. --kind pdf|web|podcast로 알려 주세요: ${input}`);
544
+ }
545
+ // 외부 명령은 레포 밖 새 임시 폴더에서 돌린다. 파이썬이 cwd의 모듈을 먼저 읽지 않게 하려는 것이다
546
+ const work = mkdtempSync(join(tmpdir(), 'gestalt-lens-'));
547
+ try {
548
+ if (detected === 'pdf')
549
+ return await ingestPdf(input, opts, work);
550
+ if (detected === 'web')
551
+ return await ingestWeb(input, opts, work);
552
+ return await ingestPodcast(input, opts, work);
553
+ }
554
+ finally {
555
+ rmSync(work, { recursive: true, force: true });
556
+ }
557
+ }
558
+ //# sourceMappingURL=ingest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../../src/lens/ingest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { LensKind } from '../digest/schema.js';
2
+ export type DetectedKind = 'youtube' | LensKind;
3
+ export declare const AUDIO_EXTS: string[];
4
+ /**
5
+ * 렌즈가 받은 주소나 파일이 무슨 자료인지 판단한다. 유튜브는 video-digest로 넘긴다.
6
+ * 순서는 유튜브, PDF, 오디오와 피드, 나머지 웹 글이다. 로컬 파일은 확장자로만 본다
7
+ */
8
+ export declare function detectLensKind(input: string): DetectedKind | null;
9
+ /** arXiv 초록 주소는 PDF 주소로 바꾼다. 다른 주소는 그대로 둔다 */
10
+ export declare function pdfUrlOf(url: string): string;
11
+ //# sourceMappingURL=kind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kind.d.ts","sourceRoot":"","sources":["../../../src/lens/kind.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhD,eAAO,MAAM,UAAU,UAAqE,CAAC;AAuB7F;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAiBjE;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5C"}