@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.
- package/dist/auth/auth-manager.d.ts +0 -1
- package/dist/auth/auth-manager.js +0 -1
- package/dist/auth/mcp-auth.d.ts +0 -1
- package/dist/auth/mcp-auth.js +0 -1
- package/dist/compliance/alert-manager.d.ts +6 -2
- package/dist/compliance/alert-manager.js +40 -10
- package/dist/compliance/breach-detection.d.ts +0 -1
- package/dist/compliance/breach-detection.js +0 -1
- package/dist/compliance/change-log.d.ts +13 -1
- package/dist/compliance/change-log.js +82 -16
- package/dist/compliance/compliance-logger.d.ts +29 -3
- package/dist/compliance/compliance-logger.js +90 -27
- package/dist/compliance/compliance-tools.d.ts +0 -1
- package/dist/compliance/compliance-tools.js +0 -1
- package/dist/compliance/consent-manager.d.ts +0 -1
- package/dist/compliance/consent-manager.js +0 -1
- package/dist/compliance/dashboard.d.ts +4 -3
- package/dist/compliance/dashboard.js +11 -8
- package/dist/compliance/data-classification.d.ts +0 -1
- package/dist/compliance/data-classification.js +0 -1
- package/dist/compliance/data-erasure.d.ts +0 -1
- package/dist/compliance/data-erasure.js +0 -1
- package/dist/compliance/data-export.d.ts +0 -1
- package/dist/compliance/data-export.js +0 -1
- package/dist/compliance/data-inventory.d.ts +0 -1
- package/dist/compliance/data-inventory.js +0 -1
- package/dist/compliance/dsar-handler.d.ts +0 -1
- package/dist/compliance/dsar-handler.js +0 -1
- package/dist/compliance/evidence-collector.d.ts +0 -1
- package/dist/compliance/evidence-collector.js +4 -2
- package/dist/compliance/health-monitor.d.ts +0 -1
- package/dist/compliance/health-monitor.js +0 -1
- package/dist/compliance/incident-manager.d.ts +0 -1
- package/dist/compliance/incident-manager.js +0 -1
- package/dist/compliance/index.d.ts +0 -1
- package/dist/compliance/index.js +0 -1
- package/dist/compliance/policy-docs.d.ts +0 -1
- package/dist/compliance/policy-docs.js +0 -1
- package/dist/compliance/privacy-notice-text.d.ts +0 -1
- package/dist/compliance/privacy-notice-text.js +0 -1
- package/dist/compliance/privacy-notice.d.ts +0 -1
- package/dist/compliance/privacy-notice.js +0 -1
- package/dist/compliance/report-generator.d.ts +7 -1
- package/dist/compliance/report-generator.js +116 -34
- package/dist/compliance/retention-engine.d.ts +0 -1
- package/dist/compliance/retention-engine.js +0 -1
- package/dist/compliance/siem-exporter.d.ts +26 -2
- package/dist/compliance/siem-exporter.js +89 -24
- package/dist/compliance/types.d.ts +0 -1
- package/dist/compliance/types.js +0 -1
- package/dist/config.d.ts +0 -1
- package/dist/config.js +2 -3
- package/dist/errors.d.ts +0 -1
- package/dist/errors.js +0 -1
- package/dist/events/event-emitter.d.ts +9 -1
- package/dist/events/event-emitter.js +47 -8
- package/dist/events/event-types.d.ts +0 -1
- package/dist/events/event-types.js +8 -2
- package/dist/gemini/gemini-client.d.ts +0 -1
- package/dist/gemini/gemini-client.js +237 -45
- package/dist/gemini/index.d.ts +0 -1
- package/dist/gemini/index.js +0 -1
- package/dist/gemini/pdf-chunker.d.ts +0 -1
- package/dist/gemini/pdf-chunker.js +60 -35
- package/dist/gemini/types.d.ts +0 -1
- package/dist/gemini/types.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +60 -7
- package/dist/library/notebook-library.d.ts +30 -2
- package/dist/library/notebook-library.js +345 -85
- package/dist/library/types.d.ts +0 -1
- package/dist/library/types.js +0 -1
- package/dist/logging/index.d.ts +0 -1
- package/dist/logging/index.js +0 -1
- package/dist/logging/query-logger.d.ts +20 -1
- package/dist/logging/query-logger.js +104 -21
- package/dist/notebook-creation/audio-manager.d.ts +7 -16
- package/dist/notebook-creation/audio-manager.js +115 -58
- package/dist/notebook-creation/browser-options.d.ts +0 -1
- package/dist/notebook-creation/browser-options.js +0 -1
- package/dist/notebook-creation/data-table-manager.d.ts +8 -14
- package/dist/notebook-creation/data-table-manager.js +64 -37
- package/dist/notebook-creation/dom-scripts.d.ts +0 -1
- package/dist/notebook-creation/dom-scripts.js +0 -1
- package/dist/notebook-creation/errors.d.ts +0 -1
- package/dist/notebook-creation/errors.js +0 -1
- package/dist/notebook-creation/index.d.ts +0 -1
- package/dist/notebook-creation/index.js +0 -1
- package/dist/notebook-creation/notebook-creator.d.ts +9 -1
- package/dist/notebook-creation/notebook-creator.js +50 -1
- package/dist/notebook-creation/notebook-nav.d.ts +0 -1
- package/dist/notebook-creation/notebook-nav.js +21 -6
- package/dist/notebook-creation/notebook-sync.d.ts +14 -2
- package/dist/notebook-creation/notebook-sync.js +124 -35
- package/dist/notebook-creation/selectors.d.ts +0 -1
- package/dist/notebook-creation/selectors.js +6 -4
- package/dist/notebook-creation/source-manager-shared.d.ts +75 -0
- package/dist/notebook-creation/source-manager-shared.js +86 -0
- package/dist/notebook-creation/source-manager.d.ts +29 -2
- package/dist/notebook-creation/source-manager.js +0 -0
- package/dist/notebook-creation/studio-manager-base.d.ts +57 -0
- package/dist/notebook-creation/studio-manager-base.js +67 -0
- package/dist/notebook-creation/types.d.ts +0 -1
- package/dist/notebook-creation/types.js +0 -1
- package/dist/notebook-creation/video-manager.d.ts +3 -16
- package/dist/notebook-creation/video-manager.js +94 -53
- package/dist/observability/metrics.d.ts +0 -1
- package/dist/observability/metrics.js +0 -1
- package/dist/quota/index.d.ts +0 -1
- package/dist/quota/index.js +0 -1
- package/dist/quota/quota-manager.d.ts +59 -4
- package/dist/quota/quota-manager.js +195 -46
- package/dist/resources/resource-handlers.d.ts +0 -1
- package/dist/resources/resource-handlers.js +33 -3
- package/dist/session/browser-session.d.ts +0 -1
- package/dist/session/browser-session.js +0 -1
- package/dist/session/session-manager.d.ts +0 -1
- package/dist/session/session-manager.js +0 -1
- package/dist/session/session-timeout.d.ts +0 -1
- package/dist/session/session-timeout.js +0 -1
- package/dist/session/shared-context-manager.d.ts +0 -1
- package/dist/session/shared-context-manager.js +0 -1
- package/dist/tools/annotations.d.ts +0 -1
- package/dist/tools/annotations.js +0 -1
- package/dist/tools/definitions/ask-question.d.ts +6 -3
- package/dist/tools/definitions/ask-question.js +12 -8
- package/dist/tools/definitions/chat-history.d.ts +0 -1
- package/dist/tools/definitions/chat-history.js +1 -1
- package/dist/tools/definitions/data-tables.d.ts +0 -1
- package/dist/tools/definitions/data-tables.js +4 -1
- package/dist/tools/definitions/gemini.d.ts +0 -1
- package/dist/tools/definitions/gemini.js +14 -7
- package/dist/tools/definitions/notebook-management.d.ts +0 -1
- package/dist/tools/definitions/notebook-management.js +7 -2
- package/dist/tools/definitions/query-history.d.ts +0 -1
- package/dist/tools/definitions/query-history.js +0 -1
- package/dist/tools/definitions/session-management.d.ts +0 -1
- package/dist/tools/definitions/session-management.js +0 -1
- package/dist/tools/definitions/system.d.ts +0 -1
- package/dist/tools/definitions/system.js +32 -12
- package/dist/tools/definitions/video.d.ts +0 -1
- package/dist/tools/definitions/video.js +6 -3
- package/dist/tools/definitions.d.ts +0 -1
- package/dist/tools/definitions.js +0 -1
- package/dist/tools/handlers/ask-question.d.ts +0 -1
- package/dist/tools/handlers/ask-question.js +47 -18
- package/dist/tools/handlers/audio-video.d.ts +0 -1
- package/dist/tools/handlers/audio-video.js +0 -1
- package/dist/tools/handlers/auth.d.ts +0 -1
- package/dist/tools/handlers/auth.js +0 -1
- package/dist/tools/handlers/error-utils.d.ts +0 -1
- package/dist/tools/handlers/error-utils.js +0 -1
- package/dist/tools/handlers/gemini.d.ts +0 -1
- package/dist/tools/handlers/gemini.js +0 -1
- package/dist/tools/handlers/index.d.ts +0 -1
- package/dist/tools/handlers/index.js +0 -1
- package/dist/tools/handlers/notebook-creation.d.ts +0 -1
- package/dist/tools/handlers/notebook-creation.js +16 -1
- package/dist/tools/handlers/notebook-management.d.ts +0 -1
- package/dist/tools/handlers/notebook-management.js +7 -2
- package/dist/tools/handlers/session-management.d.ts +0 -1
- package/dist/tools/handlers/session-management.js +0 -1
- package/dist/tools/handlers/system.d.ts +0 -1
- package/dist/tools/handlers/system.js +0 -1
- package/dist/tools/handlers/types.d.ts +0 -1
- package/dist/tools/handlers/types.js +0 -1
- package/dist/tools/handlers/webhooks.d.ts +0 -1
- package/dist/tools/handlers/webhooks.js +0 -1
- package/dist/tools/icons.d.ts +0 -1
- package/dist/tools/icons.js +0 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -1
- package/dist/utils/audit-logger.d.ts +11 -1
- package/dist/utils/audit-logger.js +189 -21
- package/dist/utils/cleanup-manager.d.ts +0 -1
- package/dist/utils/cleanup-manager.js +0 -1
- package/dist/utils/cli-handler.d.ts +0 -1
- package/dist/utils/cli-handler.js +0 -1
- package/dist/utils/crypto.d.ts +18 -9
- package/dist/utils/crypto.js +93 -28
- package/dist/utils/file-lock.d.ts +15 -1
- package/dist/utils/file-lock.js +67 -59
- package/dist/utils/file-permissions.d.ts +0 -1
- package/dist/utils/file-permissions.js +35 -7
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +0 -1
- package/dist/utils/page-utils.d.ts +0 -1
- package/dist/utils/page-utils.js +32 -28
- package/dist/utils/response-validator.d.ts +0 -1
- package/dist/utils/response-validator.js +18 -15
- package/dist/utils/secrets-scanner.d.ts +0 -1
- package/dist/utils/secrets-scanner.js +32 -7
- package/dist/utils/secure-memory.d.ts +34 -16
- package/dist/utils/secure-memory.js +40 -25
- package/dist/utils/security.d.ts +0 -1
- package/dist/utils/security.js +66 -39
- package/dist/utils/settings-manager.d.ts +9 -1
- package/dist/utils/settings-manager.js +45 -2
- package/dist/utils/stealth-utils.d.ts +0 -1
- package/dist/utils/stealth-utils.js +11 -9
- package/dist/webhooks/index.d.ts +0 -1
- package/dist/webhooks/index.js +0 -1
- package/dist/webhooks/types.d.ts +0 -1
- package/dist/webhooks/types.js +0 -1
- package/dist/webhooks/webhook-dispatcher.d.ts +0 -1
- package/dist/webhooks/webhook-dispatcher.js +0 -1
- package/package.json +5 -4
- package/dist/auth/auth-manager.d.ts.map +0 -1
- package/dist/auth/auth-manager.js.map +0 -1
- package/dist/auth/mcp-auth.d.ts.map +0 -1
- package/dist/auth/mcp-auth.js.map +0 -1
- package/dist/compliance/alert-manager.d.ts.map +0 -1
- package/dist/compliance/alert-manager.js.map +0 -1
- package/dist/compliance/breach-detection.d.ts.map +0 -1
- package/dist/compliance/breach-detection.js.map +0 -1
- package/dist/compliance/change-log.d.ts.map +0 -1
- package/dist/compliance/change-log.js.map +0 -1
- package/dist/compliance/compliance-logger.d.ts.map +0 -1
- package/dist/compliance/compliance-logger.js.map +0 -1
- package/dist/compliance/compliance-tools.d.ts.map +0 -1
- package/dist/compliance/compliance-tools.js.map +0 -1
- package/dist/compliance/consent-manager.d.ts.map +0 -1
- package/dist/compliance/consent-manager.js.map +0 -1
- package/dist/compliance/dashboard.d.ts.map +0 -1
- package/dist/compliance/dashboard.js.map +0 -1
- package/dist/compliance/data-classification.d.ts.map +0 -1
- package/dist/compliance/data-classification.js.map +0 -1
- package/dist/compliance/data-erasure.d.ts.map +0 -1
- package/dist/compliance/data-erasure.js.map +0 -1
- package/dist/compliance/data-export.d.ts.map +0 -1
- package/dist/compliance/data-export.js.map +0 -1
- package/dist/compliance/data-inventory.d.ts.map +0 -1
- package/dist/compliance/data-inventory.js.map +0 -1
- package/dist/compliance/dsar-handler.d.ts.map +0 -1
- package/dist/compliance/dsar-handler.js.map +0 -1
- package/dist/compliance/evidence-collector.d.ts.map +0 -1
- package/dist/compliance/evidence-collector.js.map +0 -1
- package/dist/compliance/health-monitor.d.ts.map +0 -1
- package/dist/compliance/health-monitor.js.map +0 -1
- package/dist/compliance/incident-manager.d.ts.map +0 -1
- package/dist/compliance/incident-manager.js.map +0 -1
- package/dist/compliance/index.d.ts.map +0 -1
- package/dist/compliance/index.js.map +0 -1
- package/dist/compliance/policy-docs.d.ts.map +0 -1
- package/dist/compliance/policy-docs.js.map +0 -1
- package/dist/compliance/privacy-notice-text.d.ts.map +0 -1
- package/dist/compliance/privacy-notice-text.js.map +0 -1
- package/dist/compliance/privacy-notice.d.ts.map +0 -1
- package/dist/compliance/privacy-notice.js.map +0 -1
- package/dist/compliance/report-generator.d.ts.map +0 -1
- package/dist/compliance/report-generator.js.map +0 -1
- package/dist/compliance/retention-engine.d.ts.map +0 -1
- package/dist/compliance/retention-engine.js.map +0 -1
- package/dist/compliance/siem-exporter.d.ts.map +0 -1
- package/dist/compliance/siem-exporter.js.map +0 -1
- package/dist/compliance/types.d.ts.map +0 -1
- package/dist/compliance/types.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/events/event-emitter.d.ts.map +0 -1
- package/dist/events/event-emitter.js.map +0 -1
- package/dist/events/event-types.d.ts.map +0 -1
- package/dist/events/event-types.js.map +0 -1
- package/dist/gemini/gemini-client.d.ts.map +0 -1
- package/dist/gemini/gemini-client.js.map +0 -1
- package/dist/gemini/index.d.ts.map +0 -1
- package/dist/gemini/index.js.map +0 -1
- package/dist/gemini/pdf-chunker.d.ts.map +0 -1
- package/dist/gemini/pdf-chunker.js.map +0 -1
- package/dist/gemini/types.d.ts.map +0 -1
- package/dist/gemini/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/library/notebook-library.d.ts.map +0 -1
- package/dist/library/notebook-library.js.map +0 -1
- package/dist/library/types.d.ts.map +0 -1
- package/dist/library/types.js.map +0 -1
- package/dist/logging/index.d.ts.map +0 -1
- package/dist/logging/index.js.map +0 -1
- package/dist/logging/query-logger.d.ts.map +0 -1
- package/dist/logging/query-logger.js.map +0 -1
- package/dist/notebook-creation/audio-manager.d.ts.map +0 -1
- package/dist/notebook-creation/audio-manager.js.map +0 -1
- package/dist/notebook-creation/browser-options.d.ts.map +0 -1
- package/dist/notebook-creation/browser-options.js.map +0 -1
- package/dist/notebook-creation/data-table-manager.d.ts.map +0 -1
- package/dist/notebook-creation/data-table-manager.js.map +0 -1
- package/dist/notebook-creation/discover-creation-flow.d.ts +0 -2
- package/dist/notebook-creation/discover-creation-flow.d.ts.map +0 -1
- package/dist/notebook-creation/discover-creation-flow.js +0 -177
- package/dist/notebook-creation/discover-creation-flow.js.map +0 -1
- package/dist/notebook-creation/discover-quota.d.ts +0 -2
- package/dist/notebook-creation/discover-quota.d.ts.map +0 -1
- package/dist/notebook-creation/discover-quota.js +0 -194
- package/dist/notebook-creation/discover-quota.js.map +0 -1
- package/dist/notebook-creation/discover-source-dialog.d.ts +0 -8
- package/dist/notebook-creation/discover-source-dialog.d.ts.map +0 -1
- package/dist/notebook-creation/discover-source-dialog.js +0 -134
- package/dist/notebook-creation/discover-source-dialog.js.map +0 -1
- package/dist/notebook-creation/discover-sources.d.ts +0 -8
- package/dist/notebook-creation/discover-sources.d.ts.map +0 -1
- package/dist/notebook-creation/discover-sources.js +0 -272
- package/dist/notebook-creation/discover-sources.js.map +0 -1
- package/dist/notebook-creation/discover-text-input.d.ts +0 -7
- package/dist/notebook-creation/discover-text-input.d.ts.map +0 -1
- package/dist/notebook-creation/discover-text-input.js +0 -135
- package/dist/notebook-creation/discover-text-input.js.map +0 -1
- package/dist/notebook-creation/dom-scripts.d.ts.map +0 -1
- package/dist/notebook-creation/dom-scripts.js.map +0 -1
- package/dist/notebook-creation/errors.d.ts.map +0 -1
- package/dist/notebook-creation/errors.js.map +0 -1
- package/dist/notebook-creation/index.d.ts.map +0 -1
- package/dist/notebook-creation/index.js.map +0 -1
- package/dist/notebook-creation/notebook-creator.d.ts.map +0 -1
- package/dist/notebook-creation/notebook-creator.js.map +0 -1
- package/dist/notebook-creation/notebook-nav.d.ts.map +0 -1
- package/dist/notebook-creation/notebook-nav.js.map +0 -1
- package/dist/notebook-creation/notebook-sync.d.ts.map +0 -1
- package/dist/notebook-creation/notebook-sync.js.map +0 -1
- package/dist/notebook-creation/run-discovery.d.ts +0 -11
- package/dist/notebook-creation/run-discovery.d.ts.map +0 -1
- package/dist/notebook-creation/run-discovery.js +0 -151
- package/dist/notebook-creation/run-discovery.js.map +0 -1
- package/dist/notebook-creation/selector-discovery.d.ts +0 -65
- package/dist/notebook-creation/selector-discovery.d.ts.map +0 -1
- package/dist/notebook-creation/selector-discovery.js +0 -414
- package/dist/notebook-creation/selector-discovery.js.map +0 -1
- package/dist/notebook-creation/selectors.d.ts.map +0 -1
- package/dist/notebook-creation/selectors.js.map +0 -1
- package/dist/notebook-creation/selectors.ts +0 -112
- package/dist/notebook-creation/source-manager.d.ts.map +0 -1
- package/dist/notebook-creation/source-manager.js.map +0 -1
- package/dist/notebook-creation/test-create.d.ts +0 -8
- package/dist/notebook-creation/test-create.d.ts.map +0 -1
- package/dist/notebook-creation/test-create.js +0 -72
- package/dist/notebook-creation/test-create.js.map +0 -1
- package/dist/notebook-creation/types.d.ts.map +0 -1
- package/dist/notebook-creation/types.js.map +0 -1
- package/dist/notebook-creation/video-manager.d.ts.map +0 -1
- package/dist/notebook-creation/video-manager.js.map +0 -1
- package/dist/observability/metrics.d.ts.map +0 -1
- package/dist/observability/metrics.js.map +0 -1
- package/dist/quota/index.d.ts.map +0 -1
- package/dist/quota/index.js.map +0 -1
- package/dist/quota/quota-manager.d.ts.map +0 -1
- package/dist/quota/quota-manager.js.map +0 -1
- package/dist/resources/resource-handlers.d.ts.map +0 -1
- package/dist/resources/resource-handlers.js.map +0 -1
- package/dist/session/browser-session.d.ts.map +0 -1
- package/dist/session/browser-session.js.map +0 -1
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/session/session-manager.js.map +0 -1
- package/dist/session/session-timeout.d.ts.map +0 -1
- package/dist/session/session-timeout.js.map +0 -1
- package/dist/session/shared-context-manager.d.ts.map +0 -1
- package/dist/session/shared-context-manager.js.map +0 -1
- package/dist/tools/annotations.d.ts.map +0 -1
- package/dist/tools/annotations.js.map +0 -1
- package/dist/tools/definitions/ask-question.d.ts.map +0 -1
- package/dist/tools/definitions/ask-question.js.map +0 -1
- package/dist/tools/definitions/chat-history.d.ts.map +0 -1
- package/dist/tools/definitions/chat-history.js.map +0 -1
- package/dist/tools/definitions/data-tables.d.ts.map +0 -1
- package/dist/tools/definitions/data-tables.js.map +0 -1
- package/dist/tools/definitions/gemini.d.ts.map +0 -1
- package/dist/tools/definitions/gemini.js.map +0 -1
- package/dist/tools/definitions/notebook-management.d.ts.map +0 -1
- package/dist/tools/definitions/notebook-management.js.map +0 -1
- package/dist/tools/definitions/query-history.d.ts.map +0 -1
- package/dist/tools/definitions/query-history.js.map +0 -1
- package/dist/tools/definitions/session-management.d.ts.map +0 -1
- package/dist/tools/definitions/session-management.js.map +0 -1
- package/dist/tools/definitions/system.d.ts.map +0 -1
- package/dist/tools/definitions/system.js.map +0 -1
- package/dist/tools/definitions/video.d.ts.map +0 -1
- package/dist/tools/definitions/video.js.map +0 -1
- package/dist/tools/definitions.d.ts.map +0 -1
- package/dist/tools/definitions.js.map +0 -1
- package/dist/tools/handlers/ask-question.d.ts.map +0 -1
- package/dist/tools/handlers/ask-question.js.map +0 -1
- package/dist/tools/handlers/audio-video.d.ts.map +0 -1
- package/dist/tools/handlers/audio-video.js.map +0 -1
- package/dist/tools/handlers/auth.d.ts.map +0 -1
- package/dist/tools/handlers/auth.js.map +0 -1
- package/dist/tools/handlers/error-utils.d.ts.map +0 -1
- package/dist/tools/handlers/error-utils.js.map +0 -1
- package/dist/tools/handlers/gemini.d.ts.map +0 -1
- package/dist/tools/handlers/gemini.js.map +0 -1
- package/dist/tools/handlers/index.d.ts.map +0 -1
- package/dist/tools/handlers/index.js.map +0 -1
- package/dist/tools/handlers/notebook-creation.d.ts.map +0 -1
- package/dist/tools/handlers/notebook-creation.js.map +0 -1
- package/dist/tools/handlers/notebook-management.d.ts.map +0 -1
- package/dist/tools/handlers/notebook-management.js.map +0 -1
- package/dist/tools/handlers/session-management.d.ts.map +0 -1
- package/dist/tools/handlers/session-management.js.map +0 -1
- package/dist/tools/handlers/system.d.ts.map +0 -1
- package/dist/tools/handlers/system.js.map +0 -1
- package/dist/tools/handlers/types.d.ts.map +0 -1
- package/dist/tools/handlers/types.js.map +0 -1
- package/dist/tools/handlers/webhooks.d.ts.map +0 -1
- package/dist/tools/handlers/webhooks.js.map +0 -1
- package/dist/tools/handlers.d.ts +0 -666
- package/dist/tools/handlers.d.ts.map +0 -1
- package/dist/tools/handlers.js +0 -2929
- package/dist/tools/handlers.js.map +0 -1
- package/dist/tools/icons.d.ts.map +0 -1
- package/dist/tools/icons.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/audit-logger.d.ts.map +0 -1
- package/dist/utils/audit-logger.js.map +0 -1
- package/dist/utils/cert-pinning.d.ts +0 -97
- package/dist/utils/cert-pinning.d.ts.map +0 -1
- package/dist/utils/cert-pinning.js +0 -328
- package/dist/utils/cert-pinning.js.map +0 -1
- package/dist/utils/cleanup-manager.d.ts.map +0 -1
- package/dist/utils/cleanup-manager.js.map +0 -1
- package/dist/utils/cli-handler.d.ts.map +0 -1
- package/dist/utils/cli-handler.js.map +0 -1
- package/dist/utils/crypto.d.ts.map +0 -1
- package/dist/utils/crypto.js.map +0 -1
- package/dist/utils/file-lock.d.ts.map +0 -1
- package/dist/utils/file-lock.js.map +0 -1
- package/dist/utils/file-permissions.d.ts.map +0 -1
- package/dist/utils/file-permissions.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/page-utils.d.ts.map +0 -1
- package/dist/utils/page-utils.js.map +0 -1
- package/dist/utils/response-validator.d.ts.map +0 -1
- package/dist/utils/response-validator.js.map +0 -1
- package/dist/utils/secrets-scanner.d.ts.map +0 -1
- package/dist/utils/secrets-scanner.js.map +0 -1
- package/dist/utils/secure-memory.d.ts.map +0 -1
- package/dist/utils/secure-memory.js.map +0 -1
- package/dist/utils/security.d.ts.map +0 -1
- package/dist/utils/security.js.map +0 -1
- package/dist/utils/settings-manager.d.ts.map +0 -1
- package/dist/utils/settings-manager.js.map +0 -1
- package/dist/utils/stealth-utils.d.ts.map +0 -1
- package/dist/utils/stealth-utils.js.map +0 -1
- package/dist/utils/tool-validation.d.ts +0 -93
- package/dist/utils/tool-validation.d.ts.map +0 -1
- package/dist/utils/tool-validation.js +0 -277
- package/dist/utils/tool-validation.js.map +0 -1
- package/dist/webhooks/index.d.ts.map +0 -1
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/types.d.ts.map +0 -1
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/webhook-dispatcher.d.ts.map +0 -1
- package/dist/webhooks/webhook-dispatcher.js.map +0 -1
- package/docs/COMPLIANCE-SPEC.md +0 -1452
- package/docs/MCP-DIRECTORY-LISTINGS.md +0 -91
- package/docs/SECURITY-FORK-OPPORTUNITIES.md +0 -79
- package/docs/SECURITY_IMPLEMENTATION_PLAN.md +0 -437
- package/docs/archive/ISSUES-legacy-2026-04-24.md +0 -644
- package/docs/configuration.md +0 -94
- package/docs/dependency-risk.md +0 -25
- package/docs/improvement-sprint-2026.2.10.md +0 -210
- package/docs/testing-runbook.md +0 -166
- package/docs/tools.md +0 -34
- package/docs/troubleshooting.md +0 -59
- 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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
|
@@ -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
|
|
@@ -29,7 +29,16 @@ export class NotebookNavigation {
|
|
|
29
29
|
}
|
|
30
30
|
async initialize(headless) {
|
|
31
31
|
log.info("🌐 Initializing browser for notebook creation...");
|
|
32
|
-
|
|
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
|
-
|
|
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
|
|
100
|
-
const ariaLabel = el.getAttribute("aria-label")
|
|
101
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
309
|
-
|
|
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
|
|
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
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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
|
|
425
|
-
|
|
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
|
|
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
|
-
|
|
478
|
+
fuzzyMatchIndex = i;
|
|
435
479
|
break;
|
|
436
480
|
}
|
|
437
481
|
}
|
|
438
482
|
}
|
|
439
|
-
if (
|
|
440
|
-
const matchingActual = actualNotebooks[
|
|
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(
|
|
448
|
-
//
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
488
|
-
|
|
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
|
|
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
|
-
|
|
519
|
-
|
|
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
|