@fraziym/axoniz 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/agents/definition.d.ts +15 -0
- package/dist/agents/definition.d.ts.map +1 -0
- package/dist/agents/definition.js +41 -0
- package/dist/agents/definition.js.map +1 -0
- package/dist/agents/index.d.ts +12 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +11 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/registry.d.ts +17 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +23 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/specialized.d.ts +31 -0
- package/dist/agents/specialized.d.ts.map +1 -0
- package/dist/agents/specialized.js +75 -0
- package/dist/agents/specialized.js.map +1 -0
- package/dist/awareness/index.d.ts +14 -0
- package/dist/awareness/index.d.ts.map +1 -0
- package/dist/awareness/index.js +22 -0
- package/dist/awareness/index.js.map +1 -0
- package/dist/awareness/service.d.ts +180 -0
- package/dist/awareness/service.d.ts.map +1 -0
- package/dist/awareness/service.js +789 -0
- package/dist/awareness/service.js.map +1 -0
- package/dist/cli/entry.d.ts +13 -0
- package/dist/cli/entry.d.ts.map +1 -0
- package/dist/cli/entry.js +35 -0
- package/dist/cli/entry.js.map +1 -0
- package/dist/comms/telegram.d.ts +41 -0
- package/dist/comms/telegram.d.ts.map +1 -0
- package/dist/comms/telegram.js +332 -0
- package/dist/comms/telegram.js.map +1 -0
- package/dist/core/agent.d.ts +252 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +1399 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/auth.d.ts +23 -0
- package/dist/core/auth.d.ts.map +1 -0
- package/dist/core/auth.js +113 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/authority.d.ts +118 -0
- package/dist/core/authority.d.ts.map +1 -0
- package/dist/core/authority.js +402 -0
- package/dist/core/authority.js.map +1 -0
- package/dist/core/backend/async_queue.d.ts +17 -0
- package/dist/core/backend/async_queue.d.ts.map +1 -0
- package/dist/core/backend/async_queue.js +66 -0
- package/dist/core/backend/async_queue.js.map +1 -0
- package/dist/core/backend/index.d.ts +24 -0
- package/dist/core/backend/index.d.ts.map +1 -0
- package/dist/core/backend/index.js +128 -0
- package/dist/core/backend/index.js.map +1 -0
- package/dist/core/backend/llama_server.d.ts +39 -0
- package/dist/core/backend/llama_server.d.ts.map +1 -0
- package/dist/core/backend/llama_server.js +182 -0
- package/dist/core/backend/llama_server.js.map +1 -0
- package/dist/core/backend/llamacpp.d.ts +40 -0
- package/dist/core/backend/llamacpp.d.ts.map +1 -0
- package/dist/core/backend/llamacpp.js +200 -0
- package/dist/core/backend/llamacpp.js.map +1 -0
- package/dist/core/backend/lmstudio.d.ts +53 -0
- package/dist/core/backend/lmstudio.d.ts.map +1 -0
- package/dist/core/backend/lmstudio.js +274 -0
- package/dist/core/backend/lmstudio.js.map +1 -0
- package/dist/core/backend/ollama.d.ts +25 -0
- package/dist/core/backend/ollama.d.ts.map +1 -0
- package/dist/core/backend/ollama.js +86 -0
- package/dist/core/backend/ollama.js.map +1 -0
- package/dist/core/backend/openai.d.ts +27 -0
- package/dist/core/backend/openai.d.ts.map +1 -0
- package/dist/core/backend/openai.js +84 -0
- package/dist/core/backend/openai.js.map +1 -0
- package/dist/core/backend/types.d.ts +73 -0
- package/dist/core/backend/types.d.ts.map +1 -0
- package/dist/core/backend/types.js +137 -0
- package/dist/core/backend/types.js.map +1 -0
- package/dist/core/chat_store.d.ts +77 -0
- package/dist/core/chat_store.d.ts.map +1 -0
- package/dist/core/chat_store.js +332 -0
- package/dist/core/chat_store.js.map +1 -0
- package/dist/core/cli.d.ts +82 -0
- package/dist/core/cli.d.ts.map +1 -0
- package/dist/core/cli.js +602 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/config.d.ts +127 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +295 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/debug.d.ts +8 -0
- package/dist/core/debug.d.ts.map +1 -0
- package/dist/core/debug.js +8 -0
- package/dist/core/debug.js.map +1 -0
- package/dist/core/downloader.d.ts +31 -0
- package/dist/core/downloader.d.ts.map +1 -0
- package/dist/core/downloader.js +180 -0
- package/dist/core/downloader.js.map +1 -0
- package/dist/core/errors.d.ts +80 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +134 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/extras.d.ts +160 -0
- package/dist/core/extras.d.ts.map +1 -0
- package/dist/core/extras.js +553 -0
- package/dist/core/extras.js.map +1 -0
- package/dist/core/health.d.ts +27 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +96 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/history.d.ts +50 -0
- package/dist/core/history.d.ts.map +1 -0
- package/dist/core/history.js +276 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/intelligence/ast_index.d.ts +255 -0
- package/dist/core/intelligence/ast_index.d.ts.map +1 -0
- package/dist/core/intelligence/ast_index.js +1369 -0
- package/dist/core/intelligence/ast_index.js.map +1 -0
- package/dist/core/intelligence/confidence.d.ts +113 -0
- package/dist/core/intelligence/confidence.d.ts.map +1 -0
- package/dist/core/intelligence/confidence.js +298 -0
- package/dist/core/intelligence/confidence.js.map +1 -0
- package/dist/core/intelligence/context_compressor.d.ts +80 -0
- package/dist/core/intelligence/context_compressor.d.ts.map +1 -0
- package/dist/core/intelligence/context_compressor.js +245 -0
- package/dist/core/intelligence/context_compressor.js.map +1 -0
- package/dist/core/intelligence/daemon.d.ts +247 -0
- package/dist/core/intelligence/daemon.d.ts.map +1 -0
- package/dist/core/intelligence/daemon.js +842 -0
- package/dist/core/intelligence/daemon.js.map +1 -0
- package/dist/core/intelligence/index.d.ts +60 -0
- package/dist/core/intelligence/index.d.ts.map +1 -0
- package/dist/core/intelligence/index.js +101 -0
- package/dist/core/intelligence/index.js.map +1 -0
- package/dist/core/intelligence/predictor.d.ts +246 -0
- package/dist/core/intelligence/predictor.d.ts.map +1 -0
- package/dist/core/intelligence/predictor.js +590 -0
- package/dist/core/intelligence/predictor.js.map +1 -0
- package/dist/core/intelligence/reflex.d.ts +84 -0
- package/dist/core/intelligence/reflex.d.ts.map +1 -0
- package/dist/core/intelligence/reflex.js +344 -0
- package/dist/core/intelligence/reflex.js.map +1 -0
- package/dist/core/intelligence/self_correction.d.ts +121 -0
- package/dist/core/intelligence/self_correction.d.ts.map +1 -0
- package/dist/core/intelligence/self_correction.js +327 -0
- package/dist/core/intelligence/self_correction.js.map +1 -0
- package/dist/core/intelligence/skill_distiller.d.ts +100 -0
- package/dist/core/intelligence/skill_distiller.d.ts.map +1 -0
- package/dist/core/intelligence/skill_distiller.js +246 -0
- package/dist/core/intelligence/skill_distiller.js.map +1 -0
- package/dist/core/intelligence/swarm.d.ts +330 -0
- package/dist/core/intelligence/swarm.d.ts.map +1 -0
- package/dist/core/intelligence/swarm.js +1064 -0
- package/dist/core/intelligence/swarm.js.map +1 -0
- package/dist/core/intelligence/trajectory.d.ts +107 -0
- package/dist/core/intelligence/trajectory.d.ts.map +1 -0
- package/dist/core/intelligence/trajectory.js +330 -0
- package/dist/core/intelligence/trajectory.js.map +1 -0
- package/dist/core/logger.d.ts +111 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +640 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/loop.d.ts +123 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +423 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/memory.d.ts +81 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +328 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/metrics.d.ts +29 -0
- package/dist/core/metrics.d.ts.map +1 -0
- package/dist/core/metrics.js +109 -0
- package/dist/core/metrics.js.map +1 -0
- package/dist/core/models.d.ts +51 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +146 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/optimizer.d.ts +34 -0
- package/dist/core/optimizer.d.ts.map +1 -0
- package/dist/core/optimizer.js +131 -0
- package/dist/core/optimizer.js.map +1 -0
- package/dist/core/persona.d.ts +35 -0
- package/dist/core/persona.d.ts.map +1 -0
- package/dist/core/persona.js +126 -0
- package/dist/core/persona.js.map +1 -0
- package/dist/core/rate_limit.d.ts +23 -0
- package/dist/core/rate_limit.d.ts.map +1 -0
- package/dist/core/rate_limit.js +62 -0
- package/dist/core/rate_limit.js.map +1 -0
- package/dist/core/runner.d.ts +63 -0
- package/dist/core/runner.d.ts.map +1 -0
- package/dist/core/runner.js +671 -0
- package/dist/core/runner.js.map +1 -0
- package/dist/core/stream_parser.d.ts +43 -0
- package/dist/core/stream_parser.d.ts.map +1 -0
- package/dist/core/stream_parser.js +140 -0
- package/dist/core/stream_parser.js.map +1 -0
- package/dist/core/tool_schemas.d.ts +26 -0
- package/dist/core/tool_schemas.d.ts.map +1 -0
- package/dist/core/tool_schemas.js +124 -0
- package/dist/core/tool_schemas.js.map +1 -0
- package/dist/core/which.d.ts +2 -0
- package/dist/core/which.d.ts.map +1 -0
- package/dist/core/which.js +35 -0
- package/dist/core/which.js.map +1 -0
- package/dist/goals/index.d.ts +9 -0
- package/dist/goals/index.d.ts.map +1 -0
- package/dist/goals/index.js +17 -0
- package/dist/goals/index.js.map +1 -0
- package/dist/goals/service.d.ts +115 -0
- package/dist/goals/service.d.ts.map +1 -0
- package/dist/goals/service.js +415 -0
- package/dist/goals/service.js.map +1 -0
- package/dist/goals/types.d.ts +47 -0
- package/dist/goals/types.d.ts.map +1 -0
- package/dist/goals/types.js +66 -0
- package/dist/goals/types.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/autonomous_startup.d.ts +51 -0
- package/dist/integrations/autonomous_startup.d.ts.map +1 -0
- package/dist/integrations/autonomous_startup.js +419 -0
- package/dist/integrations/autonomous_startup.js.map +1 -0
- package/dist/integrations/goose.d.ts +105 -0
- package/dist/integrations/goose.d.ts.map +1 -0
- package/dist/integrations/goose.js +408 -0
- package/dist/integrations/goose.js.map +1 -0
- package/dist/integrations/index.d.ts +21 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +17 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/mcp.d.ts +73 -0
- package/dist/integrations/mcp.d.ts.map +1 -0
- package/dist/integrations/mcp.js +307 -0
- package/dist/integrations/mcp.js.map +1 -0
- package/dist/integrations/mempalace.d.ts +18 -0
- package/dist/integrations/mempalace.d.ts.map +1 -0
- package/dist/integrations/mempalace.js +25 -0
- package/dist/integrations/mempalace.js.map +1 -0
- package/dist/integrations/multi_agent.d.ts +82 -0
- package/dist/integrations/multi_agent.d.ts.map +1 -0
- package/dist/integrations/multi_agent.js +280 -0
- package/dist/integrations/multi_agent.js.map +1 -0
- package/dist/integrations/unified_memory.d.ts +415 -0
- package/dist/integrations/unified_memory.d.ts.map +1 -0
- package/dist/integrations/unified_memory.js +1489 -0
- package/dist/integrations/unified_memory.js.map +1 -0
- package/dist/roles/beru.yaml +48 -0
- package/dist/sidecar/client.d.ts +63 -0
- package/dist/sidecar/client.d.ts.map +1 -0
- package/dist/sidecar/client.js +222 -0
- package/dist/sidecar/client.js.map +1 -0
- package/dist/sidecar/index.d.ts +7 -0
- package/dist/sidecar/index.d.ts.map +1 -0
- package/dist/sidecar/index.js +6 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/startup.d.ts +22 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +194 -0
- package/dist/startup.js.map +1 -0
- package/dist/tools/_internal.d.ts +90 -0
- package/dist/tools/_internal.d.ts.map +1 -0
- package/dist/tools/_internal.js +375 -0
- package/dist/tools/_internal.js.map +1 -0
- package/dist/tools/_smoke.d.ts +2 -0
- package/dist/tools/_smoke.d.ts.map +1 -0
- package/dist/tools/_smoke.js +203 -0
- package/dist/tools/_smoke.js.map +1 -0
- package/dist/tools/axodex_tools.d.ts +51 -0
- package/dist/tools/axodex_tools.d.ts.map +1 -0
- package/dist/tools/axodex_tools.js +181 -0
- package/dist/tools/axodex_tools.js.map +1 -0
- package/dist/tools/code_tools.d.ts +33 -0
- package/dist/tools/code_tools.d.ts.map +1 -0
- package/dist/tools/code_tools.js +191 -0
- package/dist/tools/code_tools.js.map +1 -0
- package/dist/tools/computer_tools.d.ts +59 -0
- package/dist/tools/computer_tools.d.ts.map +1 -0
- package/dist/tools/computer_tools.js +348 -0
- package/dist/tools/computer_tools.js.map +1 -0
- package/dist/tools/file_tools.d.ts +51 -0
- package/dist/tools/file_tools.d.ts.map +1 -0
- package/dist/tools/file_tools.js +424 -0
- package/dist/tools/file_tools.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +13 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/shell_tools.d.ts +39 -0
- package/dist/tools/shell_tools.d.ts.map +1 -0
- package/dist/tools/shell_tools.js +163 -0
- package/dist/tools/shell_tools.js.map +1 -0
- package/dist/tools/web_tools.d.ts +31 -0
- package/dist/tools/web_tools.d.ts.map +1 -0
- package/dist/tools/web_tools.js +117 -0
- package/dist/tools/web_tools.js.map +1 -0
- package/dist/voice/index.d.ts +41 -0
- package/dist/voice/index.d.ts.map +1 -0
- package/dist/voice/index.js +58 -0
- package/dist/voice/index.js.map +1 -0
- package/dist/voice/light_daemon.d.ts +197 -0
- package/dist/voice/light_daemon.d.ts.map +1 -0
- package/dist/voice/light_daemon.js +746 -0
- package/dist/voice/light_daemon.js.map +1 -0
- package/dist/voice/setup.d.ts +63 -0
- package/dist/voice/setup.d.ts.map +1 -0
- package/dist/voice/setup.js +443 -0
- package/dist/voice/setup.js.map +1 -0
- package/dist/voice/stt.d.ts +148 -0
- package/dist/voice/stt.d.ts.map +1 -0
- package/dist/voice/stt.js +361 -0
- package/dist/voice/stt.js.map +1 -0
- package/dist/voice/tts.d.ts +168 -0
- package/dist/voice/tts.d.ts.map +1 -0
- package/dist/voice/tts.js +698 -0
- package/dist/voice/tts.js.map +1 -0
- package/dist/voice/voice_loop.d.ts +101 -0
- package/dist/voice/voice_loop.d.ts.map +1 -0
- package/dist/voice/voice_loop.js +463 -0
- package/dist/voice/voice_loop.js.map +1 -0
- package/dist/voice/wake_word.d.ts +153 -0
- package/dist/voice/wake_word.d.ts.map +1 -0
- package/dist/voice/wake_word.js +458 -0
- package/dist/voice/wake_word.js.map +1 -0
- package/dist/voice/wav.d.ts +99 -0
- package/dist/voice/wav.d.ts.map +1 -0
- package/dist/voice/wav.js +306 -0
- package/dist/voice/wav.js.map +1 -0
- package/dist/web/broker.d.ts +33 -0
- package/dist/web/broker.d.ts.map +1 -0
- package/dist/web/broker.js +58 -0
- package/dist/web/broker.js.map +1 -0
- package/dist/web/open_browser.d.ts +2 -0
- package/dist/web/open_browser.d.ts.map +1 -0
- package/dist/web/open_browser.js +42 -0
- package/dist/web/open_browser.js.map +1 -0
- package/dist/web/server.d.ts +54 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +831 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web/static/app.js +4121 -0
- package/dist/web/static/index.html +2281 -0
- package/dist/web/static/js/MODULE_SUMMARY.md +124 -0
- package/dist/web/static/js/a11y.js +165 -0
- package/dist/web/static/js/admin.js +2145 -0
- package/dist/web/static/js/assistant.js +475 -0
- package/dist/web/static/js/calendar/reminders.js +114 -0
- package/dist/web/static/js/calendar/utils.js +166 -0
- package/dist/web/static/js/calendar.js +3348 -0
- package/dist/web/static/js/censor.js +356 -0
- package/dist/web/static/js/chat.js +4546 -0
- package/dist/web/static/js/chatRenderer.js +2294 -0
- package/dist/web/static/js/chatStream.js +276 -0
- package/dist/web/static/js/codeRunner.js +398 -0
- package/dist/web/static/js/color/hex.js +14 -0
- package/dist/web/static/js/colorPicker.js +453 -0
- package/dist/web/static/js/compare/icons.js +77 -0
- package/dist/web/static/js/compare/index.js +1482 -0
- package/dist/web/static/js/compare/models.js +104 -0
- package/dist/web/static/js/compare/panes.js +817 -0
- package/dist/web/static/js/compare/probe.js +78 -0
- package/dist/web/static/js/compare/scoreboard.js +223 -0
- package/dist/web/static/js/compare/selector.js +1335 -0
- package/dist/web/static/js/compare/state.js +58 -0
- package/dist/web/static/js/compare/stream.js +695 -0
- package/dist/web/static/js/compare/vote.js +254 -0
- package/dist/web/static/js/cookbook-diagnosis.js +694 -0
- package/dist/web/static/js/cookbook-hwfit.js +1888 -0
- package/dist/web/static/js/cookbook.js +2093 -0
- package/dist/web/static/js/cookbookDownload.js +633 -0
- package/dist/web/static/js/cookbookProgressSignal.js +29 -0
- package/dist/web/static/js/cookbookRunning.js +3506 -0
- package/dist/web/static/js/cookbookServe.js +2128 -0
- package/dist/web/static/js/document.js +9731 -0
- package/dist/web/static/js/documentLibrary.js +3376 -0
- package/dist/web/static/js/dragSort.js +265 -0
- package/dist/web/static/js/editor/ai-inpaint.js +374 -0
- package/dist/web/static/js/editor/ai-models.js +273 -0
- package/dist/web/static/js/editor/ai-rembg.js +230 -0
- package/dist/web/static/js/editor/ai-tool-runner.js +147 -0
- package/dist/web/static/js/editor/ai-tools-misc.js +216 -0
- package/dist/web/static/js/editor/build/controls.js +366 -0
- package/dist/web/static/js/editor/build/popups.js +112 -0
- package/dist/web/static/js/editor/build/right-panel.js +200 -0
- package/dist/web/static/js/editor/build/toolbar.js +73 -0
- package/dist/web/static/js/editor/build/topbar.js +131 -0
- package/dist/web/static/js/editor/build/transform-popup.js +109 -0
- package/dist/web/static/js/editor/canvas-coords.js +21 -0
- package/dist/web/static/js/editor/canvas-events.js +197 -0
- package/dist/web/static/js/editor/canvas-transforms.js +132 -0
- package/dist/web/static/js/editor/checkerboard.js +24 -0
- package/dist/web/static/js/editor/clipboard-and-drop.js +133 -0
- package/dist/web/static/js/editor/composite-helpers.js +83 -0
- package/dist/web/static/js/editor/filters/blur.js +118 -0
- package/dist/web/static/js/editor/filters/edge-feather.js +70 -0
- package/dist/web/static/js/editor/fx/adj-popup.js +677 -0
- package/dist/web/static/js/editor/fx/filter-string.js +38 -0
- package/dist/web/static/js/editor/fx/histogram.js +67 -0
- package/dist/web/static/js/editor/fx/pixel-pass.js +249 -0
- package/dist/web/static/js/editor/harmonize-masks.js +116 -0
- package/dist/web/static/js/editor/history-panel.js +176 -0
- package/dist/web/static/js/editor/keyboard-shortcuts.js +271 -0
- package/dist/web/static/js/editor/layer-helpers.js +131 -0
- package/dist/web/static/js/editor/layer-panel.js +600 -0
- package/dist/web/static/js/editor/mask-utils.js +91 -0
- package/dist/web/static/js/editor/shortcuts-popover.js +149 -0
- package/dist/web/static/js/editor/slider-ux.js +191 -0
- package/dist/web/static/js/editor/snap.js +107 -0
- package/dist/web/static/js/editor/state.js +257 -0
- package/dist/web/static/js/editor/stroke-pipeline.js +162 -0
- package/dist/web/static/js/editor/stroke-tool-sliders.js +64 -0
- package/dist/web/static/js/editor/tools/clone.js +81 -0
- package/dist/web/static/js/editor/tools/crop.js +137 -0
- package/dist/web/static/js/editor/tools/flood-fill.js +72 -0
- package/dist/web/static/js/editor/tools/lasso-mask.js +171 -0
- package/dist/web/static/js/editor/tools/lasso.js +65 -0
- package/dist/web/static/js/editor/tools/move.js +79 -0
- package/dist/web/static/js/editor/tools/stroke.js +123 -0
- package/dist/web/static/js/editor/tools/transform-drag.js +174 -0
- package/dist/web/static/js/editor/tools/transform-handles.js +271 -0
- package/dist/web/static/js/editor/tools/transform-session.js +381 -0
- package/dist/web/static/js/editor/tools/wand.js +46 -0
- package/dist/web/static/js/editor/wire-import.js +148 -0
- package/dist/web/static/js/editor/wire-inpaint-controls.js +164 -0
- package/dist/web/static/js/editor/wire-merge-buttons.js +103 -0
- package/dist/web/static/js/editor/wire-selection-controls.js +170 -0
- package/dist/web/static/js/editor/wire-topbar-menus.js +174 -0
- package/dist/web/static/js/editor/wire-topbar-overflow.js +49 -0
- package/dist/web/static/js/editor/wire-topbar.js +188 -0
- package/dist/web/static/js/emailInbox.js +1245 -0
- package/dist/web/static/js/emailLibrary/replyRecipients.js +27 -0
- package/dist/web/static/js/emailLibrary/signatureFold.js +339 -0
- package/dist/web/static/js/emailLibrary/state.js +34 -0
- package/dist/web/static/js/emailLibrary/utils.js +202 -0
- package/dist/web/static/js/emailLibrary.js +5217 -0
- package/dist/web/static/js/emojiPicker.js +311 -0
- package/dist/web/static/js/escMenuStack.js +102 -0
- package/dist/web/static/js/fileHandler.js +295 -0
- package/dist/web/static/js/gallery.js +2835 -0
- package/dist/web/static/js/galleryEditor.js +3798 -0
- package/dist/web/static/js/group.js +955 -0
- package/dist/web/static/js/init.js +405 -0
- package/dist/web/static/js/keyboard-shortcuts.js +292 -0
- package/dist/web/static/js/langIcons.js +187 -0
- package/dist/web/static/js/markdown/tableRow.js +19 -0
- package/dist/web/static/js/markdown.js +806 -0
- package/dist/web/static/js/memory.js +1418 -0
- package/dist/web/static/js/modalManager.js +1552 -0
- package/dist/web/static/js/modalSnap.js +782 -0
- package/dist/web/static/js/model/matchKey.js +19 -0
- package/dist/web/static/js/modelPicker.js +695 -0
- package/dist/web/static/js/modelSort.js +33 -0
- package/dist/web/static/js/models.js +642 -0
- package/dist/web/static/js/notes.js +5054 -0
- package/dist/web/static/js/package.json +1 -0
- package/dist/web/static/js/platform.js +47 -0
- package/dist/web/static/js/presets.js +1110 -0
- package/dist/web/static/js/providers.js +93 -0
- package/dist/web/static/js/rag.js +177 -0
- package/dist/web/static/js/research/jobs.js +335 -0
- package/dist/web/static/js/research/panel.js +1233 -0
- package/dist/web/static/js/researchSynapse.js +225 -0
- package/dist/web/static/js/search-chat.js +201 -0
- package/dist/web/static/js/search.js +52 -0
- package/dist/web/static/js/section-management.js +260 -0
- package/dist/web/static/js/sessions.js +3108 -0
- package/dist/web/static/js/settings.js +4991 -0
- package/dist/web/static/js/sidebar-layout.js +573 -0
- package/dist/web/static/js/signature.js +504 -0
- package/dist/web/static/js/skills.js +1908 -0
- package/dist/web/static/js/slashAutocomplete.js +267 -0
- package/dist/web/static/js/slashCommands.js +6099 -0
- package/dist/web/static/js/spinner.js +406 -0
- package/dist/web/static/js/storage.js +123 -0
- package/dist/web/static/js/tasks.js +2699 -0
- package/dist/web/static/js/theme.js +2086 -0
- package/dist/web/static/js/tileManager.js +386 -0
- package/dist/web/static/js/tourAutoplay.js +133 -0
- package/dist/web/static/js/tourHints.js +179 -0
- package/dist/web/static/js/tts-ai.js +521 -0
- package/dist/web/static/js/ui.js +1288 -0
- package/dist/web/static/js/util/ordinal.js +13 -0
- package/dist/web/static/js/voiceRecorder.js +283 -0
- package/dist/web/static/js/windowDrag.js +326 -0
- package/dist/web/static/js/windowResize.js +233 -0
- package/dist/web/static/landing.html +824 -0
- package/dist/web/static/lib/docx.umd.min.js +20116 -0
- package/dist/web/static/lib/highlight.min.js +1213 -0
- package/dist/web/static/lib/html2pdf.bundle.min.js +3 -0
- package/dist/web/static/lib/mammoth.browser.min.js +21 -0
- package/dist/web/static/lib/qrcode.min.js +8 -0
- package/dist/web/static/lib/xlsx.full.min.js +24 -0
- package/dist/web/static/login.html +582 -0
- package/dist/web/static/manifest.json +15 -0
- package/dist/web/static/style.css +35733 -0
- package/dist/web/static/sw.js +144 -0
- package/dist/workflows/engine.d.ts +162 -0
- package/dist/workflows/engine.d.ts.map +1 -0
- package/dist/workflows/engine.js +625 -0
- package/dist/workflows/engine.js.map +1 -0
- package/dist/workflows/index.d.ts +8 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +14 -0
- package/dist/workflows/index.js.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// static/js/emailLibrary/replyRecipients.js
|
|
2
|
+
//
|
|
3
|
+
// Pure helpers for building reply-all recipient lists. No DOM, no fetch,
|
|
4
|
+
// no shared state — safe to import anywhere and to unit-test under node.
|
|
5
|
+
|
|
6
|
+
// Extract the bare email from "Name <email@x>" or a plain "email@x".
|
|
7
|
+
export function extractEmail(addr) {
|
|
8
|
+
const m = (addr || '').match(/<([^>]+)>/);
|
|
9
|
+
return (m ? m[1] : (addr || '')).trim().toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Reply-all CC = everyone on the original To + Cc, minus ourselves, with the
|
|
13
|
+
// original "Name <email>" form preserved.
|
|
14
|
+
//
|
|
15
|
+
// `mine` is a single address or a list of the user's own addresses (a
|
|
16
|
+
// multi-account user has more than one). Empty/unknown ⇒ no exclusion.
|
|
17
|
+
// Comparing by exact extracted email (not a substring `includes`) is what
|
|
18
|
+
// fixes issue #360: an empty self address made `"...".includes("")` true for
|
|
19
|
+
// every recipient, so reply-all dropped the entire Cc list.
|
|
20
|
+
export function buildReplyAllCc(data, mine) {
|
|
21
|
+
const list = Array.isArray(mine) ? mine : [mine];
|
|
22
|
+
const me = new Set(list.map((a) => (a || '').toLowerCase()).filter(Boolean));
|
|
23
|
+
const split = (s) => (typeof s === 'string' ? s : '').split(',').map((x) => x.trim()).filter(Boolean);
|
|
24
|
+
return [...split(data && data.to), ...split(data && data.cc)]
|
|
25
|
+
.filter((addr) => !me.has(extractEmail(addr)))
|
|
26
|
+
.join(', ');
|
|
27
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
// static/js/emailLibrary/signatureFold.js
|
|
2
|
+
//
|
|
3
|
+
// Heuristics that turn raw HTML email bodies into folded structures —
|
|
4
|
+
// "Earlier reply" details collapsing the quoted history, and "Signature"
|
|
5
|
+
// details collapsing the trailing corporate disclaimer / boilerplate.
|
|
6
|
+
//
|
|
7
|
+
// All pure functions of HTML strings (and one DOM-mutating exception:
|
|
8
|
+
// `_harvestAttribution` peels nodes off a container). No module state,
|
|
9
|
+
// no fetch, no globals. The icons (`_SIG_ICON`, `_QUOTE_ICON`) live here
|
|
10
|
+
// since `_foldSummary` is the only caller and other modules pass them in
|
|
11
|
+
// via that helper.
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
_TALON_WROTE, _TALON_FROM, _TALON_SENT, _TALON_ORIG_RE,
|
|
15
|
+
_SIG_BLOAT_MIN_CHARS,
|
|
16
|
+
} from './utils.js';
|
|
17
|
+
|
|
18
|
+
// No leading icon on the signature fold — the user explicitly does not
|
|
19
|
+
// want a star/emoji-style glyph in this header.
|
|
20
|
+
export const _SIG_ICON = '';
|
|
21
|
+
export const _QUOTE_ICON = '<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>';
|
|
22
|
+
|
|
23
|
+
// HTML-escape used by `_extractQuoteMeta`. Inlined here (rather than
|
|
24
|
+
// imported from utils) so this module remains free of cross-file links.
|
|
25
|
+
function _esc(text) {
|
|
26
|
+
const div = document.createElement('div');
|
|
27
|
+
div.textContent = text || '';
|
|
28
|
+
return div.innerHTML;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Looks like a signature / corporate disclaimer rather than a quoted email.
|
|
32
|
+
// Heuristic: scores known "this is a disclaimer" tells against
|
|
33
|
+
// "this is a real email" tells. 3+ disclaimer hits with ≤1 conversational
|
|
34
|
+
// hit → signature.
|
|
35
|
+
export function _looksLikeSignature(html) {
|
|
36
|
+
if (!html) return false;
|
|
37
|
+
const txt = String(html).replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
38
|
+
if (!txt) return false;
|
|
39
|
+
let score = 0;
|
|
40
|
+
const SIG_TELLS = [
|
|
41
|
+
/\bregistered\s+in\b/i,
|
|
42
|
+
/\blimited\s+liability\s+partnership\b/i,
|
|
43
|
+
/\b(Pte\.?\s*Ltd|GmbH|S\.A\.|S\.A\.S|LLC|LLP|Inc\.?)\b/,
|
|
44
|
+
/\bintended\s+solely\s+for\b/i,
|
|
45
|
+
/\bconfidential(?:ity)?\s+(?:notice|information)\b/i,
|
|
46
|
+
/\b(?:disclaimer|please\s+(?:notify|delete))\b/i,
|
|
47
|
+
/\bunsubscribe\b/i,
|
|
48
|
+
/\bUEN\b\s*\w/i,
|
|
49
|
+
/\b\+\d[\d\s().-]{6,}\b/, // phone number
|
|
50
|
+
];
|
|
51
|
+
for (const re of SIG_TELLS) if (re.test(txt)) score++;
|
|
52
|
+
const PRIOR_TELLS = [
|
|
53
|
+
/\bHi\s+[A-Z][a-z]+\b/,
|
|
54
|
+
/\bDear\s+[A-Z][a-z]+\b/,
|
|
55
|
+
/\bRegards\b/i,
|
|
56
|
+
/\?\s*$/,
|
|
57
|
+
];
|
|
58
|
+
let priorScore = 0;
|
|
59
|
+
for (const re of PRIOR_TELLS) if (re.test(txt)) priorScore++;
|
|
60
|
+
return score >= 3 && priorScore <= 1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Look for an "On <date>, <addr> wrote:" line at the END of a fragment
|
|
64
|
+
// and remove it (returning the captured meta string, or null). Also
|
|
65
|
+
// handles Outlook-style "From: ... Sent: ... Subject: ..." blocks.
|
|
66
|
+
export function _harvestAttribution(container) {
|
|
67
|
+
const text = container.textContent || '';
|
|
68
|
+
const wroteLineRe = new RegExp(`${_TALON_WROTE}\\s*:\\s*$|${_TALON_WROTE}\\s*:\\s*<`, 'i');
|
|
69
|
+
const lastLines = text.trim().split('\n').slice(-3).join('\n');
|
|
70
|
+
if (!wroteLineRe.test(lastLines)) {
|
|
71
|
+
const outlookHeadRe = new RegExp(`${_TALON_FROM}\\s*:.*?${_TALON_SENT}\\s*:`, 'is');
|
|
72
|
+
if (!outlookHeadRe.test(text.split('\n').slice(-12).join('\n'))) {
|
|
73
|
+
if (!_TALON_ORIG_RE.test(text)) return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const trailing = [];
|
|
77
|
+
for (let i = container.childNodes.length - 1; i >= 0; i--) {
|
|
78
|
+
const node = container.childNodes[i];
|
|
79
|
+
const t = (node.textContent || '').trim();
|
|
80
|
+
if (!t) { trailing.unshift(node); continue; }
|
|
81
|
+
trailing.unshift(node);
|
|
82
|
+
if (trailing.map(n => n.textContent || '').join('\n').length > 600) break;
|
|
83
|
+
}
|
|
84
|
+
const meta = _extractQuoteMeta(trailing.map(n => n.outerHTML || n.textContent || '').join(''));
|
|
85
|
+
for (const n of trailing) {
|
|
86
|
+
try { container.removeChild(n); } catch {}
|
|
87
|
+
}
|
|
88
|
+
return meta || null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function _extractTurnMetaFromBlockquote(bq) {
|
|
92
|
+
const html = bq.innerHTML.slice(0, 2000);
|
|
93
|
+
const meta = _extractQuoteMeta(html);
|
|
94
|
+
return meta || null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// "Earlier reply" / "Signature" summary header — caller supplies the
|
|
98
|
+
// label string + icon SVG. `meta`, when present, is split on " · " to
|
|
99
|
+
// promote the sender's name to the headline.
|
|
100
|
+
export function _foldSummary(label, iconSvg, meta) {
|
|
101
|
+
let primary = label;
|
|
102
|
+
let subMeta = meta || '';
|
|
103
|
+
if (meta) {
|
|
104
|
+
const idx = meta.indexOf(' · ');
|
|
105
|
+
if (idx > 0) {
|
|
106
|
+
primary = meta.slice(0, idx);
|
|
107
|
+
subMeta = meta.slice(idx + 3);
|
|
108
|
+
} else if (meta.length <= 80 && !/^\d/.test(meta)) {
|
|
109
|
+
primary = meta;
|
|
110
|
+
subMeta = '';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// `meta` is derived from _extractQuoteMeta, which strips tags but then
|
|
114
|
+
// un-escapes entities (to recover `<foo@bar.com>` for bubble alignment) —
|
|
115
|
+
// so it can carry attacker-controlled angle brackets from a quoted block.
|
|
116
|
+
// This summary is built into innerHTML, so escape both parts to stop a
|
|
117
|
+
// crafted quote (e.g. `From: <img src=x onerror=...>`) from running script.
|
|
118
|
+
const metaSpan = subMeta
|
|
119
|
+
? `<span class="email-fold-summary-meta">${_esc(subMeta)}</span>`
|
|
120
|
+
: '';
|
|
121
|
+
return (
|
|
122
|
+
'<summary class="email-fold-summary">'
|
|
123
|
+
+ iconSvg
|
|
124
|
+
+ `<span class="email-fold-summary-name">${_esc(primary)}</span>`
|
|
125
|
+
+ metaSpan
|
|
126
|
+
+ '<svg class="email-summary-chevron" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="margin-left:auto;transition:transform .15s ease;"><polyline points="6 9 12 15 18 9"/></svg>'
|
|
127
|
+
+ '</summary>'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Extract sender + date from a quoted email block. Tries Outlook-style
|
|
132
|
+
// "From: X · Sent: Y" header first, falls back to Gmail-style
|
|
133
|
+
// "On <date>, <addr> wrote:". Returns a display string like
|
|
134
|
+
// "Jane Doe · Mon, Apr 18, 2026 at 9:31 AM" or `''`.
|
|
135
|
+
export function _extractQuoteMeta(html) {
|
|
136
|
+
if (typeof html !== 'string' || !html) return '';
|
|
137
|
+
const txt = html
|
|
138
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
139
|
+
.replace(/<[^>]+>/g, ' ')
|
|
140
|
+
.replace(/ /gi, ' ')
|
|
141
|
+
.replace(/&/gi, '&')
|
|
142
|
+
.replace(/</gi, '<')
|
|
143
|
+
.replace(/>/gi, '>')
|
|
144
|
+
.replace(/"/gi, '"')
|
|
145
|
+
.replace(/\s+/g, ' ')
|
|
146
|
+
.slice(0, 1500);
|
|
147
|
+
|
|
148
|
+
const FROM = '(?:From|Från|Von|De|Da|От|Od|Van)';
|
|
149
|
+
const SENT = '(?:Sent|Skickat|Gesendet|Envoyé|Inviato|Enviado|Verzonden|Отправлено|Wysłane|Date)';
|
|
150
|
+
const STOP = `(?=\\s+(?:To|Cc|Bcc|Subject|Ämne|Betreff|Objet|Oggetto|Asunto|Onderwerp|Тема|Temat|${SENT})\\s*:)`;
|
|
151
|
+
const fromMatch = txt.match(new RegExp(`${FROM}\\s*:\\s*(.+?)${STOP}`, 'i'));
|
|
152
|
+
const sentMatch = txt.match(new RegExp(`${SENT}\\s*:\\s*([^\\n]+?)(?=\\s+(?:To|Cc|Bcc|Subject|Ämne|Betreff|Objet|Oggetto|Asunto|Onderwerp|Тема|Temat)\\s*:)`, 'i'));
|
|
153
|
+
let from = fromMatch ? fromMatch[1].trim() : '';
|
|
154
|
+
let date = sentMatch ? sentMatch[1].trim() : '';
|
|
155
|
+
|
|
156
|
+
if (!from && !date) {
|
|
157
|
+
// The date may carry up to three commas before the year: the standard
|
|
158
|
+
// US Gmail attribution is "On Mon, Apr 18, 2026 at 9:31 AM, Jane wrote:"
|
|
159
|
+
// (weekday and day-of-month each add one). A single-comma pattern never
|
|
160
|
+
// reached the year there, so the fold lost its sender/date headline.
|
|
161
|
+
const gmail = txt.match(/On\s+((?:[^,]*,){0,3}?[^,]*?\d{4}[^,]*),?\s+(.+?)\s+wrote\s*:/i);
|
|
162
|
+
if (gmail) { date = gmail[1].trim(); from = gmail[2].trim(); }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
from = from.replace(/[<>]/g, '').replace(/\s+/g, ' ').trim();
|
|
166
|
+
date = date.replace(/\s+/g, ' ').trim();
|
|
167
|
+
if (from.length > 60) from = from.slice(0, 57) + '…';
|
|
168
|
+
if (date.length > 28) date = date.slice(0, 25) + '…';
|
|
169
|
+
|
|
170
|
+
// Return the raw sender/date text; `_foldSummary` is the single sink that
|
|
171
|
+
// builds these into HTML, so it owns escaping. Escaping here too would
|
|
172
|
+
// double-encode (e.g. "Ben & Jerry" -> "Ben &amp; Jerry").
|
|
173
|
+
if (from && date) return `${from} · ${date}`;
|
|
174
|
+
if (from) return from;
|
|
175
|
+
if (date) return date;
|
|
176
|
+
return '';
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Peel the first non-empty line off the signature tail. That line is
|
|
180
|
+
// usually the signer's name — keep it inline so "Kind regards, / Bob"
|
|
181
|
+
// reads naturally. Returns `{ preBloat, bloat }` — `bloat` is what
|
|
182
|
+
// should go into the fold; `preBloat` stays visible above it.
|
|
183
|
+
export function _peelSigNameLine(htmlAfterClosing) {
|
|
184
|
+
if (!htmlAfterClosing) return { preBloat: '', bloat: '' };
|
|
185
|
+
const breakRe = /<br\s*\/?>|<\/p>|<\/div>|\n/gi;
|
|
186
|
+
let cursor = 0;
|
|
187
|
+
let nameConsumed = false;
|
|
188
|
+
let mm;
|
|
189
|
+
while ((mm = breakRe.exec(htmlAfterClosing)) !== null) {
|
|
190
|
+
const seg = htmlAfterClosing.slice(cursor, mm.index)
|
|
191
|
+
.replace(/<[^>]+>/g, '').replace(/ /gi, ' ').trim();
|
|
192
|
+
if (seg.length > 0) {
|
|
193
|
+
const looksBloat = /[@]|tel\.?:|mobile:|phone:|www\.|https?:\/\/|sent from|^\+?\d[\d \-().]{6,}$/i.test(seg);
|
|
194
|
+
if (looksBloat) {
|
|
195
|
+
return {
|
|
196
|
+
preBloat: htmlAfterClosing.slice(0, cursor),
|
|
197
|
+
bloat: htmlAfterClosing.slice(cursor),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (!nameConsumed) {
|
|
201
|
+
nameConsumed = true;
|
|
202
|
+
const off = mm.index + mm[0].length;
|
|
203
|
+
return {
|
|
204
|
+
preBloat: htmlAfterClosing.slice(0, off),
|
|
205
|
+
bloat: htmlAfterClosing.slice(off),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
cursor = mm.index + mm[0].length;
|
|
210
|
+
}
|
|
211
|
+
return { preBloat: htmlAfterClosing, bloat: '' };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function _isBloatedSig(htmlFragment) {
|
|
215
|
+
if (!htmlFragment) return false;
|
|
216
|
+
const plain = htmlFragment
|
|
217
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
218
|
+
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
219
|
+
.replace(/<[^>]+>/g, ' ')
|
|
220
|
+
.replace(/ /gi, ' ')
|
|
221
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
|
|
222
|
+
.replace(/\s+/g, ' ')
|
|
223
|
+
.trim();
|
|
224
|
+
return plain.length >= _SIG_BLOAT_MIN_CHARS;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Try folding using a per-sender cached signature (built by the
|
|
228
|
+
// `learn_sender_signatures` action). When the cached text is found near
|
|
229
|
+
// the end of `html`, slice there and wrap the tail in a details fold.
|
|
230
|
+
// Returns the wrapped HTML or null when the hint doesn't apply.
|
|
231
|
+
export function _tryFoldHintSig(html, hintSig) {
|
|
232
|
+
if (!html || !hintSig || typeof hintSig !== 'string') return null;
|
|
233
|
+
if (hintSig.length < 20) return null;
|
|
234
|
+
const lines = hintSig.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
|
|
235
|
+
const closingsRe = /^(?:Best regards|Best wishes|Kind regards|Yours (?:truly|sincerely|faithfully)|Sincerely|Cheers|Thanks|Thank you|Regards|Warm regards|Many thanks|Take care)[,!.\s]*$/i;
|
|
236
|
+
const anchor = (lines.find(l => l.length >= 8 && !closingsRe.test(l)) || lines[0] || '').trim();
|
|
237
|
+
if (anchor.length < 8) return null;
|
|
238
|
+
const plain = [];
|
|
239
|
+
const map = [];
|
|
240
|
+
let i = 0;
|
|
241
|
+
while (i < html.length) {
|
|
242
|
+
if (html[i] === '<') {
|
|
243
|
+
if (/^<br\s*\/?\s*>/i.test(html.slice(i, i + 6))) {
|
|
244
|
+
plain.push('\n'); map.push(i);
|
|
245
|
+
const e = html.indexOf('>', i);
|
|
246
|
+
i = e + 1;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const e = html.indexOf('>', i);
|
|
250
|
+
if (e < 0) break;
|
|
251
|
+
i = e + 1;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (html[i] === '&') {
|
|
255
|
+
const semi = html.indexOf(';', i);
|
|
256
|
+
if (semi > 0 && semi - i < 8) {
|
|
257
|
+
const ent = html.slice(i + 1, semi);
|
|
258
|
+
const dec = ({nbsp: ' ', amp: '&', lt: '<', gt: '>', quot: '"', apos: "'"})[ent];
|
|
259
|
+
if (dec !== undefined) {
|
|
260
|
+
plain.push(dec); map.push(i);
|
|
261
|
+
i = semi + 1;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
plain.push(html[i]); map.push(i);
|
|
267
|
+
i++;
|
|
268
|
+
}
|
|
269
|
+
const plainStr = plain.join('');
|
|
270
|
+
const idx = plainStr.lastIndexOf(anchor);
|
|
271
|
+
if (idx < 0) return null;
|
|
272
|
+
const htmlStart = map[idx];
|
|
273
|
+
if (htmlStart == null) return null;
|
|
274
|
+
const before = html.slice(0, htmlStart);
|
|
275
|
+
const sigSection = html.slice(htmlStart);
|
|
276
|
+
if (!_isBloatedSig(sigSection)) return null;
|
|
277
|
+
return before + '<details class="email-sig-fold">'
|
|
278
|
+
+ _foldSummary('Signature', _SIG_ICON)
|
|
279
|
+
+ sigSection + '</details>';
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Top-level signature fold — runs through several detection strategies
|
|
283
|
+
// in priority order. Returns the original html unchanged when no
|
|
284
|
+
// strategy fires.
|
|
285
|
+
export function _foldSignature(html, hintSig) {
|
|
286
|
+
if (!html || typeof html !== 'string') return html;
|
|
287
|
+
if (html.length > 80000) return html;
|
|
288
|
+
if (hintSig) {
|
|
289
|
+
const wrapped = _tryFoldHintSig(html, hintSig);
|
|
290
|
+
if (wrapped !== null) return wrapped;
|
|
291
|
+
}
|
|
292
|
+
const wrap = (before, marker, rest) => {
|
|
293
|
+
if (!_isBloatedSig(rest)) return html;
|
|
294
|
+
return before + (marker || '') + '<details class="email-sig-fold">'
|
|
295
|
+
+ _foldSummary('Signature', _SIG_ICON) + rest + '</details>';
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
let m = html.match(/<div[^>]*class=["'][^"']*\bgmail_signature\b[^"']*["'][\s\S]*$/i);
|
|
299
|
+
if (m) return wrap(html.slice(0, html.length - m[0].length), '', m[0]);
|
|
300
|
+
m = html.match(/<div[^>]*data-smartmail=["']gmail_signature["'][\s\S]*$/i);
|
|
301
|
+
if (m) return wrap(html.slice(0, html.length - m[0].length), '', m[0]);
|
|
302
|
+
m = html.match(/<div[^>]*id=["'](?:Signature|signature|divRplyFwdMsg)["'][\s\S]*$/i);
|
|
303
|
+
if (m) return wrap(html.slice(0, html.length - m[0].length), '', m[0]);
|
|
304
|
+
|
|
305
|
+
m = html.match(/(<br\s*\/?>|\n)\s*--\s*(<br\s*\/?>|\n)([\s\S]*)$/i);
|
|
306
|
+
if (m) {
|
|
307
|
+
const idx = html.lastIndexOf(m[0]);
|
|
308
|
+
return wrap(html.slice(0, idx), m[1], m[3]);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const blockBoundary = '(?:<br\\s*/?>|<\\/p>|<\\/div>|<\\/li>|<p[^>]*>|<div[^>]*>|<span[^>]*>|\\n)';
|
|
312
|
+
const closings = '(?:Best regards|Best wishes|Kind regards|Yours truly|Yours sincerely|Yours faithfully|Best,|Best\\s|Cheers,|Cheers\\s|Thanks,|Thanks\\s|Thank you,|Regards,|Regards\\s|Sincerely[, ]|Warm regards|Many thanks|Talk soon|Take care)';
|
|
313
|
+
m = html.match(new RegExp(`(${blockBoundary})\\s*(${closings})([\\s\\S]+)$`, 'i'));
|
|
314
|
+
if (m) {
|
|
315
|
+
const idx = html.lastIndexOf(m[0]);
|
|
316
|
+
const boundary = m[1];
|
|
317
|
+
const closing = m[2];
|
|
318
|
+
const after = m[3];
|
|
319
|
+
const { preBloat, bloat } = _peelSigNameLine(after);
|
|
320
|
+
if (!_isBloatedSig(bloat)) return html;
|
|
321
|
+
return html.slice(0, idx) + boundary + closing + preBloat
|
|
322
|
+
+ '<details class="email-sig-fold">' + _foldSummary('Signature', _SIG_ICON)
|
|
323
|
+
+ bloat + '</details>';
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
m = html.match(new RegExp(`(${blockBoundary})\\s*((?:Sent from my (?:iPhone|iPad|Android|Galaxy|Pixel|phone|mobile)|Get Outlook for (?:iOS|Android))[\\s\\S]*)$`, 'i'));
|
|
327
|
+
if (m) {
|
|
328
|
+
const idx = html.lastIndexOf(m[0]);
|
|
329
|
+
return wrap(html.slice(0, idx), m[1], m[2]);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
m = html.match(new RegExp(`(${blockBoundary})\\s*((?:CONFIDENTIALITY NOTICE|DISCLAIMER|This e-?mail (?:is confidential|may contain confidential)|The information (?:contained )?in this e-?mail|This message and any attachments)[\\s\\S]*)$`, 'i'));
|
|
333
|
+
if (m) {
|
|
334
|
+
const idx = html.lastIndexOf(m[0]);
|
|
335
|
+
return wrap(html.slice(0, idx), m[1], m[2]);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return html;
|
|
339
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// static/js/emailLibrary/state.js
|
|
2
|
+
//
|
|
3
|
+
// Shared mutable state for the email-library popup. Keeping these on a
|
|
4
|
+
// single exported object lets sibling modules (utils, signatureFold,
|
|
5
|
+
// future render/menu/composer splits) read and write the same values
|
|
6
|
+
// without each one importing 19 `let` bindings — which ES modules
|
|
7
|
+
// don't allow from outside the defining module anyway.
|
|
8
|
+
//
|
|
9
|
+
// Writes look like `state._libOpen = true` everywhere; reads look like
|
|
10
|
+
// `state._libOpen`. The names match the originals so the refactor is a
|
|
11
|
+
// pure rename, not a semantic change.
|
|
12
|
+
|
|
13
|
+
export const state = {
|
|
14
|
+
_libOpen: false,
|
|
15
|
+
_libJustOpened: false,
|
|
16
|
+
_libEmails: [],
|
|
17
|
+
_libTotal: 0,
|
|
18
|
+
_libOffset: 0,
|
|
19
|
+
_libFolder: 'INBOX',
|
|
20
|
+
_libFolders: [],
|
|
21
|
+
_libAccountId: null, // null = backend default account
|
|
22
|
+
_libAccounts: [], // list of accounts for the chip strip
|
|
23
|
+
_libPendingExpandUid: null,
|
|
24
|
+
_libSearch: '',
|
|
25
|
+
_libFilter: 'all', // all, unread, unanswered
|
|
26
|
+
_libSort: 'recent', // recent, unread, favorites
|
|
27
|
+
_libHasAttachments: false,
|
|
28
|
+
_libLoading: false,
|
|
29
|
+
_docModule: null,
|
|
30
|
+
_onEmailClick: null,
|
|
31
|
+
_libEscHandler: null,
|
|
32
|
+
_selectMode: false,
|
|
33
|
+
_selectedUids: new Set(),
|
|
34
|
+
};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// static/js/emailLibrary/utils.js
|
|
2
|
+
//
|
|
3
|
+
// Pure helpers extracted from emailLibrary.js. No DOM state, no fetch,
|
|
4
|
+
// no shared mutable references — safe to import anywhere.
|
|
5
|
+
|
|
6
|
+
// ── Talon-inspired multilingual quote-detection regexes ───────────
|
|
7
|
+
// Borrowed (loosely) from Mailgun's `talon` library. These are partial
|
|
8
|
+
// regex source strings — combined with surrounding patterns by callers.
|
|
9
|
+
// Multilingual on purpose: a typed "wrote:" line is locale-bound, and
|
|
10
|
+
// people forward / reply across language settings all the time.
|
|
11
|
+
|
|
12
|
+
export const _TALON_WROTE = '(?:wrote|écrit|escribió|scrisse|schrieb|skrev|schreef|napisał|написал|napsal|написа|έγραψε|katselivat|napisao|написав|napisała|napisali|hat geschrieben|kirjoitti|написала|escreveu|napisao|написа|написала)';
|
|
13
|
+
|
|
14
|
+
export const _TALON_FROM = '(?:From|Från|Von|De|Da|От|Od|Van|差出人|发件人|寄件人|Ut|Frá|Lähettäjä|Avsender|Pošiljatelj|Од|Від|Posiljatelj|Frå)';
|
|
15
|
+
export const _TALON_SENT = '(?:Sent|Skickat|Gesendet|Envoy[ée]|Inviato|Enviado|Verzonden|Отправлено|Wysłane|Date|送信日時|发送时间|寄件日期|Sendt|Lähetetty|Tarih|Datum|Data|Datum)';
|
|
16
|
+
export const _TALON_SUBJ = '(?:Subject|Ämne|Betreff|Objet|Oggetto|Asunto|Onderwerp|Тема|Temat|件名|主题|主旨|Emne|Aihe|Onderwerp|Konu)';
|
|
17
|
+
export const _TALON_TO = '(?:To|Till|An|À|A|Voor|Para|Naar|Кому|Do|宛先|收件人|Emri|Komu)';
|
|
18
|
+
export const _TALON_ORIG_RE = /(?:^|\n)[\s>]*[-_=]{3,}\s*(?:Original\s+Message|Forwarded\s+message|Ursprüngliche\s+Nachricht|Mensaje\s+original|Messaggio\s+originale|Message\s+d['’]origine|Oorspronkelijk\s+bericht|Original\s+meddelande|Vor[ ]asal[a]\s+meddelande|原文|原始邮件|転送)\s*[-_=]{3,}/i;
|
|
19
|
+
|
|
20
|
+
// Minimum plain-text length of a "signature" before we bother folding it.
|
|
21
|
+
// Short closings ("Cheers, John") stay inline — folding them would add
|
|
22
|
+
// a click for two bytes of saving.
|
|
23
|
+
export const _SIG_BLOAT_MIN_CHARS = 200;
|
|
24
|
+
|
|
25
|
+
// HTML-escape a string by round-tripping through a detached div. Cheap
|
|
26
|
+
// and correct (handles all the entities that matter for innerHTML).
|
|
27
|
+
export function _esc(text) {
|
|
28
|
+
const div = document.createElement('div');
|
|
29
|
+
div.textContent = text || '';
|
|
30
|
+
return div.innerHTML;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Escape + linkify URLs and email addresses. Returns innerHTML-safe markup.
|
|
34
|
+
export function _escLinkify(text) {
|
|
35
|
+
const escaped = _esc(text);
|
|
36
|
+
// URLs: http(s)://... or www....
|
|
37
|
+
const urlRe = /\b((?:https?:\/\/|www\.)[^\s<>"']+[^\s<>"'.,;:!?)\]])/g;
|
|
38
|
+
const mailRe = /\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})\b/g;
|
|
39
|
+
return escaped
|
|
40
|
+
.replace(urlRe, (m) => {
|
|
41
|
+
const href = m.startsWith('www.') ? `https://${m}` : m;
|
|
42
|
+
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${m}</a>`;
|
|
43
|
+
})
|
|
44
|
+
.replace(mailRe, (m) => `<a href="mailto:${m}">${m}</a>`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Pull display name out of "Name <email@x>"; fallback to local-part of
|
|
48
|
+
// the email; final fallback to the input string.
|
|
49
|
+
export function _extractName(addr) {
|
|
50
|
+
const m = addr.match(/^"?([^"<]+?)"?\s*<([^>]+)>\s*$/);
|
|
51
|
+
if (m) return m[1].trim();
|
|
52
|
+
const localPart = addr.split('@')[0];
|
|
53
|
+
return localPart || addr;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Parse the "Author <email> · Date" metadata string emitted by the
|
|
57
|
+
// server-side thread parser.
|
|
58
|
+
export function _parseTurnMeta(meta) {
|
|
59
|
+
if (!meta) return { author: '', email: '', date: '' };
|
|
60
|
+
const m = String(meta);
|
|
61
|
+
const eMatch = m.match(/<([^<>\s]+@[^<>\s]+)>/) ||
|
|
62
|
+
m.match(/\b([\w.+-]+@[\w.-]+\.[A-Za-z]{2,})\b/);
|
|
63
|
+
const email = eMatch ? eMatch[1].toLowerCase().trim() : '';
|
|
64
|
+
const parts = m.split(/\s+[·•]\s+/);
|
|
65
|
+
let author = '', date = '';
|
|
66
|
+
if (parts.length >= 2) {
|
|
67
|
+
author = parts[0].replace(/<[^>]+>/g, '').trim();
|
|
68
|
+
date = parts.slice(1).join(' · ').trim();
|
|
69
|
+
} else {
|
|
70
|
+
author = m.replace(/<[^>]+>/g, '').trim();
|
|
71
|
+
}
|
|
72
|
+
return { author, email, date };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Short, locale-aware display string for a chat-bubble timestamp.
|
|
76
|
+
// Returns '' for invalid / empty input.
|
|
77
|
+
export function _formatBubbleDate(iso) {
|
|
78
|
+
if (!iso) return '';
|
|
79
|
+
const d = new Date(iso);
|
|
80
|
+
if (!d || isNaN(d.getTime())) return '';
|
|
81
|
+
try {
|
|
82
|
+
return d.toLocaleString(undefined, {
|
|
83
|
+
month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit',
|
|
84
|
+
});
|
|
85
|
+
} catch (_) { return ''; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Format a raw "to" address string ("Foo <foo@x.com>, bar@y.com") into a
|
|
89
|
+
// short, readable list — display names when present, just the local part
|
|
90
|
+
// of the email otherwise, and ", +N" once there are more than 2 recipients.
|
|
91
|
+
export function _formatRecipients(raw) {
|
|
92
|
+
if (!raw) return '';
|
|
93
|
+
const addrs = String(raw).split(',').map(s => s.trim()).filter(Boolean);
|
|
94
|
+
if (!addrs.length) return '';
|
|
95
|
+
const friendly = addrs.map(a => {
|
|
96
|
+
const m = a.match(/^\s*"?([^"<]+?)"?\s*<[^>]+>\s*$/);
|
|
97
|
+
if (m && m[1].trim()) return m[1].trim();
|
|
98
|
+
const em = a.replace(/[<>]/g, '').trim();
|
|
99
|
+
return em.split('@')[0] || em;
|
|
100
|
+
});
|
|
101
|
+
if (friendly.length === 1) return friendly[0];
|
|
102
|
+
if (friendly.length === 2) return friendly.join(', ');
|
|
103
|
+
return friendly.slice(0, 2).join(', ') + ' +' + (friendly.length - 2);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Deterministic per-sender colour. Same hashing as
|
|
107
|
+
// emailInbox.js#_senderColor so a sender's avatar / name colour matches
|
|
108
|
+
// across the list view and the bubble reader.
|
|
109
|
+
export function _senderColor(name) {
|
|
110
|
+
if (!name) return 'hsl(220, 55%, 65%)';
|
|
111
|
+
const key = String(name).toLowerCase();
|
|
112
|
+
let hash = 0;
|
|
113
|
+
for (let i = 0; i < key.length; i++) {
|
|
114
|
+
hash = ((hash << 5) - hash + key.charCodeAt(i)) | 0;
|
|
115
|
+
}
|
|
116
|
+
const hue = ((hash % 360) + 360) % 360;
|
|
117
|
+
return `hsl(${hue}, 55%, 65%)`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 1- or 2-letter initials for an avatar bubble. Unicode-friendly.
|
|
121
|
+
export function _initials(s) {
|
|
122
|
+
if (!s) return '?';
|
|
123
|
+
const clean = String(s).replace(/<[^>]+>/g, '').replace(/[^\p{L}\s]/gu, ' ').trim();
|
|
124
|
+
const parts = clean.split(/\s+/).filter(Boolean);
|
|
125
|
+
if (!parts.length) return '?';
|
|
126
|
+
const first = parts[0][0] || '';
|
|
127
|
+
const last = parts.length > 1 ? parts[parts.length - 1][0] : '';
|
|
128
|
+
return (first + last).toUpperCase();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// HTML sanitizer for rendering remote email bodies. Strips script/iframe/
|
|
132
|
+
// form/style/etc., kills `on*` handlers, blocks `javascript:`/`vbscript:`/
|
|
133
|
+
// `data:` URLs on every known URL attribute, scrubs inline colour/font/
|
|
134
|
+
// position styles so the theme can take over, and wraps highlight-bearing
|
|
135
|
+
// inline tags in <mark> so they render legibly across themes.
|
|
136
|
+
export function _sanitizeHtml(html) {
|
|
137
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
138
|
+
doc.querySelectorAll(
|
|
139
|
+
'script, iframe, object, embed, form, style, link, ' +
|
|
140
|
+
'svg, math, base, meta, noscript, frame, frameset, applet, portal'
|
|
141
|
+
).forEach(el => el.remove());
|
|
142
|
+
|
|
143
|
+
const URL_ATTRS = ['href', 'src', 'srcset', 'action', 'formaction', 'background', 'poster', 'data'];
|
|
144
|
+
const isDangerousUrl = (val) => {
|
|
145
|
+
if (!val) return false;
|
|
146
|
+
const v = val.trim().toLowerCase();
|
|
147
|
+
return v.startsWith('javascript:') || v.startsWith('vbscript:') || v.startsWith('data:');
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const STRIP_CSS_PROPS = ['color', 'background', 'background-color',
|
|
151
|
+
'font-family', 'font', '-webkit-text-fill-color',
|
|
152
|
+
'position', 'z-index'];
|
|
153
|
+
const HIGHLIGHT_INLINE_TAGS = new Set(['SPAN', 'FONT', 'EM', 'B', 'I',
|
|
154
|
+
'STRONG', 'SMALL', 'U']);
|
|
155
|
+
const HAS_BG_COLOR = /background(?:-color)?\s*:\s*(?!\s*(?:transparent|none|inherit|initial)\b)[^;]+/i;
|
|
156
|
+
const _markedForHighlight = [];
|
|
157
|
+
|
|
158
|
+
doc.querySelectorAll('*').forEach(el => {
|
|
159
|
+
for (const attr of [...el.attributes]) {
|
|
160
|
+
const name = attr.name.toLowerCase();
|
|
161
|
+
if (name.startsWith('on')) { el.removeAttribute(attr.name); continue; }
|
|
162
|
+
if (name === 'srcdoc') { el.removeAttribute(attr.name); continue; }
|
|
163
|
+
if (URL_ATTRS.includes(name) && isDangerousUrl(attr.value)) {
|
|
164
|
+
el.removeAttribute(attr.name);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
el.removeAttribute('color');
|
|
169
|
+
const bgcolor = el.getAttribute('bgcolor');
|
|
170
|
+
el.removeAttribute('bgcolor');
|
|
171
|
+
el.removeAttribute('face');
|
|
172
|
+
const style = el.getAttribute('style');
|
|
173
|
+
const hadHighlight =
|
|
174
|
+
HIGHLIGHT_INLINE_TAGS.has(el.tagName) &&
|
|
175
|
+
((style && HAS_BG_COLOR.test(style)) || (bgcolor && bgcolor !== 'transparent'));
|
|
176
|
+
if (hadHighlight) _markedForHighlight.push(el);
|
|
177
|
+
if (style) {
|
|
178
|
+
const kept = style.split(';').map(s => s.trim()).filter(decl => {
|
|
179
|
+
if (!decl) return false;
|
|
180
|
+
const lower = decl.toLowerCase();
|
|
181
|
+
if (lower.includes('javascript:') || lower.includes('expression(')) return false;
|
|
182
|
+
const prop = decl.split(':', 1)[0].trim().toLowerCase();
|
|
183
|
+
return !STRIP_CSS_PROPS.includes(prop);
|
|
184
|
+
});
|
|
185
|
+
if (kept.length) el.setAttribute('style', kept.join('; '));
|
|
186
|
+
else el.removeAttribute('style');
|
|
187
|
+
}
|
|
188
|
+
if (el.tagName === 'A') {
|
|
189
|
+
el.setAttribute('target', '_blank');
|
|
190
|
+
el.setAttribute('rel', 'noopener noreferrer');
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
_markedForHighlight.forEach(el => {
|
|
195
|
+
if (el.tagName === 'MARK' || !el.firstChild) return;
|
|
196
|
+
const mark = doc.createElement('mark');
|
|
197
|
+
while (el.firstChild) mark.appendChild(el.firstChild);
|
|
198
|
+
el.appendChild(mark);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return doc.body.innerHTML;
|
|
202
|
+
}
|