@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,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI model dropdown loader — fetches available model endpoints from
|
|
3
|
+
* the backend and populates the editor's three model-select surfaces:
|
|
4
|
+
*
|
|
5
|
+
* #ge-ai-model — global Gen picker
|
|
6
|
+
* #ge-ai-inpaint — inpaint picker
|
|
7
|
+
* select.ge-tool-model[data-ge-tool-model="…"]
|
|
8
|
+
* — per-tool pickers (harmonize / upscale / style /
|
|
9
|
+
* sharpen / etc.)
|
|
10
|
+
*
|
|
11
|
+
* Each model is filtered through a small capability classifier so the
|
|
12
|
+
* Gen dropdown only sees text-to-image models, the inpaint dropdown
|
|
13
|
+
* only sees image+mask edit models, and the per-tool dropdowns get
|
|
14
|
+
* everything img2img-capable.
|
|
15
|
+
*
|
|
16
|
+
* Every picker ends with a "+ Serve a model in Cookbook…" sentinel —
|
|
17
|
+
* choosing it opens Cookbook → Serve filtered to image models, then
|
|
18
|
+
* reverts the picker to its prior value (so it's an action, not a
|
|
19
|
+
* selectable model).
|
|
20
|
+
*
|
|
21
|
+
* @param {{
|
|
22
|
+
* container: HTMLElement,
|
|
23
|
+
* apiBase: string,
|
|
24
|
+
* openCookbookForImg2img: () => void,
|
|
25
|
+
* }} deps
|
|
26
|
+
*/
|
|
27
|
+
import { state } from './state.js';
|
|
28
|
+
import { sortModelIds } from '../modelSort.js';
|
|
29
|
+
|
|
30
|
+
// Heuristic classifier on a model id + endpoint name. A model can be:
|
|
31
|
+
// - gen: text-to-image generation
|
|
32
|
+
// - inpaint: image+mask edit (inpaint / img2img)
|
|
33
|
+
// Some models do only one (e.g. dall-e-3 = gen-only, no edits API).
|
|
34
|
+
function modelCaps(modelId, endpointName, endpointType) {
|
|
35
|
+
const id = (modelId || '').toLowerCase();
|
|
36
|
+
const name = (endpointName || '').toLowerCase();
|
|
37
|
+
const type = (endpointType || '').toLowerCase();
|
|
38
|
+
// Reject anything obviously text-only.
|
|
39
|
+
const textOnly = /(?:^|[/\-_:])(gpt-?[345]|gpt-oss|claude|llama|qwen[^-]*chat|chat$|instruct$|coder)/i;
|
|
40
|
+
if (textOnly.test(id) && !/image/i.test(id)) return { gen: false, inpaint: false };
|
|
41
|
+
// OpenAI image family.
|
|
42
|
+
if (/dall-e-3/.test(id)) return { gen: true, inpaint: false };
|
|
43
|
+
if (/dall-e-2/.test(id)) return { gen: true, inpaint: true };
|
|
44
|
+
if (/gpt-image/.test(id)) return { gen: true, inpaint: true };
|
|
45
|
+
// Diffusion families — most generic SD/SDXL/Flux base models
|
|
46
|
+
// support both via diffusers.
|
|
47
|
+
if (/(?:^|[/\-_])(?:sd-?xl|sdxl|sd3|sd-|stable[\s-]*diffusion|flux|playground|pixart|kandinsky)/i.test(id)) {
|
|
48
|
+
const isInpaintModel = /inpaint|edit|fill/i.test(id) || /inpaint|edit|fill/i.test(name);
|
|
49
|
+
return { gen: !isInpaintModel || /base/i.test(id), inpaint: true };
|
|
50
|
+
}
|
|
51
|
+
// Self-hosted diffusion server: model id often matches the repo
|
|
52
|
+
// name; trust the endpoint name hint.
|
|
53
|
+
if (type === 'image') {
|
|
54
|
+
if (/inpaint|edit|fill/i.test(name)) return { gen: false, inpaint: true };
|
|
55
|
+
return { gen: true, inpaint: true };
|
|
56
|
+
}
|
|
57
|
+
if (/inpaint|edit|fill/i.test(name)) return { gen: false, inpaint: true };
|
|
58
|
+
if (/diffus|flux|sd|image/i.test(name)) return { gen: true, inpaint: true };
|
|
59
|
+
// Editor image tools should be conservative. Unknown LLM/chat models
|
|
60
|
+
// do not belong in image generation or inpaint pickers.
|
|
61
|
+
return { gen: false, inpaint: false };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function wireAIModelSelectors({ container, apiBase, openCookbookForImg2img }) {
|
|
65
|
+
// Delegated handler for the "+ Serve a model in Cookbook…" sentinel
|
|
66
|
+
// option — catches clicks regardless of whether loadAIModels has
|
|
67
|
+
// rewired the individual select yet and survives any innerHTML
|
|
68
|
+
// reset later.
|
|
69
|
+
container.addEventListener('change', (e) => {
|
|
70
|
+
const sel = e.target.closest('select');
|
|
71
|
+
if (!sel) return;
|
|
72
|
+
if (sel.value !== '__serve_cookbook__') return;
|
|
73
|
+
// Revert to the previous selection so the sentinel isn't "stuck".
|
|
74
|
+
const prev = sel._prevServeValue ?? '';
|
|
75
|
+
sel.value = prev;
|
|
76
|
+
openCookbookForImg2img();
|
|
77
|
+
});
|
|
78
|
+
// Track prior value so we can restore it after the sentinel fires.
|
|
79
|
+
container.addEventListener('focus', (e) => {
|
|
80
|
+
const sel = e.target.closest('select');
|
|
81
|
+
if (sel && sel.value !== '__serve_cookbook__') sel._prevServeValue = sel.value;
|
|
82
|
+
}, true);
|
|
83
|
+
|
|
84
|
+
const aiGenSelect = document.getElementById('ge-ai-model');
|
|
85
|
+
const aiInpaintSelect = document.getElementById('ge-ai-inpaint');
|
|
86
|
+
// The global Gen model dropdown was removed from the editor topbar;
|
|
87
|
+
// only bail if there's nothing to populate at all (neither the Gen
|
|
88
|
+
// select nor the inpaint select nor any per-tool select).
|
|
89
|
+
if (!aiGenSelect && !aiInpaintSelect &&
|
|
90
|
+
!document.querySelector('select.ge-tool-model')) return;
|
|
91
|
+
|
|
92
|
+
async function loadAIModels(opts = {}) {
|
|
93
|
+
try {
|
|
94
|
+
const selectBaseUrl = opts.selectBaseUrl || '';
|
|
95
|
+
const prevGenValue = aiGenSelect?.value || '';
|
|
96
|
+
const prevInpaintValue = aiInpaintSelect?.value || '';
|
|
97
|
+
const res = await fetch(`${apiBase}/api/model-endpoints`);
|
|
98
|
+
const endpoints = await res.json();
|
|
99
|
+
if (aiGenSelect) aiGenSelect.innerHTML = '<option value="">None</option>';
|
|
100
|
+
if (aiInpaintSelect) aiInpaintSelect.innerHTML = '<option value="">Auto</option>';
|
|
101
|
+
const perToolSelects = Array.from(document.querySelectorAll('select.ge-tool-model'));
|
|
102
|
+
for (const ts of perToolSelects) ts.innerHTML = '<option value="">Auto</option>';
|
|
103
|
+
let firstGen = null;
|
|
104
|
+
let firstInpaint = null;
|
|
105
|
+
let selectedGen = null;
|
|
106
|
+
let selectedInpaint = null;
|
|
107
|
+
for (const ep of endpoints) {
|
|
108
|
+
if (!ep.is_enabled) continue;
|
|
109
|
+
const hasListedModels = Array.isArray(ep.models) && ep.models.length;
|
|
110
|
+
const models = hasListedModels ? sortModelIds(ep.models) : [''];
|
|
111
|
+
const isImageEndpoint = (ep.model_type || '').toLowerCase() === 'image';
|
|
112
|
+
// Image/inpaint endpoints can be called by URL even when their
|
|
113
|
+
// /models cache is still empty, so don't strand a freshly served
|
|
114
|
+
// Cookbook model as "(offline)" in the editor picker.
|
|
115
|
+
const epUsable = !!ep.online || isImageEndpoint;
|
|
116
|
+
for (const modelId of models) {
|
|
117
|
+
const caps = modelCaps(modelId || ep.name, ep.name, ep.model_type);
|
|
118
|
+
if (!caps.gen && !caps.inpaint) continue;
|
|
119
|
+
// Encode "<base_url>::<model_id>" so the value carries both pieces.
|
|
120
|
+
const value = `${ep.base_url}::${modelId}`;
|
|
121
|
+
const shortModel = modelId ? String(modelId).split('/').pop() : (ep.name || ep.base_url);
|
|
122
|
+
const epHint = modelId && ep.name && ep.name !== modelId ? ` · ${ep.name}` : '';
|
|
123
|
+
const label = `${shortModel}${epHint}${epUsable ? '' : ' (offline)'}`;
|
|
124
|
+
if (caps.gen && aiGenSelect) {
|
|
125
|
+
const opt = document.createElement('option');
|
|
126
|
+
opt.value = value;
|
|
127
|
+
opt.textContent = label;
|
|
128
|
+
opt.disabled = !epUsable;
|
|
129
|
+
aiGenSelect.appendChild(opt);
|
|
130
|
+
if (epUsable && !firstGen) firstGen = value;
|
|
131
|
+
if (epUsable && selectBaseUrl && ep.base_url === selectBaseUrl && !selectedGen) selectedGen = value;
|
|
132
|
+
}
|
|
133
|
+
if (caps.inpaint && aiInpaintSelect) {
|
|
134
|
+
const opt = document.createElement('option');
|
|
135
|
+
opt.value = value;
|
|
136
|
+
opt.textContent = label;
|
|
137
|
+
opt.disabled = !epUsable;
|
|
138
|
+
aiInpaintSelect.appendChild(opt);
|
|
139
|
+
if (epUsable && selectBaseUrl && ep.base_url === selectBaseUrl && !selectedInpaint) selectedInpaint = value;
|
|
140
|
+
// Prefer dedicated inpaint/edit models for default selection.
|
|
141
|
+
if (epUsable && !firstInpaint && (!modelId || /inpaint|edit|fill|gpt-image/i.test(modelId) || /inpaint|edit|fill/i.test(ep.name || ''))) {
|
|
142
|
+
firstInpaint = value;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Per-tool selectors get every img2img-capable entry. Both
|
|
146
|
+
// caps.inpaint AND caps.gen models work for harmonize /
|
|
147
|
+
// style / upscale (anything that can do img2img).
|
|
148
|
+
if (caps.inpaint || caps.gen) {
|
|
149
|
+
for (const ts of perToolSelects) {
|
|
150
|
+
const opt = document.createElement('option');
|
|
151
|
+
opt.value = value;
|
|
152
|
+
opt.textContent = label;
|
|
153
|
+
opt.disabled = !epUsable;
|
|
154
|
+
ts.appendChild(opt);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const hasValue = (sel, value) => !!value && [...sel.options].some(o => o.value === value);
|
|
160
|
+
if (aiGenSelect) {
|
|
161
|
+
if (selectedGen) aiGenSelect.value = selectedGen;
|
|
162
|
+
else if (hasValue(aiGenSelect, prevGenValue)) aiGenSelect.value = prevGenValue;
|
|
163
|
+
else if (firstGen) aiGenSelect.value = firstGen;
|
|
164
|
+
}
|
|
165
|
+
if (aiInpaintSelect) {
|
|
166
|
+
if (selectedInpaint) aiInpaintSelect.value = selectedInpaint;
|
|
167
|
+
else if (hasValue(aiInpaintSelect, prevInpaintValue)) aiInpaintSelect.value = prevInpaintValue;
|
|
168
|
+
else if (firstInpaint) aiInpaintSelect.value = firstInpaint;
|
|
169
|
+
}
|
|
170
|
+
// Append the "Serve a model in Cookbook…" sentinel at the
|
|
171
|
+
// bottom of every model dropdown.
|
|
172
|
+
const appendServeSentinel = (sel) => {
|
|
173
|
+
const sep = document.createElement('option');
|
|
174
|
+
sep.disabled = true;
|
|
175
|
+
sep.textContent = '──────────';
|
|
176
|
+
sel.appendChild(sep);
|
|
177
|
+
const serveOpt = document.createElement('option');
|
|
178
|
+
serveOpt.value = '__serve_cookbook__';
|
|
179
|
+
serveOpt.textContent = '+ Serve a model in Cookbook…';
|
|
180
|
+
sel.appendChild(serveOpt);
|
|
181
|
+
};
|
|
182
|
+
for (const ts of perToolSelects) appendServeSentinel(ts);
|
|
183
|
+
if (aiGenSelect) appendServeSentinel(aiGenSelect);
|
|
184
|
+
if (aiInpaintSelect) appendServeSentinel(aiInpaintSelect);
|
|
185
|
+
// Wire the sentinel on the Gen + Inpaint selects too.
|
|
186
|
+
const wireServeSentinel = (sel) => {
|
|
187
|
+
if (!sel) return;
|
|
188
|
+
let prev = sel.value;
|
|
189
|
+
sel.addEventListener('change', () => {
|
|
190
|
+
if (sel.value === '__serve_cookbook__') {
|
|
191
|
+
sel.value = prev;
|
|
192
|
+
openCookbookForImg2img();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
prev = sel.value;
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
wireServeSentinel(aiGenSelect);
|
|
199
|
+
wireServeSentinel(aiInpaintSelect);
|
|
200
|
+
// Restore each per-tool selection from localStorage.
|
|
201
|
+
for (const ts of perToolSelects) {
|
|
202
|
+
const key = 'ge-tool-model-' + ts.dataset.geToolModel;
|
|
203
|
+
try {
|
|
204
|
+
const saved = localStorage.getItem(key);
|
|
205
|
+
if (saved && [...ts.options].some(o => o.value === saved)) {
|
|
206
|
+
ts.value = saved;
|
|
207
|
+
}
|
|
208
|
+
} catch {}
|
|
209
|
+
let prevValue = ts.value;
|
|
210
|
+
ts.addEventListener('change', () => {
|
|
211
|
+
if (ts.value === '__serve_cookbook__') {
|
|
212
|
+
ts.value = prevValue;
|
|
213
|
+
openCookbookForImg2img();
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
prevValue = ts.value;
|
|
217
|
+
try { localStorage.setItem(key, ts.value); } catch {}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
} catch (e) {
|
|
221
|
+
// Fetch failed — still give the user the affordance to set up
|
|
222
|
+
// a model. Otherwise the dropdown shows only "Auto" with no
|
|
223
|
+
// hint about what to do next.
|
|
224
|
+
const fallback = '<option value="">Auto</option><option value="" disabled>──────────</option><option value="__serve_cookbook__">+ Serve a model in Cookbook…</option>';
|
|
225
|
+
if (aiGenSelect) aiGenSelect.innerHTML = fallback;
|
|
226
|
+
if (aiInpaintSelect) aiInpaintSelect.innerHTML = fallback;
|
|
227
|
+
document.querySelectorAll('select.ge-tool-model').forEach(ts => { ts.innerHTML = fallback; });
|
|
228
|
+
const wireServe = (sel) => {
|
|
229
|
+
if (!sel) return;
|
|
230
|
+
let prev = sel.value;
|
|
231
|
+
sel.addEventListener('change', () => {
|
|
232
|
+
if (sel.value === '__serve_cookbook__') {
|
|
233
|
+
sel.value = prev;
|
|
234
|
+
openCookbookForImg2img();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
prev = sel.value;
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
wireServe(aiGenSelect);
|
|
241
|
+
wireServe(aiInpaintSelect);
|
|
242
|
+
document.querySelectorAll('select.ge-tool-model').forEach(wireServe);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
loadAIModels();
|
|
246
|
+
const onModelEndpointsUpdated = (e) => {
|
|
247
|
+
if (!container.isConnected) {
|
|
248
|
+
window.removeEventListener('ge:model-endpoints-updated', onModelEndpointsUpdated);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
loadAIModels({ selectBaseUrl: e.detail?.baseUrl || '' });
|
|
252
|
+
};
|
|
253
|
+
window.addEventListener('ge:model-endpoints-updated', onModelEndpointsUpdated);
|
|
254
|
+
// Re-fetch the model list when the user opens the inpaint dropdown,
|
|
255
|
+
// so a model served via Cookbook mid-edit shows up without having to
|
|
256
|
+
// close and reopen the editor. Debounced to one refresh per 3s so
|
|
257
|
+
// rapid open/close doesn't hammer the endpoint. Preserves the
|
|
258
|
+
// current selection across the reload.
|
|
259
|
+
let _lastModelRefresh = 0;
|
|
260
|
+
const refreshOnOpen = (e) => {
|
|
261
|
+
const sel = e.target.closest('#ge-ai-inpaint, select.ge-tool-model');
|
|
262
|
+
if (!sel) return;
|
|
263
|
+
const now = Date.now();
|
|
264
|
+
if (now - _lastModelRefresh < 3000) return;
|
|
265
|
+
_lastModelRefresh = now;
|
|
266
|
+
const keep = sel.value;
|
|
267
|
+
loadAIModels().then(() => {
|
|
268
|
+
// Restore the prior selection if it still exists.
|
|
269
|
+
if ([...sel.options].some(o => o.value === keep)) sel.value = keep;
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
container.addEventListener('mousedown', refreshOnOpen, true);
|
|
273
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Remove (rembg) + Sharpen wiring + the live edge-cleanup
|
|
3
|
+
* tuner that runs on the most-recent rembg cutout.
|
|
4
|
+
*
|
|
5
|
+
* rembg-run button: flatten + POST to /api/image/remove-bg with an
|
|
6
|
+
* optional hint_mask if the user has a wand/lasso selection
|
|
7
|
+
* active. After the new layer lands, hides every previously-
|
|
8
|
+
* visible layer so the cutout reads cleanly, and binds the
|
|
9
|
+
* live-tuner to the new layer.
|
|
10
|
+
*
|
|
11
|
+
* Live edge-cleanup tuner: snapshots the pristine cutout the
|
|
12
|
+
* moment it lands; subsequent feather/grow slider tweaks
|
|
13
|
+
* rebuild the layer's alpha from that snapshot WITHOUT
|
|
14
|
+
* re-running the model.
|
|
15
|
+
* - Grow > 0 → blur snap alpha, threshold low (32) → grow.
|
|
16
|
+
* - Grow < 0 → blur snap alpha, threshold high (200) → shrink.
|
|
17
|
+
* - Feather > 0 → blur the whole layer (alpha + RGB) so the
|
|
18
|
+
* edge softens AND the residual color fringe from the
|
|
19
|
+
* original background gets blurred away.
|
|
20
|
+
*
|
|
21
|
+
* Sharpen: small slider + button; just calls _applyImageTool
|
|
22
|
+
* against /api/image/sharpen.
|
|
23
|
+
*
|
|
24
|
+
* buildSelectionHintMask: pure-ish utility — returns a base64 PNG
|
|
25
|
+
* (no data: prefix) of the active wand or lasso selection, or
|
|
26
|
+
* null. Returned so other wand-rembg call sites can use it.
|
|
27
|
+
*
|
|
28
|
+
* @param {{
|
|
29
|
+
* applyImageTool: (endpoint, payload, layerName, btn, opts?) => Promise<void>,
|
|
30
|
+
* openCookbookForDependency: (pkg: string) => void,
|
|
31
|
+
* composite: () => void,
|
|
32
|
+
* renderLayerPanel: () => void,
|
|
33
|
+
* uiModule: object,
|
|
34
|
+
* }} deps
|
|
35
|
+
*
|
|
36
|
+
* @returns {{ buildSelectionHintMask: () => string | null }}
|
|
37
|
+
*/
|
|
38
|
+
import { state } from './state.js';
|
|
39
|
+
|
|
40
|
+
export function wireRembgAndSharpen({
|
|
41
|
+
applyImageTool, openCookbookForDependency,
|
|
42
|
+
composite, renderLayerPanel, uiModule,
|
|
43
|
+
}) {
|
|
44
|
+
// ── Sharpen ──
|
|
45
|
+
const sharpenPrev = document.getElementById('ge-sharpen-preview');
|
|
46
|
+
if (sharpenPrev) sharpenPrev.style.opacity = '0.5';
|
|
47
|
+
document.getElementById('ge-sharpen-amount')?.addEventListener('input', (e) => {
|
|
48
|
+
document.getElementById('ge-sharpen-label').textContent = e.target.value + '%';
|
|
49
|
+
if (sharpenPrev) sharpenPrev.style.opacity = (parseInt(e.target.value, 10) / 100).toFixed(2);
|
|
50
|
+
});
|
|
51
|
+
document.getElementById('ge-sharpen-run')?.addEventListener('click', () => {
|
|
52
|
+
const amount = parseInt(document.getElementById('ge-sharpen-amount')?.value || '50');
|
|
53
|
+
applyImageTool('/api/image/sharpen', { amount }, 'Sharpened', document.getElementById('ge-sharpen-run'));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ── Bg Remove ──
|
|
57
|
+
document.getElementById('ge-rembg-install-link')?.addEventListener('click', () => {
|
|
58
|
+
openCookbookForDependency('rembg');
|
|
59
|
+
});
|
|
60
|
+
document.getElementById('ge-rembg-run')?.addEventListener('click', async () => {
|
|
61
|
+
const payload = {};
|
|
62
|
+
const hint = buildSelectionHintMask();
|
|
63
|
+
if (hint) payload.hint_mask = hint;
|
|
64
|
+
// NB: edge_feather / edge_grow are applied CLIENT-side so the
|
|
65
|
+
// sliders can re-tune the cutout without re-running the model.
|
|
66
|
+
const btn = document.getElementById('ge-rembg-run');
|
|
67
|
+
const before = state.layers.length;
|
|
68
|
+
// Snapshot which layers were visible BEFORE the run so we know
|
|
69
|
+
// which to hide after a successful cutout.
|
|
70
|
+
const prevVisible = state.layers.filter(l => l.visible).map(l => l.id);
|
|
71
|
+
await applyImageTool('/api/image/remove-bg', payload, 'BG Removed', btn);
|
|
72
|
+
// applyImageTool finishes after fetch but the new layer is added
|
|
73
|
+
// inside img.onload (one tick later). Poll for up to 60 frames
|
|
74
|
+
// (~1s) for the new layer to appear before we auto-hide.
|
|
75
|
+
let frames = 0;
|
|
76
|
+
while (state.layers.length <= before && frames < 60) {
|
|
77
|
+
await new Promise(r => requestAnimationFrame(r));
|
|
78
|
+
frames++;
|
|
79
|
+
}
|
|
80
|
+
if (state.layers.length > before) {
|
|
81
|
+
const newLayer = state.layers[state.layers.length - 1];
|
|
82
|
+
bindRembgLiveTuner(newLayer);
|
|
83
|
+
// Auto-hide underlying layers so the user sees just the
|
|
84
|
+
// cutout — the eye toggles back on if they re-enable manually.
|
|
85
|
+
for (const layer of state.layers) {
|
|
86
|
+
if (prevVisible.includes(layer.id) && layer.id !== newLayer.id) {
|
|
87
|
+
layer.visible = false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
composite();
|
|
91
|
+
renderLayerPanel();
|
|
92
|
+
}
|
|
93
|
+
// Reset sliders so the new cutout starts clean.
|
|
94
|
+
const f = document.getElementById('ge-rembg-feather');
|
|
95
|
+
const g = document.getElementById('ge-rembg-grow');
|
|
96
|
+
if (f) { f.value = 0; document.getElementById('ge-rembg-feather-label').textContent = '0px'; syncRembgFeather(0); }
|
|
97
|
+
if (g) { g.value = 0; document.getElementById('ge-rembg-grow-label').textContent = '0px'; syncRembgGrow(0); }
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// ── Live edge-cleanup tuner ──
|
|
101
|
+
// Snapshots the pristine cutout the moment it lands; slider tweaks
|
|
102
|
+
// rebuild alpha from that snapshot.
|
|
103
|
+
function bindRembgLiveTuner(layer) {
|
|
104
|
+
if (!layer) return;
|
|
105
|
+
const w = layer.canvas.width, h = layer.canvas.height;
|
|
106
|
+
const snap = document.createElement('canvas');
|
|
107
|
+
snap.width = w; snap.height = h;
|
|
108
|
+
snap.getContext('2d').drawImage(layer.canvas, 0, 0);
|
|
109
|
+
state.rembgLiveLayer = layer;
|
|
110
|
+
state.rembgLiveSnap = snap;
|
|
111
|
+
rembgApplyEdgeNow(); // initial pass (no-op at 0/0)
|
|
112
|
+
}
|
|
113
|
+
let rembgRaf = null;
|
|
114
|
+
function scheduleRembgApply() {
|
|
115
|
+
if (rembgRaf) return;
|
|
116
|
+
rembgRaf = requestAnimationFrame(() => { rembgRaf = null; rembgApplyEdgeNow(); });
|
|
117
|
+
}
|
|
118
|
+
function rembgApplyEdgeNow() {
|
|
119
|
+
if (!state.rembgLiveLayer || !state.rembgLiveSnap) return;
|
|
120
|
+
const feather = parseInt(document.getElementById('ge-rembg-feather')?.value || '0', 10);
|
|
121
|
+
const grow = parseInt(document.getElementById('ge-rembg-grow')?.value || '0', 10);
|
|
122
|
+
const layer = state.rembgLiveLayer;
|
|
123
|
+
const snap = state.rembgLiveSnap;
|
|
124
|
+
const w = snap.width, h = snap.height;
|
|
125
|
+
const lctx = layer.ctx;
|
|
126
|
+
|
|
127
|
+
// 1) Start fresh from the pristine cutout snapshot.
|
|
128
|
+
lctx.clearRect(0, 0, w, h);
|
|
129
|
+
lctx.drawImage(snap, 0, 0);
|
|
130
|
+
|
|
131
|
+
// 2) Edge ±N — dilate / erode alpha via blur+threshold:
|
|
132
|
+
// grow > 0 → low threshold (32) → halo counts as opaque → grows.
|
|
133
|
+
// grow < 0 → high threshold (200) → only solid interior → shrinks.
|
|
134
|
+
// RGB is kept; only alpha is replaced.
|
|
135
|
+
if (grow !== 0) {
|
|
136
|
+
const blurC = document.createElement('canvas');
|
|
137
|
+
blurC.width = w; blurC.height = h;
|
|
138
|
+
const bctx = blurC.getContext('2d');
|
|
139
|
+
bctx.filter = `blur(${Math.abs(grow)}px)`;
|
|
140
|
+
bctx.drawImage(snap, 0, 0);
|
|
141
|
+
bctx.filter = 'none';
|
|
142
|
+
const blurred = bctx.getImageData(0, 0, w, h).data;
|
|
143
|
+
const layerData = lctx.getImageData(0, 0, w, h);
|
|
144
|
+
const out = layerData.data;
|
|
145
|
+
const thr = grow > 0 ? 32 : 200;
|
|
146
|
+
for (let i = 0; i < out.length; i += 4) {
|
|
147
|
+
out[i + 3] = blurred[i + 3] >= thr ? 255 : 0;
|
|
148
|
+
}
|
|
149
|
+
lctx.putImageData(layerData, 0, 0);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 3) Feather softens whatever edge we have now. Blur the entire
|
|
153
|
+
// layer (alpha + RGB) — alpha gets smooth falloff, RGB gets a
|
|
154
|
+
// faint blur at the edge which actually helps hide residual
|
|
155
|
+
// colour fringing from the original background.
|
|
156
|
+
if (feather > 0) {
|
|
157
|
+
const fC = document.createElement('canvas');
|
|
158
|
+
fC.width = w; fC.height = h;
|
|
159
|
+
const fctx = fC.getContext('2d');
|
|
160
|
+
fctx.filter = `blur(${feather}px)`;
|
|
161
|
+
fctx.drawImage(layer.canvas, 0, 0);
|
|
162
|
+
fctx.filter = 'none';
|
|
163
|
+
lctx.clearRect(0, 0, w, h);
|
|
164
|
+
lctx.drawImage(fC, 0, 0);
|
|
165
|
+
}
|
|
166
|
+
composite();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ── Slider preview swatches + wiring ──
|
|
170
|
+
const rembgFeatherPrev = document.getElementById('ge-rembg-feather-preview');
|
|
171
|
+
const rembgGrowPrev = document.getElementById('ge-rembg-grow-preview');
|
|
172
|
+
function syncRembgFeather(v) {
|
|
173
|
+
if (!rembgFeatherPrev) return;
|
|
174
|
+
const inner = Math.max(0, 50 - v * 2.5);
|
|
175
|
+
rembgFeatherPrev.style.background = `radial-gradient(circle, var(--fg) 0%, var(--fg) ${inner}%, transparent 75%)`;
|
|
176
|
+
}
|
|
177
|
+
function syncRembgGrow(v) {
|
|
178
|
+
if (!rembgGrowPrev) return;
|
|
179
|
+
// -10..+10 → scale 0.6 .. 1.4 so the swatch visibly grows/shrinks.
|
|
180
|
+
const s = 1 + v * 0.04;
|
|
181
|
+
rembgGrowPrev.style.transform = `scale(${s})`;
|
|
182
|
+
rembgGrowPrev.style.background = v < 0 ? 'color-mix(in srgb, var(--fg) 40%, transparent)' : 'var(--fg)';
|
|
183
|
+
}
|
|
184
|
+
syncRembgFeather(2);
|
|
185
|
+
syncRembgGrow(0);
|
|
186
|
+
document.getElementById('ge-rembg-feather')?.addEventListener('input', (e) => {
|
|
187
|
+
const v = parseInt(e.target.value, 10);
|
|
188
|
+
document.getElementById('ge-rembg-feather-label').textContent = v + 'px';
|
|
189
|
+
syncRembgFeather(v);
|
|
190
|
+
scheduleRembgApply();
|
|
191
|
+
});
|
|
192
|
+
document.getElementById('ge-rembg-grow')?.addEventListener('input', (e) => {
|
|
193
|
+
const v = parseInt(e.target.value, 10);
|
|
194
|
+
document.getElementById('ge-rembg-grow-label').textContent = (v >= 0 ? '+' : '') + v + 'px';
|
|
195
|
+
syncRembgGrow(v);
|
|
196
|
+
scheduleRembgApply();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// ── Selection-hint mask builder (used here + by wand-rembg) ──
|
|
200
|
+
// Full-image white-on-transparent mask PNG (base64, no `data:`
|
|
201
|
+
// prefix) of whichever selection is active — wand first, lasso
|
|
202
|
+
// second. Returns null if neither has a selection.
|
|
203
|
+
function buildSelectionHintMask() {
|
|
204
|
+
const w = state.imgWidth, h = state.imgHeight;
|
|
205
|
+
if (state.wandMask && state.wandLayerId) {
|
|
206
|
+
const off = state.layerOffsets.get(state.wandLayerId) || { x: 0, y: 0 };
|
|
207
|
+
const c = document.createElement('canvas');
|
|
208
|
+
c.width = w; c.height = h;
|
|
209
|
+
c.getContext('2d').drawImage(state.wandMask, off.x, off.y);
|
|
210
|
+
return c.toDataURL('image/png').split(',')[1];
|
|
211
|
+
}
|
|
212
|
+
if (state.lassoPoints.length >= 3 && !state.lassoActive) {
|
|
213
|
+
const c = document.createElement('canvas');
|
|
214
|
+
c.width = w; c.height = h;
|
|
215
|
+
const ctx = c.getContext('2d');
|
|
216
|
+
ctx.fillStyle = '#fff';
|
|
217
|
+
ctx.beginPath();
|
|
218
|
+
ctx.moveTo(state.lassoPoints[0].x, state.lassoPoints[0].y);
|
|
219
|
+
for (let i = 1; i < state.lassoPoints.length; i++) {
|
|
220
|
+
ctx.lineTo(state.lassoPoints[i].x, state.lassoPoints[i].y);
|
|
221
|
+
}
|
|
222
|
+
ctx.closePath();
|
|
223
|
+
ctx.fill();
|
|
224
|
+
return c.toDataURL('image/png').split(',')[1];
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return { buildSelectionHintMask };
|
|
230
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared AI-tool runner. Used by Sharpen / Harmonize / Upscale / Style /
|
|
3
|
+
* Bg-Remove / etc. — every tool that flattens the document, POSTs the
|
|
4
|
+
* PNG to a server-side image endpoint, and drops the result back in
|
|
5
|
+
* as a new layer.
|
|
6
|
+
*
|
|
7
|
+
* Handles all the orchestration around the request:
|
|
8
|
+
*
|
|
9
|
+
* - Button busy state: swap label for "<verbing>…" + whirlpool
|
|
10
|
+
* spinner, lock width so the button doesn't visually jump.
|
|
11
|
+
* - Endpoint+model selection from the tool's own picker (or the
|
|
12
|
+
* global fallback) so the backend knows which model to invoke.
|
|
13
|
+
* - Response handling: decode the returned PNG, push it as a new
|
|
14
|
+
* layer, save state, composite, refresh the layer panel.
|
|
15
|
+
* - Error reporting: surface failures via toast. Detects "needs
|
|
16
|
+
* img2img server" and "package not installed" failure modes and
|
|
17
|
+
* surfaces an action-toast that opens Cookbook to fix.
|
|
18
|
+
*
|
|
19
|
+
* @param {{
|
|
20
|
+
* flatten: () => HTMLCanvasElement,
|
|
21
|
+
* saveState: (label?: string) => void,
|
|
22
|
+
* createLayer: (name: string, w: number, h: number) => object,
|
|
23
|
+
* composite: () => void,
|
|
24
|
+
* renderLayerPanel: () => void,
|
|
25
|
+
* deriveBusyLabel: (layerName: string) => string,
|
|
26
|
+
* getSelectedAIEndpoint: (type: string | null) => { endpoint?: string, model?: string },
|
|
27
|
+
* openCookbookForDependency: (pkg: string) => void,
|
|
28
|
+
* openCookbookForImg2img: () => void,
|
|
29
|
+
* spinnerModule: object,
|
|
30
|
+
* uiModule: object | null,
|
|
31
|
+
* }} deps
|
|
32
|
+
*
|
|
33
|
+
* @returns {(endpoint: string, extraPayload: object, layerName: string, btn: HTMLButtonElement, opts?: { busyLabel?: string }) => Promise<void>}
|
|
34
|
+
*/
|
|
35
|
+
import { state } from './state.js';
|
|
36
|
+
|
|
37
|
+
const KNOWN_DEPS = ['realesrgan', 'rembg'];
|
|
38
|
+
|
|
39
|
+
export function createApplyImageTool({
|
|
40
|
+
flatten, saveState, createLayer, composite, renderLayerPanel,
|
|
41
|
+
deriveBusyLabel, getSelectedAIEndpoint,
|
|
42
|
+
openCookbookForDependency, openCookbookForImg2img,
|
|
43
|
+
spinnerModule, uiModule,
|
|
44
|
+
}) {
|
|
45
|
+
return async function applyImageTool(endpoint, extraPayload, layerName, btn, opts) {
|
|
46
|
+
const origHTML = btn.innerHTML;
|
|
47
|
+
const origWidth = btn.offsetWidth; // lock width so the button doesn't jump
|
|
48
|
+
btn.disabled = true;
|
|
49
|
+
btn.classList.add('ge-btn-processing');
|
|
50
|
+
btn.style.minWidth = origWidth + 'px';
|
|
51
|
+
// Swap label for a "<verbing>…" text + whirlpool while the
|
|
52
|
+
// request runs. Falls back to deriving a busy label from
|
|
53
|
+
// layerName when the caller didn't supply one.
|
|
54
|
+
const busyLabel = (opts && opts.busyLabel) || deriveBusyLabel(layerName);
|
|
55
|
+
btn.innerHTML = '';
|
|
56
|
+
let btnSpinner = null;
|
|
57
|
+
try {
|
|
58
|
+
btnSpinner = spinnerModule.create('', 'clean', 'whirlpool');
|
|
59
|
+
const sp = btnSpinner.createElement();
|
|
60
|
+
btn.appendChild(sp);
|
|
61
|
+
const txt = document.createElement('span');
|
|
62
|
+
txt.className = 'ge-btn-busy-label';
|
|
63
|
+
txt.textContent = busyLabel;
|
|
64
|
+
btn.appendChild(txt);
|
|
65
|
+
btnSpinner.start();
|
|
66
|
+
} catch { btn.textContent = busyLabel; }
|
|
67
|
+
// Tool-specific model picker — pulled from the per-tool select
|
|
68
|
+
// (harmonize/style) if available, otherwise the global
|
|
69
|
+
// fallback. Derived from the endpoint URL.
|
|
70
|
+
if (!extraPayload._endpoint) {
|
|
71
|
+
const m = /\/api\/image\/([\w-]+)/.exec(endpoint || '');
|
|
72
|
+
const type = m ? m[1].replace('upscale-ai', 'upscale').replace('remove-bg', 'rembg') : null;
|
|
73
|
+
const sel = getSelectedAIEndpoint(type);
|
|
74
|
+
if (sel.endpoint) extraPayload._endpoint = sel.endpoint;
|
|
75
|
+
if (sel.model && !extraPayload._model) extraPayload._model = sel.model;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const flatCanvas = flatten();
|
|
79
|
+
const imageB64 = flatCanvas.toDataURL('image/png').split(',')[1];
|
|
80
|
+
const body = { image: imageB64, ...extraPayload };
|
|
81
|
+
const res = await fetch(endpoint, {
|
|
82
|
+
method: 'POST', credentials: 'same-origin',
|
|
83
|
+
headers: { 'Content-Type': 'application/json' },
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
let err = res.statusText;
|
|
88
|
+
try { const e = await res.json(); err = e.detail || e.error || err; } catch {}
|
|
89
|
+
throw new Error(err);
|
|
90
|
+
}
|
|
91
|
+
const data = await res.json();
|
|
92
|
+
if (data.error) throw new Error(data.error);
|
|
93
|
+
if (!data.image) throw new Error('No image returned');
|
|
94
|
+
const img = new Image();
|
|
95
|
+
img.onload = () => {
|
|
96
|
+
if (!state.editorOpen) return; // user closed mid-decode (v2 review HIGH-4)
|
|
97
|
+
saveState();
|
|
98
|
+
const layer = createLayer(layerName, state.imgWidth, state.imgHeight);
|
|
99
|
+
layer.ctx.drawImage(img, 0, 0);
|
|
100
|
+
state.layers.push(layer);
|
|
101
|
+
state.activeLayerId = layer.id;
|
|
102
|
+
composite();
|
|
103
|
+
renderLayerPanel();
|
|
104
|
+
if (uiModule) uiModule.showToast(layerName + ' complete', 4500);
|
|
105
|
+
};
|
|
106
|
+
img.onerror = () => { if (uiModule) uiModule.showToast('Failed to load result', 6000); };
|
|
107
|
+
img.src = 'data:image/png;base64,' + data.image;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
// Detect known failure modes and surface an action-toast.
|
|
110
|
+
const msg = (e?.message || '').toLowerCase();
|
|
111
|
+
const needsImg2Img = (
|
|
112
|
+
msg.includes('img2img') ||
|
|
113
|
+
msg.includes('diffusion server') ||
|
|
114
|
+
msg.includes("doesn't expose")
|
|
115
|
+
);
|
|
116
|
+
let depMatch = null;
|
|
117
|
+
for (const pkg of KNOWN_DEPS) {
|
|
118
|
+
if (msg.includes(`${pkg} not installed`) || msg.includes(`no module named '${pkg}'`)) {
|
|
119
|
+
depMatch = pkg; break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (uiModule) {
|
|
123
|
+
if (depMatch && uiModule.showToast.length >= 2) {
|
|
124
|
+
uiModule.showToast(layerName + ' failed: ' + depMatch + ' is not installed on the server.', {
|
|
125
|
+
duration: 9000,
|
|
126
|
+
action: `Install ${depMatch}`,
|
|
127
|
+
onAction: () => openCookbookForDependency(depMatch),
|
|
128
|
+
});
|
|
129
|
+
} else if (needsImg2Img && uiModule.showToast.length >= 2) {
|
|
130
|
+
uiModule.showToast(layerName + ' failed: ' + e.message, {
|
|
131
|
+
duration: 9000,
|
|
132
|
+
action: 'Open Cookbook',
|
|
133
|
+
onAction: () => openCookbookForImg2img(),
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
uiModule.showToast(layerName + ' failed: ' + e.message, 6000);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
} finally {
|
|
140
|
+
btn.disabled = false;
|
|
141
|
+
btn.classList.remove('ge-btn-processing');
|
|
142
|
+
try { btnSpinner?.destroy(); } catch {}
|
|
143
|
+
btn.innerHTML = origHTML;
|
|
144
|
+
btn.style.minWidth = '';
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|