@pan-sec/notebooklm-mcp 2026.3.3 → 2026.4.1

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 (470) hide show
  1. package/dist/auth/auth-manager.d.ts +0 -1
  2. package/dist/auth/auth-manager.js +0 -1
  3. package/dist/auth/mcp-auth.d.ts +0 -1
  4. package/dist/auth/mcp-auth.js +0 -1
  5. package/dist/compliance/alert-manager.d.ts +6 -2
  6. package/dist/compliance/alert-manager.js +40 -10
  7. package/dist/compliance/breach-detection.d.ts +0 -1
  8. package/dist/compliance/breach-detection.js +0 -1
  9. package/dist/compliance/change-log.d.ts +13 -1
  10. package/dist/compliance/change-log.js +82 -16
  11. package/dist/compliance/compliance-logger.d.ts +29 -3
  12. package/dist/compliance/compliance-logger.js +90 -27
  13. package/dist/compliance/compliance-tools.d.ts +0 -1
  14. package/dist/compliance/compliance-tools.js +0 -1
  15. package/dist/compliance/consent-manager.d.ts +0 -1
  16. package/dist/compliance/consent-manager.js +0 -1
  17. package/dist/compliance/dashboard.d.ts +4 -3
  18. package/dist/compliance/dashboard.js +11 -8
  19. package/dist/compliance/data-classification.d.ts +0 -1
  20. package/dist/compliance/data-classification.js +0 -1
  21. package/dist/compliance/data-erasure.d.ts +0 -1
  22. package/dist/compliance/data-erasure.js +0 -1
  23. package/dist/compliance/data-export.d.ts +0 -1
  24. package/dist/compliance/data-export.js +0 -1
  25. package/dist/compliance/data-inventory.d.ts +0 -1
  26. package/dist/compliance/data-inventory.js +0 -1
  27. package/dist/compliance/dsar-handler.d.ts +0 -1
  28. package/dist/compliance/dsar-handler.js +0 -1
  29. package/dist/compliance/evidence-collector.d.ts +0 -1
  30. package/dist/compliance/evidence-collector.js +4 -2
  31. package/dist/compliance/health-monitor.d.ts +0 -1
  32. package/dist/compliance/health-monitor.js +0 -1
  33. package/dist/compliance/incident-manager.d.ts +0 -1
  34. package/dist/compliance/incident-manager.js +0 -1
  35. package/dist/compliance/index.d.ts +0 -1
  36. package/dist/compliance/index.js +0 -1
  37. package/dist/compliance/policy-docs.d.ts +0 -1
  38. package/dist/compliance/policy-docs.js +0 -1
  39. package/dist/compliance/privacy-notice-text.d.ts +0 -1
  40. package/dist/compliance/privacy-notice-text.js +0 -1
  41. package/dist/compliance/privacy-notice.d.ts +0 -1
  42. package/dist/compliance/privacy-notice.js +0 -1
  43. package/dist/compliance/report-generator.d.ts +7 -1
  44. package/dist/compliance/report-generator.js +116 -34
  45. package/dist/compliance/retention-engine.d.ts +0 -1
  46. package/dist/compliance/retention-engine.js +0 -1
  47. package/dist/compliance/siem-exporter.d.ts +26 -2
  48. package/dist/compliance/siem-exporter.js +89 -24
  49. package/dist/compliance/types.d.ts +0 -1
  50. package/dist/compliance/types.js +0 -1
  51. package/dist/config.d.ts +0 -1
  52. package/dist/config.js +2 -3
  53. package/dist/errors.d.ts +0 -1
  54. package/dist/errors.js +0 -1
  55. package/dist/events/event-emitter.d.ts +9 -1
  56. package/dist/events/event-emitter.js +47 -8
  57. package/dist/events/event-types.d.ts +0 -1
  58. package/dist/events/event-types.js +8 -2
  59. package/dist/gemini/gemini-client.d.ts +0 -1
  60. package/dist/gemini/gemini-client.js +237 -45
  61. package/dist/gemini/index.d.ts +0 -1
  62. package/dist/gemini/index.js +0 -1
  63. package/dist/gemini/pdf-chunker.d.ts +0 -1
  64. package/dist/gemini/pdf-chunker.js +60 -35
  65. package/dist/gemini/types.d.ts +0 -1
  66. package/dist/gemini/types.js +0 -1
  67. package/dist/index.d.ts +0 -1
  68. package/dist/index.js +60 -7
  69. package/dist/library/notebook-library.d.ts +30 -2
  70. package/dist/library/notebook-library.js +345 -85
  71. package/dist/library/types.d.ts +0 -1
  72. package/dist/library/types.js +0 -1
  73. package/dist/logging/index.d.ts +0 -1
  74. package/dist/logging/index.js +0 -1
  75. package/dist/logging/query-logger.d.ts +20 -1
  76. package/dist/logging/query-logger.js +104 -21
  77. package/dist/notebook-creation/audio-manager.d.ts +7 -16
  78. package/dist/notebook-creation/audio-manager.js +115 -58
  79. package/dist/notebook-creation/browser-options.d.ts +0 -1
  80. package/dist/notebook-creation/browser-options.js +0 -1
  81. package/dist/notebook-creation/data-table-manager.d.ts +8 -14
  82. package/dist/notebook-creation/data-table-manager.js +64 -37
  83. package/dist/notebook-creation/dom-scripts.d.ts +0 -1
  84. package/dist/notebook-creation/dom-scripts.js +0 -1
  85. package/dist/notebook-creation/errors.d.ts +0 -1
  86. package/dist/notebook-creation/errors.js +0 -1
  87. package/dist/notebook-creation/index.d.ts +0 -1
  88. package/dist/notebook-creation/index.js +0 -1
  89. package/dist/notebook-creation/notebook-creator.d.ts +9 -1
  90. package/dist/notebook-creation/notebook-creator.js +50 -1
  91. package/dist/notebook-creation/notebook-nav.d.ts +0 -1
  92. package/dist/notebook-creation/notebook-nav.js +21 -6
  93. package/dist/notebook-creation/notebook-sync.d.ts +14 -2
  94. package/dist/notebook-creation/notebook-sync.js +124 -35
  95. package/dist/notebook-creation/selectors.d.ts +0 -1
  96. package/dist/notebook-creation/selectors.js +6 -4
  97. package/dist/notebook-creation/source-manager-shared.d.ts +75 -0
  98. package/dist/notebook-creation/source-manager-shared.js +86 -0
  99. package/dist/notebook-creation/source-manager.d.ts +29 -2
  100. package/dist/notebook-creation/source-manager.js +0 -0
  101. package/dist/notebook-creation/studio-manager-base.d.ts +57 -0
  102. package/dist/notebook-creation/studio-manager-base.js +67 -0
  103. package/dist/notebook-creation/types.d.ts +0 -1
  104. package/dist/notebook-creation/types.js +0 -1
  105. package/dist/notebook-creation/video-manager.d.ts +3 -16
  106. package/dist/notebook-creation/video-manager.js +94 -53
  107. package/dist/observability/metrics.d.ts +0 -1
  108. package/dist/observability/metrics.js +0 -1
  109. package/dist/quota/index.d.ts +0 -1
  110. package/dist/quota/index.js +0 -1
  111. package/dist/quota/quota-manager.d.ts +59 -4
  112. package/dist/quota/quota-manager.js +195 -46
  113. package/dist/resources/resource-handlers.d.ts +0 -1
  114. package/dist/resources/resource-handlers.js +33 -3
  115. package/dist/session/browser-session.d.ts +0 -1
  116. package/dist/session/browser-session.js +0 -1
  117. package/dist/session/session-manager.d.ts +0 -1
  118. package/dist/session/session-manager.js +0 -1
  119. package/dist/session/session-timeout.d.ts +0 -1
  120. package/dist/session/session-timeout.js +0 -1
  121. package/dist/session/shared-context-manager.d.ts +0 -1
  122. package/dist/session/shared-context-manager.js +0 -1
  123. package/dist/tools/annotations.d.ts +0 -1
  124. package/dist/tools/annotations.js +0 -1
  125. package/dist/tools/definitions/ask-question.d.ts +6 -3
  126. package/dist/tools/definitions/ask-question.js +12 -8
  127. package/dist/tools/definitions/chat-history.d.ts +0 -1
  128. package/dist/tools/definitions/chat-history.js +1 -1
  129. package/dist/tools/definitions/data-tables.d.ts +0 -1
  130. package/dist/tools/definitions/data-tables.js +4 -1
  131. package/dist/tools/definitions/gemini.d.ts +0 -1
  132. package/dist/tools/definitions/gemini.js +14 -7
  133. package/dist/tools/definitions/notebook-management.d.ts +0 -1
  134. package/dist/tools/definitions/notebook-management.js +7 -2
  135. package/dist/tools/definitions/query-history.d.ts +0 -1
  136. package/dist/tools/definitions/query-history.js +0 -1
  137. package/dist/tools/definitions/session-management.d.ts +0 -1
  138. package/dist/tools/definitions/session-management.js +0 -1
  139. package/dist/tools/definitions/system.d.ts +0 -1
  140. package/dist/tools/definitions/system.js +32 -12
  141. package/dist/tools/definitions/video.d.ts +0 -1
  142. package/dist/tools/definitions/video.js +6 -3
  143. package/dist/tools/definitions.d.ts +0 -1
  144. package/dist/tools/definitions.js +0 -1
  145. package/dist/tools/handlers/ask-question.d.ts +0 -1
  146. package/dist/tools/handlers/ask-question.js +47 -18
  147. package/dist/tools/handlers/audio-video.d.ts +0 -1
  148. package/dist/tools/handlers/audio-video.js +0 -1
  149. package/dist/tools/handlers/auth.d.ts +0 -1
  150. package/dist/tools/handlers/auth.js +0 -1
  151. package/dist/tools/handlers/error-utils.d.ts +0 -1
  152. package/dist/tools/handlers/error-utils.js +0 -1
  153. package/dist/tools/handlers/gemini.d.ts +0 -1
  154. package/dist/tools/handlers/gemini.js +0 -1
  155. package/dist/tools/handlers/index.d.ts +0 -1
  156. package/dist/tools/handlers/index.js +0 -1
  157. package/dist/tools/handlers/notebook-creation.d.ts +0 -1
  158. package/dist/tools/handlers/notebook-creation.js +16 -1
  159. package/dist/tools/handlers/notebook-management.d.ts +0 -1
  160. package/dist/tools/handlers/notebook-management.js +7 -2
  161. package/dist/tools/handlers/session-management.d.ts +0 -1
  162. package/dist/tools/handlers/session-management.js +0 -1
  163. package/dist/tools/handlers/system.d.ts +0 -1
  164. package/dist/tools/handlers/system.js +0 -1
  165. package/dist/tools/handlers/types.d.ts +0 -1
  166. package/dist/tools/handlers/types.js +0 -1
  167. package/dist/tools/handlers/webhooks.d.ts +0 -1
  168. package/dist/tools/handlers/webhooks.js +0 -1
  169. package/dist/tools/icons.d.ts +0 -1
  170. package/dist/tools/icons.js +0 -1
  171. package/dist/tools/index.d.ts +0 -1
  172. package/dist/tools/index.js +0 -1
  173. package/dist/types.d.ts +0 -1
  174. package/dist/types.js +0 -1
  175. package/dist/utils/audit-logger.d.ts +11 -1
  176. package/dist/utils/audit-logger.js +189 -21
  177. package/dist/utils/cleanup-manager.d.ts +0 -1
  178. package/dist/utils/cleanup-manager.js +0 -1
  179. package/dist/utils/cli-handler.d.ts +0 -1
  180. package/dist/utils/cli-handler.js +0 -1
  181. package/dist/utils/crypto.d.ts +18 -9
  182. package/dist/utils/crypto.js +93 -28
  183. package/dist/utils/file-lock.d.ts +15 -1
  184. package/dist/utils/file-lock.js +67 -59
  185. package/dist/utils/file-permissions.d.ts +0 -1
  186. package/dist/utils/file-permissions.js +35 -7
  187. package/dist/utils/logger.d.ts +0 -1
  188. package/dist/utils/logger.js +0 -1
  189. package/dist/utils/page-utils.d.ts +0 -1
  190. package/dist/utils/page-utils.js +32 -28
  191. package/dist/utils/response-validator.d.ts +0 -1
  192. package/dist/utils/response-validator.js +18 -15
  193. package/dist/utils/secrets-scanner.d.ts +0 -1
  194. package/dist/utils/secrets-scanner.js +32 -7
  195. package/dist/utils/secure-memory.d.ts +34 -16
  196. package/dist/utils/secure-memory.js +40 -25
  197. package/dist/utils/security.d.ts +0 -1
  198. package/dist/utils/security.js +66 -39
  199. package/dist/utils/settings-manager.d.ts +9 -1
  200. package/dist/utils/settings-manager.js +45 -2
  201. package/dist/utils/stealth-utils.d.ts +0 -1
  202. package/dist/utils/stealth-utils.js +11 -9
  203. package/dist/webhooks/index.d.ts +0 -1
  204. package/dist/webhooks/index.js +0 -1
  205. package/dist/webhooks/types.d.ts +0 -1
  206. package/dist/webhooks/types.js +0 -1
  207. package/dist/webhooks/webhook-dispatcher.d.ts +0 -1
  208. package/dist/webhooks/webhook-dispatcher.js +0 -1
  209. package/package.json +5 -4
  210. package/dist/auth/auth-manager.d.ts.map +0 -1
  211. package/dist/auth/auth-manager.js.map +0 -1
  212. package/dist/auth/mcp-auth.d.ts.map +0 -1
  213. package/dist/auth/mcp-auth.js.map +0 -1
  214. package/dist/compliance/alert-manager.d.ts.map +0 -1
  215. package/dist/compliance/alert-manager.js.map +0 -1
  216. package/dist/compliance/breach-detection.d.ts.map +0 -1
  217. package/dist/compliance/breach-detection.js.map +0 -1
  218. package/dist/compliance/change-log.d.ts.map +0 -1
  219. package/dist/compliance/change-log.js.map +0 -1
  220. package/dist/compliance/compliance-logger.d.ts.map +0 -1
  221. package/dist/compliance/compliance-logger.js.map +0 -1
  222. package/dist/compliance/compliance-tools.d.ts.map +0 -1
  223. package/dist/compliance/compliance-tools.js.map +0 -1
  224. package/dist/compliance/consent-manager.d.ts.map +0 -1
  225. package/dist/compliance/consent-manager.js.map +0 -1
  226. package/dist/compliance/dashboard.d.ts.map +0 -1
  227. package/dist/compliance/dashboard.js.map +0 -1
  228. package/dist/compliance/data-classification.d.ts.map +0 -1
  229. package/dist/compliance/data-classification.js.map +0 -1
  230. package/dist/compliance/data-erasure.d.ts.map +0 -1
  231. package/dist/compliance/data-erasure.js.map +0 -1
  232. package/dist/compliance/data-export.d.ts.map +0 -1
  233. package/dist/compliance/data-export.js.map +0 -1
  234. package/dist/compliance/data-inventory.d.ts.map +0 -1
  235. package/dist/compliance/data-inventory.js.map +0 -1
  236. package/dist/compliance/dsar-handler.d.ts.map +0 -1
  237. package/dist/compliance/dsar-handler.js.map +0 -1
  238. package/dist/compliance/evidence-collector.d.ts.map +0 -1
  239. package/dist/compliance/evidence-collector.js.map +0 -1
  240. package/dist/compliance/health-monitor.d.ts.map +0 -1
  241. package/dist/compliance/health-monitor.js.map +0 -1
  242. package/dist/compliance/incident-manager.d.ts.map +0 -1
  243. package/dist/compliance/incident-manager.js.map +0 -1
  244. package/dist/compliance/index.d.ts.map +0 -1
  245. package/dist/compliance/index.js.map +0 -1
  246. package/dist/compliance/policy-docs.d.ts.map +0 -1
  247. package/dist/compliance/policy-docs.js.map +0 -1
  248. package/dist/compliance/privacy-notice-text.d.ts.map +0 -1
  249. package/dist/compliance/privacy-notice-text.js.map +0 -1
  250. package/dist/compliance/privacy-notice.d.ts.map +0 -1
  251. package/dist/compliance/privacy-notice.js.map +0 -1
  252. package/dist/compliance/report-generator.d.ts.map +0 -1
  253. package/dist/compliance/report-generator.js.map +0 -1
  254. package/dist/compliance/retention-engine.d.ts.map +0 -1
  255. package/dist/compliance/retention-engine.js.map +0 -1
  256. package/dist/compliance/siem-exporter.d.ts.map +0 -1
  257. package/dist/compliance/siem-exporter.js.map +0 -1
  258. package/dist/compliance/types.d.ts.map +0 -1
  259. package/dist/compliance/types.js.map +0 -1
  260. package/dist/config.d.ts.map +0 -1
  261. package/dist/config.js.map +0 -1
  262. package/dist/errors.d.ts.map +0 -1
  263. package/dist/errors.js.map +0 -1
  264. package/dist/events/event-emitter.d.ts.map +0 -1
  265. package/dist/events/event-emitter.js.map +0 -1
  266. package/dist/events/event-types.d.ts.map +0 -1
  267. package/dist/events/event-types.js.map +0 -1
  268. package/dist/gemini/gemini-client.d.ts.map +0 -1
  269. package/dist/gemini/gemini-client.js.map +0 -1
  270. package/dist/gemini/index.d.ts.map +0 -1
  271. package/dist/gemini/index.js.map +0 -1
  272. package/dist/gemini/pdf-chunker.d.ts.map +0 -1
  273. package/dist/gemini/pdf-chunker.js.map +0 -1
  274. package/dist/gemini/types.d.ts.map +0 -1
  275. package/dist/gemini/types.js.map +0 -1
  276. package/dist/index.d.ts.map +0 -1
  277. package/dist/index.js.map +0 -1
  278. package/dist/library/notebook-library.d.ts.map +0 -1
  279. package/dist/library/notebook-library.js.map +0 -1
  280. package/dist/library/types.d.ts.map +0 -1
  281. package/dist/library/types.js.map +0 -1
  282. package/dist/logging/index.d.ts.map +0 -1
  283. package/dist/logging/index.js.map +0 -1
  284. package/dist/logging/query-logger.d.ts.map +0 -1
  285. package/dist/logging/query-logger.js.map +0 -1
  286. package/dist/notebook-creation/audio-manager.d.ts.map +0 -1
  287. package/dist/notebook-creation/audio-manager.js.map +0 -1
  288. package/dist/notebook-creation/browser-options.d.ts.map +0 -1
  289. package/dist/notebook-creation/browser-options.js.map +0 -1
  290. package/dist/notebook-creation/data-table-manager.d.ts.map +0 -1
  291. package/dist/notebook-creation/data-table-manager.js.map +0 -1
  292. package/dist/notebook-creation/discover-creation-flow.d.ts +0 -2
  293. package/dist/notebook-creation/discover-creation-flow.d.ts.map +0 -1
  294. package/dist/notebook-creation/discover-creation-flow.js +0 -177
  295. package/dist/notebook-creation/discover-creation-flow.js.map +0 -1
  296. package/dist/notebook-creation/discover-quota.d.ts +0 -2
  297. package/dist/notebook-creation/discover-quota.d.ts.map +0 -1
  298. package/dist/notebook-creation/discover-quota.js +0 -194
  299. package/dist/notebook-creation/discover-quota.js.map +0 -1
  300. package/dist/notebook-creation/discover-source-dialog.d.ts +0 -8
  301. package/dist/notebook-creation/discover-source-dialog.d.ts.map +0 -1
  302. package/dist/notebook-creation/discover-source-dialog.js +0 -134
  303. package/dist/notebook-creation/discover-source-dialog.js.map +0 -1
  304. package/dist/notebook-creation/discover-sources.d.ts +0 -8
  305. package/dist/notebook-creation/discover-sources.d.ts.map +0 -1
  306. package/dist/notebook-creation/discover-sources.js +0 -272
  307. package/dist/notebook-creation/discover-sources.js.map +0 -1
  308. package/dist/notebook-creation/discover-text-input.d.ts +0 -7
  309. package/dist/notebook-creation/discover-text-input.d.ts.map +0 -1
  310. package/dist/notebook-creation/discover-text-input.js +0 -135
  311. package/dist/notebook-creation/discover-text-input.js.map +0 -1
  312. package/dist/notebook-creation/dom-scripts.d.ts.map +0 -1
  313. package/dist/notebook-creation/dom-scripts.js.map +0 -1
  314. package/dist/notebook-creation/errors.d.ts.map +0 -1
  315. package/dist/notebook-creation/errors.js.map +0 -1
  316. package/dist/notebook-creation/index.d.ts.map +0 -1
  317. package/dist/notebook-creation/index.js.map +0 -1
  318. package/dist/notebook-creation/notebook-creator.d.ts.map +0 -1
  319. package/dist/notebook-creation/notebook-creator.js.map +0 -1
  320. package/dist/notebook-creation/notebook-nav.d.ts.map +0 -1
  321. package/dist/notebook-creation/notebook-nav.js.map +0 -1
  322. package/dist/notebook-creation/notebook-sync.d.ts.map +0 -1
  323. package/dist/notebook-creation/notebook-sync.js.map +0 -1
  324. package/dist/notebook-creation/run-discovery.d.ts +0 -11
  325. package/dist/notebook-creation/run-discovery.d.ts.map +0 -1
  326. package/dist/notebook-creation/run-discovery.js +0 -151
  327. package/dist/notebook-creation/run-discovery.js.map +0 -1
  328. package/dist/notebook-creation/selector-discovery.d.ts +0 -65
  329. package/dist/notebook-creation/selector-discovery.d.ts.map +0 -1
  330. package/dist/notebook-creation/selector-discovery.js +0 -414
  331. package/dist/notebook-creation/selector-discovery.js.map +0 -1
  332. package/dist/notebook-creation/selectors.d.ts.map +0 -1
  333. package/dist/notebook-creation/selectors.js.map +0 -1
  334. package/dist/notebook-creation/selectors.ts +0 -112
  335. package/dist/notebook-creation/source-manager.d.ts.map +0 -1
  336. package/dist/notebook-creation/source-manager.js.map +0 -1
  337. package/dist/notebook-creation/test-create.d.ts +0 -8
  338. package/dist/notebook-creation/test-create.d.ts.map +0 -1
  339. package/dist/notebook-creation/test-create.js +0 -72
  340. package/dist/notebook-creation/test-create.js.map +0 -1
  341. package/dist/notebook-creation/types.d.ts.map +0 -1
  342. package/dist/notebook-creation/types.js.map +0 -1
  343. package/dist/notebook-creation/video-manager.d.ts.map +0 -1
  344. package/dist/notebook-creation/video-manager.js.map +0 -1
  345. package/dist/observability/metrics.d.ts.map +0 -1
  346. package/dist/observability/metrics.js.map +0 -1
  347. package/dist/quota/index.d.ts.map +0 -1
  348. package/dist/quota/index.js.map +0 -1
  349. package/dist/quota/quota-manager.d.ts.map +0 -1
  350. package/dist/quota/quota-manager.js.map +0 -1
  351. package/dist/resources/resource-handlers.d.ts.map +0 -1
  352. package/dist/resources/resource-handlers.js.map +0 -1
  353. package/dist/session/browser-session.d.ts.map +0 -1
  354. package/dist/session/browser-session.js.map +0 -1
  355. package/dist/session/session-manager.d.ts.map +0 -1
  356. package/dist/session/session-manager.js.map +0 -1
  357. package/dist/session/session-timeout.d.ts.map +0 -1
  358. package/dist/session/session-timeout.js.map +0 -1
  359. package/dist/session/shared-context-manager.d.ts.map +0 -1
  360. package/dist/session/shared-context-manager.js.map +0 -1
  361. package/dist/tools/annotations.d.ts.map +0 -1
  362. package/dist/tools/annotations.js.map +0 -1
  363. package/dist/tools/definitions/ask-question.d.ts.map +0 -1
  364. package/dist/tools/definitions/ask-question.js.map +0 -1
  365. package/dist/tools/definitions/chat-history.d.ts.map +0 -1
  366. package/dist/tools/definitions/chat-history.js.map +0 -1
  367. package/dist/tools/definitions/data-tables.d.ts.map +0 -1
  368. package/dist/tools/definitions/data-tables.js.map +0 -1
  369. package/dist/tools/definitions/gemini.d.ts.map +0 -1
  370. package/dist/tools/definitions/gemini.js.map +0 -1
  371. package/dist/tools/definitions/notebook-management.d.ts.map +0 -1
  372. package/dist/tools/definitions/notebook-management.js.map +0 -1
  373. package/dist/tools/definitions/query-history.d.ts.map +0 -1
  374. package/dist/tools/definitions/query-history.js.map +0 -1
  375. package/dist/tools/definitions/session-management.d.ts.map +0 -1
  376. package/dist/tools/definitions/session-management.js.map +0 -1
  377. package/dist/tools/definitions/system.d.ts.map +0 -1
  378. package/dist/tools/definitions/system.js.map +0 -1
  379. package/dist/tools/definitions/video.d.ts.map +0 -1
  380. package/dist/tools/definitions/video.js.map +0 -1
  381. package/dist/tools/definitions.d.ts.map +0 -1
  382. package/dist/tools/definitions.js.map +0 -1
  383. package/dist/tools/handlers/ask-question.d.ts.map +0 -1
  384. package/dist/tools/handlers/ask-question.js.map +0 -1
  385. package/dist/tools/handlers/audio-video.d.ts.map +0 -1
  386. package/dist/tools/handlers/audio-video.js.map +0 -1
  387. package/dist/tools/handlers/auth.d.ts.map +0 -1
  388. package/dist/tools/handlers/auth.js.map +0 -1
  389. package/dist/tools/handlers/error-utils.d.ts.map +0 -1
  390. package/dist/tools/handlers/error-utils.js.map +0 -1
  391. package/dist/tools/handlers/gemini.d.ts.map +0 -1
  392. package/dist/tools/handlers/gemini.js.map +0 -1
  393. package/dist/tools/handlers/index.d.ts.map +0 -1
  394. package/dist/tools/handlers/index.js.map +0 -1
  395. package/dist/tools/handlers/notebook-creation.d.ts.map +0 -1
  396. package/dist/tools/handlers/notebook-creation.js.map +0 -1
  397. package/dist/tools/handlers/notebook-management.d.ts.map +0 -1
  398. package/dist/tools/handlers/notebook-management.js.map +0 -1
  399. package/dist/tools/handlers/session-management.d.ts.map +0 -1
  400. package/dist/tools/handlers/session-management.js.map +0 -1
  401. package/dist/tools/handlers/system.d.ts.map +0 -1
  402. package/dist/tools/handlers/system.js.map +0 -1
  403. package/dist/tools/handlers/types.d.ts.map +0 -1
  404. package/dist/tools/handlers/types.js.map +0 -1
  405. package/dist/tools/handlers/webhooks.d.ts.map +0 -1
  406. package/dist/tools/handlers/webhooks.js.map +0 -1
  407. package/dist/tools/handlers.d.ts +0 -666
  408. package/dist/tools/handlers.d.ts.map +0 -1
  409. package/dist/tools/handlers.js +0 -2929
  410. package/dist/tools/handlers.js.map +0 -1
  411. package/dist/tools/icons.d.ts.map +0 -1
  412. package/dist/tools/icons.js.map +0 -1
  413. package/dist/tools/index.d.ts.map +0 -1
  414. package/dist/tools/index.js.map +0 -1
  415. package/dist/types.d.ts.map +0 -1
  416. package/dist/types.js.map +0 -1
  417. package/dist/utils/audit-logger.d.ts.map +0 -1
  418. package/dist/utils/audit-logger.js.map +0 -1
  419. package/dist/utils/cert-pinning.d.ts +0 -97
  420. package/dist/utils/cert-pinning.d.ts.map +0 -1
  421. package/dist/utils/cert-pinning.js +0 -328
  422. package/dist/utils/cert-pinning.js.map +0 -1
  423. package/dist/utils/cleanup-manager.d.ts.map +0 -1
  424. package/dist/utils/cleanup-manager.js.map +0 -1
  425. package/dist/utils/cli-handler.d.ts.map +0 -1
  426. package/dist/utils/cli-handler.js.map +0 -1
  427. package/dist/utils/crypto.d.ts.map +0 -1
  428. package/dist/utils/crypto.js.map +0 -1
  429. package/dist/utils/file-lock.d.ts.map +0 -1
  430. package/dist/utils/file-lock.js.map +0 -1
  431. package/dist/utils/file-permissions.d.ts.map +0 -1
  432. package/dist/utils/file-permissions.js.map +0 -1
  433. package/dist/utils/logger.d.ts.map +0 -1
  434. package/dist/utils/logger.js.map +0 -1
  435. package/dist/utils/page-utils.d.ts.map +0 -1
  436. package/dist/utils/page-utils.js.map +0 -1
  437. package/dist/utils/response-validator.d.ts.map +0 -1
  438. package/dist/utils/response-validator.js.map +0 -1
  439. package/dist/utils/secrets-scanner.d.ts.map +0 -1
  440. package/dist/utils/secrets-scanner.js.map +0 -1
  441. package/dist/utils/secure-memory.d.ts.map +0 -1
  442. package/dist/utils/secure-memory.js.map +0 -1
  443. package/dist/utils/security.d.ts.map +0 -1
  444. package/dist/utils/security.js.map +0 -1
  445. package/dist/utils/settings-manager.d.ts.map +0 -1
  446. package/dist/utils/settings-manager.js.map +0 -1
  447. package/dist/utils/stealth-utils.d.ts.map +0 -1
  448. package/dist/utils/stealth-utils.js.map +0 -1
  449. package/dist/utils/tool-validation.d.ts +0 -93
  450. package/dist/utils/tool-validation.d.ts.map +0 -1
  451. package/dist/utils/tool-validation.js +0 -277
  452. package/dist/utils/tool-validation.js.map +0 -1
  453. package/dist/webhooks/index.d.ts.map +0 -1
  454. package/dist/webhooks/index.js.map +0 -1
  455. package/dist/webhooks/types.d.ts.map +0 -1
  456. package/dist/webhooks/types.js.map +0 -1
  457. package/dist/webhooks/webhook-dispatcher.d.ts.map +0 -1
  458. package/dist/webhooks/webhook-dispatcher.js.map +0 -1
  459. package/docs/COMPLIANCE-SPEC.md +0 -1452
  460. package/docs/MCP-DIRECTORY-LISTINGS.md +0 -91
  461. package/docs/SECURITY-FORK-OPPORTUNITIES.md +0 -79
  462. package/docs/SECURITY_IMPLEMENTATION_PLAN.md +0 -437
  463. package/docs/archive/ISSUES-legacy-2026-04-24.md +0 -644
  464. package/docs/configuration.md +0 -94
  465. package/docs/dependency-risk.md +0 -25
  466. package/docs/improvement-sprint-2026.2.10.md +0 -210
  467. package/docs/testing-runbook.md +0 -166
  468. package/docs/tools.md +0 -34
  469. package/docs/troubleshooting.md +0 -59
  470. package/docs/usage-guide.md +0 -246
@@ -16,29 +16,10 @@
16
16
  */
17
17
  import { log } from "../utils/logger.js";
18
18
  import { randomDelay } from "../utils/stealth-utils.js";
19
- export class DataTableManager {
20
- authManager;
21
- contextManager;
22
- page = null;
23
- constructor(authManager, contextManager) {
24
- this.authManager = authManager;
25
- this.contextManager = contextManager;
26
- }
27
- /**
28
- * Navigate to a notebook and ensure we're on the right page
29
- */
30
- async navigateToNotebook(notebookUrl) {
31
- const context = await this.contextManager.getOrCreateContext();
32
- const isAuth = await this.authManager.validateWithRetry(context);
33
- if (!isAuth) {
34
- throw new Error("Not authenticated. Run setup_auth first.");
35
- }
36
- this.page = await context.newPage();
37
- await this.page.goto(notebookUrl, { waitUntil: "domcontentloaded" });
38
- await this.page.waitForLoadState("networkidle").catch(() => { });
39
- await randomDelay(2000, 3000);
40
- return this.page;
41
- }
19
+ import { validateResponse } from "../utils/response-validator.js";
20
+ import { StudioManagerBase, } from "./studio-manager-base.js";
21
+ export class DataTableManager extends StudioManagerBase {
22
+ logName = "data-table-manager";
42
23
  /**
43
24
  * Ensure the Studio panel is visible (expand if collapsed).
44
25
  *
@@ -105,6 +86,18 @@ export class DataTableManager {
105
86
  if (item.classList.contains("shimmer-blue") || titleText.toLowerCase().includes("generating")) {
106
87
  return { status: "generating", progress: 0 };
107
88
  }
89
+ // Detect an explicit failure state on THIS artifact before assuming ready.
90
+ // A failed generation leaves a non-shimmer artifact, which would otherwise be
91
+ // misreported as "ready". Scope the check to the matched item only — a page-global
92
+ // alert query could match unrelated UI. Class names are best-effort (unconfirmed
93
+ // by live inspection); [role="alert"]/error child is the locale-independent signal.
94
+ const hasErrorChild = !!item.querySelector('[role="alert"], .error-state, .artifact-error');
95
+ if (hasErrorChild ||
96
+ item.classList.contains("error-state") ||
97
+ item.classList.contains("artifact-error") ||
98
+ item.classList.contains("failed")) {
99
+ return { status: "failed" };
100
+ }
108
101
  // Otherwise it's ready
109
102
  return { status: "ready" };
110
103
  }
@@ -214,6 +207,14 @@ export class DataTableManager {
214
207
  await randomDelay(500, 800);
215
208
  // Check if generation started
216
209
  const newStatus = await this.checkDataTableStatusInternal(page);
210
+ if (newStatus.status === "failed") {
211
+ log.warning(" Data table generation reported a failed state");
212
+ return {
213
+ success: false,
214
+ status: newStatus,
215
+ error: "Data table generation failed.",
216
+ };
217
+ }
217
218
  if (newStatus.status === "generating" || newStatus.status === "ready") {
218
219
  log.success(` Data table generation ${newStatus.status === "ready" ? "completed" : "started"}`);
219
220
  return { success: true, status: newStatus };
@@ -253,6 +254,12 @@ export class DataTableManager {
253
254
  error: "No data table found. Use generate_data_table first.",
254
255
  };
255
256
  }
257
+ if (status.status === "failed") {
258
+ return {
259
+ success: false,
260
+ error: "Data table generation failed. Use generate_data_table to retry.",
261
+ };
262
+ }
256
263
  // Click the data table artifact to open it
257
264
  const artifactClicked = await this.clickDataTableArtifact(page);
258
265
  if (!artifactClicked) {
@@ -261,6 +268,12 @@ export class DataTableManager {
261
268
  error: "Could not click on data table artifact.",
262
269
  };
263
270
  }
271
+ // Status is already confirmed "ready" above, so a table is expected to
272
+ // render after opening the artifact. Wait for the concrete <table> element
273
+ // that extractTableData() reads, instead of relying on a fixed sleep as the
274
+ // only readiness gate (M30). Bounded + .catch so a miss degrades to the
275
+ // prior behavior (fall through to extractTableData, which returns null).
276
+ await page.waitForSelector("table", { timeout: 10000 }).catch(() => { });
264
277
  await randomDelay(2000, 3000);
265
278
  // Extract table data from the page
266
279
  const table = await this.extractTableData(page);
@@ -270,10 +283,14 @@ export class DataTableManager {
270
283
  error: "Could not extract table data. The table may not be visible yet.",
271
284
  };
272
285
  }
273
- log.success(` Extracted data table: ${table.totalColumns} columns x ${table.totalRows} rows`);
286
+ // Notebook sources are arbitrary documents, so table cell text is untrusted
287
+ // and a prompt-injection conduit. Sanitize every cell before returning it
288
+ // to the calling model (mirrors ask_question response validation).
289
+ const safeTable = await this.sanitizeTable(table);
290
+ log.success(` Extracted data table: ${safeTable.totalColumns} columns x ${safeTable.totalRows} rows`);
274
291
  return {
275
292
  success: true,
276
- table,
293
+ table: safeTable,
277
294
  };
278
295
  }
279
296
  finally {
@@ -336,19 +353,29 @@ export class DataTableManager {
336
353
  });
337
354
  }
338
355
  /**
339
- * Close the page if open
356
+ * Sanitize extracted table content through the shared response validator.
357
+ * Each cell originates from untrusted document sources, so any prompt
358
+ * injection / malicious content is redacted before the table is returned
359
+ * to the calling model.
340
360
  */
341
- async closePage() {
342
- if (this.page) {
343
- try {
344
- await this.page.close();
345
- }
346
- catch (err) {
347
- log.debug(`data-table-manager: closing page: ${err instanceof Error ? err.message : String(err)}`);
348
- // Ignore close errors
349
- }
350
- this.page = null;
361
+ async sanitizeTable(table) {
362
+ let flagged = false;
363
+ const sanitizeCell = async (value) => {
364
+ const validation = await validateResponse(value);
365
+ if (!validation.safe)
366
+ flagged = true;
367
+ return validation.sanitized;
368
+ };
369
+ const headers = await Promise.all(table.headers.map(sanitizeCell));
370
+ const rows = await Promise.all(table.rows.map((row) => Promise.all(row.map(sanitizeCell))));
371
+ if (flagged) {
372
+ log.warning("🛡️ Suspicious content detected in extracted data table — sanitized");
351
373
  }
374
+ return {
375
+ headers,
376
+ rows,
377
+ totalRows: table.totalRows,
378
+ totalColumns: table.totalColumns,
379
+ };
352
380
  }
353
381
  }
354
- //# sourceMappingURL=data-table-manager.js.map
@@ -7,4 +7,3 @@
7
7
  export declare function clickCopiedTextSourceOption(): {
8
8
  clicked: boolean;
9
9
  };
10
- //# sourceMappingURL=dom-scripts.d.ts.map
@@ -55,4 +55,3 @@ export function clickCopiedTextSourceOption() {
55
55
  }
56
56
  return { clicked: false };
57
57
  }
58
- //# sourceMappingURL=dom-scripts.js.map
@@ -15,4 +15,3 @@ export declare class NotebookCreationError extends Error {
15
15
  readonly cause?: unknown;
16
16
  constructor(message: string, options: NotebookCreationErrorOptions);
17
17
  }
18
- //# sourceMappingURL=errors.d.ts.map
@@ -17,4 +17,3 @@ export class NotebookCreationError extends Error {
17
17
  this.cause = options.cause;
18
18
  }
19
19
  }
20
- //# sourceMappingURL=errors.js.map
@@ -12,4 +12,3 @@ export * from "./notebook-creator.js";
12
12
  export * from "./notebook-sync.js";
13
13
  export * from "./video-manager.js";
14
14
  export * from "./data-table-manager.js";
15
- //# sourceMappingURL=index.d.ts.map
@@ -12,4 +12,3 @@ export * from "./notebook-creator.js";
12
12
  export * from "./notebook-sync.js";
13
13
  export * from "./video-manager.js";
14
14
  export * from "./data-table-manager.js";
15
- //# sourceMappingURL=index.js.map
@@ -17,6 +17,14 @@ export declare class NotebookCreator {
17
17
  private withOperationLock;
18
18
  createNotebook(options: CreateNotebookOptions): Promise<CreatedNotebook>;
19
19
  private runCreateNotebook;
20
+ /**
21
+ * Best-effort deletion of a freshly-created but empty notebook (no sources
22
+ * added). Opens the notebook's overflow/options menu and confirms delete.
23
+ *
24
+ * Failure to delete is logged but not rethrown: the caller is already
25
+ * reporting the creation as failed, so we must not mask that with a
26
+ * secondary error.
27
+ */
28
+ private deleteEmptyNotebook;
20
29
  }
21
30
  export declare function createNotebook(authManager: AuthManager, contextManager: SharedContextManager, options: CreateNotebookOptions): Promise<CreatedNotebook>;
22
- //# sourceMappingURL=notebook-creator.d.ts.map
@@ -83,6 +83,17 @@ export class NotebookCreator {
83
83
  }
84
84
  await randomDelay(1000, 2000);
85
85
  }
86
+ // Fail-safe: if sources were requested but NONE actually succeeded, the
87
+ // notebook is empty and useless. Discard it (best-effort delete to avoid
88
+ // burning quota) and throw so the caller never persists a library entry
89
+ // or counts a successful creation for it. An empty `sources` array (e.g.
90
+ // an overflow shell notebook) is a legitimate zero-success case and is
91
+ // left untouched.
92
+ if (sources.length > 0 && successCount === 0) {
93
+ log.error(`❌ Notebook creation failed: no sources could be added (${notebookId})`);
94
+ await this.deleteEmptyNotebook();
95
+ throw new Error("Notebook creation failed: no sources could be added; empty notebook was discarded");
96
+ }
86
97
  currentStep++;
87
98
  await sendProgress?.("Finalizing notebook...", currentStep, totalSteps);
88
99
  const notebookUrl = await this.navigation.finalizeAndGetUrl();
@@ -103,9 +114,47 @@ export class NotebookCreator {
103
114
  await this.navigation.cleanup();
104
115
  }
105
116
  }
117
+ /**
118
+ * Best-effort deletion of a freshly-created but empty notebook (no sources
119
+ * added). Opens the notebook's overflow/options menu and confirms delete.
120
+ *
121
+ * Failure to delete is logged but not rethrown: the caller is already
122
+ * reporting the creation as failed, so we must not mask that with a
123
+ * secondary error.
124
+ */
125
+ async deleteEmptyNotebook() {
126
+ const page = this.navigation.getCurrentPage();
127
+ if (!page) {
128
+ log.debug("notebook creator: no page available to delete empty notebook");
129
+ return;
130
+ }
131
+ try {
132
+ const menuButton = page
133
+ .locator('button[aria-label*="more" i], button[aria-label*="options" i], button[aria-label*="settings" i]')
134
+ .first();
135
+ await menuButton.click({ timeout: 5000 });
136
+ await randomDelay(500, 1000);
137
+ const deleteOption = page
138
+ .locator('button:has-text("Delete"), [role="menuitem"]:has-text("Delete")')
139
+ .first();
140
+ await deleteOption.click({ timeout: 5000 });
141
+ await randomDelay(500, 1000);
142
+ // Confirm in any follow-up dialog.
143
+ const confirmButton = page
144
+ .locator('button:has-text("Delete"), button:has-text("Confirm")')
145
+ .last();
146
+ if ((await confirmButton.count()) > 0) {
147
+ await confirmButton.click({ timeout: 5000 });
148
+ await randomDelay(500, 1000);
149
+ }
150
+ log.info("🗑️ Discarded empty notebook (no sources added)");
151
+ }
152
+ catch (error) {
153
+ log.warning(`⚠️ Could not delete empty notebook: ${error instanceof Error ? error.message : String(error)}`);
154
+ }
155
+ }
106
156
  }
107
157
  export async function createNotebook(authManager, contextManager, options) {
108
158
  const creator = new NotebookCreator(authManager, contextManager);
109
159
  return creator.createNotebook(options);
110
160
  }
111
- //# sourceMappingURL=notebook-creator.js.map
@@ -16,4 +16,3 @@ export declare class NotebookNavigation {
16
16
  safePageUrl(page: Page): string;
17
17
  cleanup(): Promise<void>;
18
18
  }
19
- //# sourceMappingURL=notebook-nav.d.ts.map
@@ -29,7 +29,16 @@ export class NotebookNavigation {
29
29
  }
30
30
  async initialize(headless) {
31
31
  log.info("🌐 Initializing browser for notebook creation...");
32
- const context = await this.contextManager.getOrCreateContext(headless === false ? true : undefined);
32
+ // Map the caller's headless intent to getOrCreateContext's explicit
33
+ // "show browser" contract (its argument is true = show/visible,
34
+ // false = headless, undefined = defer to CONFIG.headless).
35
+ // - headless === false -> the caller explicitly wants a VISIBLE browser
36
+ // -> showBrowser = true
37
+ // - headless === true / undefined -> no explicit visible request; defer
38
+ // to the configured default
39
+ // -> showBrowser = undefined
40
+ const showBrowser = headless === false ? true : undefined;
41
+ const context = await this.contextManager.getOrCreateContext(showBrowser);
33
42
  const isAuthenticated = await this.authManager.validateWithRetry(context);
34
43
  if (!isAuthenticated) {
35
44
  throw new Error("Not authenticated to NotebookLM. Please run setup_auth first.");
@@ -89,16 +98,23 @@ export class NotebookNavigation {
89
98
  log.debug(`notebook-nav: clicking 'New notebook' button selector: ${err instanceof Error ? err.message : String(err)}`);
90
99
  }
91
100
  }
92
- const textPatterns = ["New notebook", "Create notebook", "Create new", "New"];
101
+ // Specific, multi-word labels only. The previous last-ditch pattern was the
102
+ // bare word "New", which an includes()-match happily found inside unrelated
103
+ // controls like "New chat" or "New label" — clicking the wrong button. Match
104
+ // only full, unambiguous create-notebook labels.
105
+ const textPatterns = ["New notebook", "Create notebook", "Create new notebook"];
93
106
  for (const pattern of textPatterns) {
94
107
  try {
95
108
  const clicked = await this.page.evaluate((searchText) => {
96
109
  const browser = globalThis;
110
+ const needle = searchText.toLowerCase();
97
111
  const elements = browser.document.querySelectorAll('button, a, [role="button"]');
98
112
  for (const el of elements) {
99
- const elText = el.textContent?.toLowerCase() || "";
100
- const ariaLabel = el.getAttribute("aria-label")?.toLowerCase() || "";
101
- if (elText.includes(searchText.toLowerCase()) || ariaLabel.includes(searchText.toLowerCase())) {
113
+ const elText = (el.textContent || "").trim().toLowerCase();
114
+ const ariaLabel = (el.getAttribute("aria-label") || "").trim().toLowerCase();
115
+ // Exact label match only — never a loose substring — so we cannot
116
+ // latch onto "New chat" / "New label" etc.
117
+ if (elText === needle || ariaLabel === needle) {
102
118
  el.click();
103
119
  return true;
104
120
  }
@@ -237,4 +253,3 @@ export class NotebookNavigation {
237
253
  }
238
254
  }
239
255
  }
240
- //# sourceMappingURL=notebook-nav.js.map
@@ -26,6 +26,13 @@ export interface SyncResult {
26
26
  libraryName: string;
27
27
  libraryUrl: string;
28
28
  reason: string;
29
+ /**
30
+ * Whether this entry is SAFE to auto-remove. Only true when we have an
31
+ * exact, UUID-based confirmation that the notebook no longer exists. Entries
32
+ * that merely failed a fuzzy title match are reported as stale (for the
33
+ * human to review) but are NOT eligible for destructive auto-fix.
34
+ */
35
+ autoFixSafe: boolean;
29
36
  }>;
30
37
  missingNotebooks: ActualNotebook[];
31
38
  suggestions: string[];
@@ -84,7 +91,13 @@ export declare class NotebookSync {
84
91
  */
85
92
  private titlesMatch;
86
93
  /**
87
- * Extract notebook ID from URL
94
+ * Extract a STABLE notebook UUID from a URL, or null if none can be derived.
95
+ *
96
+ * Returns null for "pending-*" placeholders and for any URL that does not
97
+ * carry a real /notebook/UUID segment. A null id must NEVER be treated as a
98
+ * match key (two unknowns are not "equal") and must NEVER feed a destructive
99
+ * auto-fix decision — doing so previously let placeholder/garbage ids collide
100
+ * or let a missing id be (mis)matched and removed.
88
101
  */
89
102
  private extractNotebookId;
90
103
  /**
@@ -115,4 +128,3 @@ export declare function syncLibrary(authManager: AuthManager, contextManager: Sh
115
128
  autoFix?: boolean;
116
129
  showBrowser?: boolean;
117
130
  }): Promise<SyncResult>;
118
- //# sourceMappingURL=notebook-sync.d.ts.map
@@ -289,10 +289,26 @@ export class NotebookSync {
289
289
  return [];
290
290
  // Click each row to capture the URL via navigation
291
291
  const notebooks = [];
292
- const startUrl = this.page.url();
292
+ // Capture the library root URL ONCE, before any navigation. If the page is
293
+ // already sitting on a /notebook/ URL (left over from a prior step), the
294
+ // per-row waitForURL(/\/notebook\//) would resolve immediately against the
295
+ // pre-existing URL and mislabel every row with the wrong UUID. In that case
296
+ // navigate back to the library root first so clicks produce real
297
+ // navigations from a known-good base.
298
+ let startUrl = this.page.url();
299
+ if (/\/notebook\//.test(startUrl)) {
300
+ log.warning(" ⚠️ Not on library root before row scrape — returning to library");
301
+ await this.page.goto(NOTEBOOKLM_URL, { waitUntil: "domcontentloaded", timeout: CONFIG.browserTimeout });
302
+ await this.page.waitForLoadState("networkidle").catch(() => { });
303
+ await randomDelay(1500, 2000);
304
+ startUrl = this.page.url();
305
+ }
293
306
  for (let i = 0; i < rowData.length; i++) {
294
307
  const row = rowData[i];
295
308
  try {
309
+ // Record the URL immediately before the click so we can confirm that a
310
+ // REAL navigation occurred (and not accept a pre-existing notebook URL).
311
+ const urlBeforeClick = this.page.url();
296
312
  // Click the data row by index (skip non-data rows in evaluate)
297
313
  await this.page.evaluate((clickIdx) => {
298
314
  const browser = globalThis;
@@ -305,22 +321,32 @@ export class NotebookSync {
305
321
  }
306
322
  dataRows[clickIdx]?.click();
307
323
  }, i);
308
- // Wait for navigation to complete
309
- await this.page.waitForURL(/\/notebook\//, { timeout: 10000 }).catch(() => { });
324
+ // Wait for the URL to actually CHANGE to a new /notebook/ page. Using a
325
+ // predicate (rather than a bare /\/notebook\// regex) prevents resolving
326
+ // immediately against a pre-existing notebook URL and capturing a stale
327
+ // UUID for this row.
328
+ await this.page
329
+ .waitForURL((u) => /\/notebook\//.test(u.toString()) && u.toString() !== urlBeforeClick, { timeout: 10000 })
330
+ .catch(() => { });
310
331
  await randomDelay(500, 1000);
311
- // Capture the URL
332
+ // Capture the URL — only trust a UUID when a real navigation to a NEW
333
+ // notebook actually happened.
312
334
  const currentUrl = this.page.url();
313
335
  const notebookMatch = currentUrl.match(/\/notebook\/([a-f0-9-]+)/i);
314
- const url = notebookMatch
336
+ const navigated = currentUrl !== urlBeforeClick && notebookMatch !== null;
337
+ const url = navigated
315
338
  ? `https://notebooklm.google.com/notebook/${notebookMatch[1]}`
316
339
  : `pending-nav-${notebooks.length}`;
340
+ if (!navigated) {
341
+ log.warning(` ⚠️ Row click did not navigate to a new notebook: ${row.title}`);
342
+ }
317
343
  notebooks.push({
318
344
  title: row.title,
319
345
  url,
320
346
  sourceCount: row.sourceCount,
321
347
  createdDate: row.createdDate,
322
348
  });
323
- // Navigate back
349
+ // Navigate back to the library root
324
350
  await this.page.goto(startUrl, { waitUntil: "domcontentloaded", timeout: CONFIG.browserTimeout });
325
351
  await this.page.waitForLoadState("networkidle").catch(() => { });
326
352
  await randomDelay(1500, 2000);
@@ -404,65 +430,108 @@ export class NotebookSync {
404
430
  const matched = [];
405
431
  const staleEntries = [];
406
432
  const suggestions = [];
433
+ // Is the extraction trustworthy enough to treat "UUID absent from this list"
434
+ // as positive proof of deletion? Only if we actually saw notebooks AND every
435
+ // one of them yielded a real UUID. An empty list usually means extraction
436
+ // failed (page didn't load / strategy missed) — NOT that the account is
437
+ // empty — and a "pending-*" entry could BE the very notebook we're checking,
438
+ // so "absent" is not a confirmation. Without this guard a failed scrape would
439
+ // mark every valid library entry as "confirmed deleted" and autoFix would
440
+ // wipe the whole library. This is the core data-loss M33 must prevent.
441
+ const extractionIsAuthoritative = actualNotebooks.length > 0 &&
442
+ actualNotebooks.every((n) => this.extractNotebookId(n.url) !== null);
407
443
  // Track which actual notebooks are matched
408
444
  const matchedActualIndices = new Set();
445
+ // Actual notebooks tied to a library entry by a FUZZY (unconfirmed) title
446
+ // match. They are not authoritative matches, but we must not auto-ADD them
447
+ // as "missing" either — that would create a duplicate library entry for a
448
+ // notebook the human still needs to reconcile. Excluded from auto-add only.
449
+ const fuzzyReservedIndices = new Set();
409
450
  // Check each library entry
410
451
  for (const entry of libraryEntries) {
411
- // Extract notebook ID from URL
452
+ // Extract notebook ID from URL (null = pending/garbage, never a match key)
412
453
  const libraryNotebookId = this.extractNotebookId(entry.url);
413
- // Try to find matching actual notebook
414
- let matchingActualIndex = -1;
415
- // First try: match by URL/ID
416
- for (let i = 0; i < actualNotebooks.length; i++) {
417
- const actual = actualNotebooks[i];
418
- const actualNotebookId = this.extractNotebookId(actual.url);
419
- if (actualNotebookId === libraryNotebookId && !actual.url.startsWith("pending-")) {
420
- matchingActualIndex = i;
421
- break;
454
+ // First try: EXACT UUID match. This is the only authoritative identity —
455
+ // and the only signal allowed to drive a destructive auto-fix.
456
+ let exactMatchIndex = -1;
457
+ if (libraryNotebookId !== null) {
458
+ for (let i = 0; i < actualNotebooks.length; i++) {
459
+ const actualNotebookId = this.extractNotebookId(actualNotebooks[i].url);
460
+ if (actualNotebookId !== null && actualNotebookId === libraryNotebookId) {
461
+ exactMatchIndex = i;
462
+ break;
463
+ }
422
464
  }
423
465
  }
424
- // Second try: match by title similarity (fuzzy match)
425
- if (matchingActualIndex < 0) {
466
+ // Second try: fuzzy title match. This is a SUGGESTION ONLY. A 60% word
467
+ // overlap can match the wrong notebook ("Security Notes 2025" vs "...2026"),
468
+ // so a fuzzy hit must never be fed into removal/relabel — it only avoids
469
+ // proposing deletion of an entry we can plausibly still see.
470
+ let fuzzyMatchIndex = -1;
471
+ if (exactMatchIndex < 0) {
426
472
  const normalizedEntryName = this.normalizeTitle(entry.name);
427
473
  for (let i = 0; i < actualNotebooks.length; i++) {
428
474
  if (matchedActualIndices.has(i))
429
475
  continue; // Already matched
430
- const actual = actualNotebooks[i];
431
- const normalizedActualTitle = this.normalizeTitle(actual.title);
432
- // Check for significant overlap
476
+ const normalizedActualTitle = this.normalizeTitle(actualNotebooks[i].title);
433
477
  if (this.titlesMatch(normalizedEntryName, normalizedActualTitle)) {
434
- matchingActualIndex = i;
478
+ fuzzyMatchIndex = i;
435
479
  break;
436
480
  }
437
481
  }
438
482
  }
439
- if (matchingActualIndex >= 0) {
440
- const matchingActual = actualNotebooks[matchingActualIndex];
483
+ if (exactMatchIndex >= 0) {
484
+ const matchingActual = actualNotebooks[exactMatchIndex];
441
485
  matched.push({
442
486
  libraryId: entry.id,
443
487
  libraryName: entry.name,
444
488
  actualTitle: matchingActual.title,
445
489
  actualUrl: matchingActual.url,
446
490
  });
447
- matchedActualIndices.add(matchingActualIndex);
448
- // Check if name differs significantly
491
+ matchedActualIndices.add(exactMatchIndex);
492
+ // Title drift on a UUID-confirmed match is safe to suggest relabelling.
449
493
  const cleanActualTitle = this.normalizeTitle(matchingActual.title);
450
494
  const cleanEntryName = this.normalizeTitle(entry.name);
451
495
  if (cleanEntryName !== cleanActualTitle) {
452
496
  suggestions.push(`📝 "${entry.name}" matches "${matchingActual.title}" (consider updating library entry)`);
453
497
  }
454
498
  }
499
+ else if (fuzzyMatchIndex >= 0) {
500
+ // Fuzzy hit: report as a SUGGESTION only. Do not consume the actual
501
+ // notebook (leave it as "missing" so the human sees both sides) and do
502
+ // NOT mark the library entry as auto-removable.
503
+ const fuzzyActual = actualNotebooks[fuzzyMatchIndex];
504
+ fuzzyReservedIndices.add(fuzzyMatchIndex);
505
+ suggestions.push(`❓ "${entry.name}" may correspond to "${fuzzyActual.title}" (fuzzy title match — verify manually; not auto-applied)`);
506
+ staleEntries.push({
507
+ libraryId: entry.id,
508
+ libraryName: entry.name,
509
+ libraryUrl: entry.url,
510
+ reason: "No exact UUID match; only a fuzzy title match was found (review manually)",
511
+ autoFixSafe: false,
512
+ });
513
+ }
455
514
  else {
515
+ // No exact and no fuzzy match. Only safe to auto-remove when we could
516
+ // actually derive a real UUID for this entry AND positively confirmed it
517
+ // is absent. If the entry's own URL has no parseable UUID (pending/
518
+ // garbage), we cannot prove the notebook is gone — never auto-delete it.
456
519
  staleEntries.push({
457
520
  libraryId: entry.id,
458
521
  libraryName: entry.name,
459
522
  libraryUrl: entry.url,
460
- reason: "Notebook not found in NotebookLM (may be deleted or URL changed)",
523
+ reason: libraryNotebookId === null
524
+ ? "Entry has no resolvable notebook UUID (cannot confirm deletion — review manually)"
525
+ : !extractionIsAuthoritative
526
+ ? "Notebook not found, but extraction was incomplete (empty or pending results) — cannot confirm deletion; review manually"
527
+ : "Notebook UUID not present in NotebookLM (confirmed deleted or moved)",
528
+ autoFixSafe: libraryNotebookId !== null && extractionIsAuthoritative,
461
529
  });
462
530
  }
463
531
  }
464
- // Find notebooks not in library
465
- const missingNotebooks = actualNotebooks.filter((_, index) => !matchedActualIndices.has(index));
532
+ // Find notebooks not in library. Exclude fuzzy-reserved actuals so we don't
533
+ // auto-add a duplicate of a notebook a stale entry probably already denotes.
534
+ const missingNotebooks = actualNotebooks.filter((_, index) => !matchedActualIndices.has(index) && !fuzzyReservedIndices.has(index));
466
535
  // Generate suggestions
467
536
  if (staleEntries.length > 0) {
468
537
  suggestions.unshift(`🗑️ ${staleEntries.length} stale library entries should be removed`);
@@ -484,8 +553,13 @@ export class NotebookSync {
484
553
  normalizeTitle(title) {
485
554
  return title
486
555
  .toLowerCase()
487
- .replace(/[🔓🔒📁📄🔐⚛️🧠🛡️💻📋]/g, "") // Remove emojis
488
- .replace(/[\u{1F300}-\u{1F9FF}]/gu, "") // Remove other emojis
556
+ // Remove emoji across all Unicode ranges (flags, symbols, supplemental
557
+ // pictographs, etc.) plus the zero-width-joiner and variation selectors
558
+ // used to compose emoji sequences. A hardcoded set / narrow range missed
559
+ // common emoji and made otherwise-equal titles normalize differently,
560
+ // producing false "stale" mismatches.
561
+ .replace(/\p{Extended_Pictographic}/gu, "")
562
+ .replace(/[\u{200D}\u{FE0E}\u{FE0F}\u{1F3FB}-\u{1F3FF}]/gu, "") // ZWJ, variation selectors, skin-tone modifiers
489
563
  .replace(/[^\w\s]/g, " ") // Remove punctuation
490
564
  .replace(/\s+/g, " ") // Normalize whitespace
491
565
  .trim();
@@ -511,12 +585,21 @@ export class NotebookSync {
511
585
  return overlapRatio >= 0.6;
512
586
  }
513
587
  /**
514
- * Extract notebook ID from URL
588
+ * Extract a STABLE notebook UUID from a URL, or null if none can be derived.
589
+ *
590
+ * Returns null for "pending-*" placeholders and for any URL that does not
591
+ * carry a real /notebook/UUID segment. A null id must NEVER be treated as a
592
+ * match key (two unknowns are not "equal") and must NEVER feed a destructive
593
+ * auto-fix decision — doing so previously let placeholder/garbage ids collide
594
+ * or let a missing id be (mis)matched and removed.
515
595
  */
516
596
  extractNotebookId(url) {
597
+ if (!url || url.startsWith("pending-"))
598
+ return null;
517
599
  // URL format: https://notebooklm.google.com/notebook/UUID?authuser=X
518
- const match = url.match(/\/notebook\/([a-f0-9-]+)/i);
519
- return match ? match[1] : url;
600
+ // Require a canonical UUID so a partial/garbage id can't be matched.
601
+ const match = url.match(/\/notebook\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/i);
602
+ return match ? match[1].toLowerCase() : null;
520
603
  }
521
604
  /**
522
605
  * Auto-fix stale entries by removing them
@@ -524,6 +607,13 @@ export class NotebookSync {
524
607
  async autoFixStaleEntries(staleEntries) {
525
608
  log.info("🔧 Auto-fixing stale entries...");
526
609
  for (const entry of staleEntries) {
610
+ // DESTRUCTIVE GUARD: only remove entries we could confirm as deleted via
611
+ // an exact UUID. Fuzzy/unresolvable entries are left for manual review so
612
+ // a valid library entry is never destroyed on a 60%-title-overlap guess.
613
+ if (!entry.autoFixSafe) {
614
+ log.warning(`⏭️ Skipping auto-remove of "${entry.libraryName}" — ${entry.reason}`);
615
+ continue;
616
+ }
527
617
  try {
528
618
  this.library.removeNotebook(entry.libraryId);
529
619
  log.success(`✅ Removed stale entry: ${entry.libraryName}`);
@@ -623,4 +713,3 @@ export async function syncLibrary(authManager, contextManager, library, options)
623
713
  const sync = new NotebookSync(authManager, contextManager, library);
624
714
  return await sync.syncLibrary(options);
625
715
  }
626
- //# sourceMappingURL=notebook-sync.js.map
@@ -138,4 +138,3 @@ export type SelectorKey = keyof typeof NOTEBOOKLM_SELECTORS;
138
138
  * Get all selectors for a key (primary + fallbacks)
139
139
  */
140
140
  export declare function getSelectors(key: SelectorKey): string[];
141
- //# sourceMappingURL=selectors.d.ts.map