jodit-pro 4.12.32 → 4.12.34
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/es2015/jodit.css +1 -1
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +8 -8
- package/es2015/jodit.js +38 -2
- package/es2015/jodit.min.js +2 -2
- package/es2015/plugins/ai-assistant-pro/ai-assistant-pro.css +34 -1
- package/es2015/plugins/ai-assistant-pro/ai-assistant-pro.js +596 -44
- package/es2015/plugins/ai-assistant-pro/ai-assistant-pro.min.css +1 -1
- package/es2015/plugins/ai-assistant-pro/ai-assistant-pro.min.js +33 -33
- package/es2015/plugins/autocomplete/autocomplete.css +1 -1
- package/es2015/plugins/autocomplete/autocomplete.js +1 -1
- package/es2015/plugins/autocomplete/autocomplete.min.js +1 -1
- package/es2015/plugins/backup/backup.css +1 -1
- package/es2015/plugins/backup/backup.js +1 -1
- package/es2015/plugins/backup/backup.min.js +1 -1
- package/es2015/plugins/button-generator/button-generator.css +1 -1
- package/es2015/plugins/button-generator/button-generator.js +1 -1
- package/es2015/plugins/button-generator/button-generator.min.js +1 -1
- package/es2015/plugins/change-case/change-case.js +1 -1
- package/es2015/plugins/change-case/change-case.min.js +1 -1
- package/es2015/plugins/color-picker/color-picker.css +1 -1
- package/es2015/plugins/color-picker/color-picker.js +1 -1
- package/es2015/plugins/color-picker/color-picker.min.js +1 -1
- package/es2015/plugins/emoji/emoji.css +1 -1
- package/es2015/plugins/emoji/emoji.js +1 -1
- package/es2015/plugins/emoji/emoji.min.js +1 -1
- package/es2015/plugins/export-docs/export-docs.js +1 -1
- package/es2015/plugins/export-docs/export-docs.min.js +1 -1
- package/es2015/plugins/finder/finder.css +1 -1
- package/es2015/plugins/finder/finder.js +1 -1
- package/es2015/plugins/finder/finder.min.js +1 -1
- package/es2015/plugins/google-maps/google-maps.css +1 -1
- package/es2015/plugins/google-maps/google-maps.js +1 -1
- package/es2015/plugins/google-maps/google-maps.min.js +1 -1
- package/es2015/plugins/google-search/google-search.js +1 -1
- package/es2015/plugins/google-search/google-search.min.js +1 -1
- package/es2015/plugins/highlight-signature/highlight-signature.js +1 -1
- package/es2015/plugins/highlight-signature/highlight-signature.min.js +1 -1
- package/es2015/plugins/iframe-editor/iframe-editor.css +1 -1
- package/es2015/plugins/iframe-editor/iframe-editor.js +1 -1
- package/es2015/plugins/iframe-editor/iframe-editor.min.js +1 -1
- package/es2015/plugins/keyboard/keyboard.css +1 -1
- package/es2015/plugins/keyboard/keyboard.js +1 -1
- package/es2015/plugins/keyboard/keyboard.min.js +1 -1
- package/es2015/plugins/mobile-view/mobile-view.js +1 -1
- package/es2015/plugins/mobile-view/mobile-view.min.js +1 -1
- package/es2015/plugins/page-break/page-break.js +1 -1
- package/es2015/plugins/page-break/page-break.min.js +1 -1
- package/es2015/plugins/paste-code/paste-code.css +1 -1
- package/es2015/plugins/paste-code/paste-code.js +1 -1
- package/es2015/plugins/paste-code/paste-code.min.js +1 -1
- package/es2015/plugins/paste-from-word/paste-from-word.js +1 -1
- package/es2015/plugins/paste-from-word/paste-from-word.min.js +1 -1
- package/es2015/plugins/show-blocks/show-blocks.js +1 -1
- package/es2015/plugins/show-blocks/show-blocks.min.js +1 -1
- package/es2015/plugins/style/style.css +1 -1
- package/es2015/plugins/style/style.js +1 -1
- package/es2015/plugins/style/style.min.js +1 -1
- package/es2015/plugins/templates/templates.css +1 -1
- package/es2015/plugins/templates/templates.js +1 -1
- package/es2015/plugins/templates/templates.min.js +1 -1
- package/es2015/plugins/todo-list/todo-list.css +1 -1
- package/es2015/plugins/todo-list/todo-list.js +1 -1
- package/es2015/plugins/todo-list/todo-list.min.js +1 -1
- package/es2015/plugins/translate/translate.css +1 -1
- package/es2015/plugins/translate/translate.js +1 -1
- package/es2015/plugins/translate/translate.min.js +1 -1
- package/es2015/plugins/tune-block/tune-block.css +1 -1
- package/es2015/plugins/tune-block/tune-block.js +1 -1
- package/es2015/plugins/tune-block/tune-block.min.js +1 -1
- package/es2018/jodit.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +6 -6
- package/es2018/jodit.min.js +2 -2
- package/es2018/plugins/ai-assistant-pro/ai-assistant-pro.min.css +1 -1
- package/es2018/plugins/ai-assistant-pro/ai-assistant-pro.min.js +38 -38
- package/es2018/plugins/autocomplete/autocomplete.min.js +1 -1
- package/es2018/plugins/backup/backup.min.js +1 -1
- package/es2018/plugins/button-generator/button-generator.min.js +1 -1
- package/es2018/plugins/change-case/change-case.min.js +1 -1
- package/es2018/plugins/color-picker/color-picker.min.js +1 -1
- package/es2018/plugins/emoji/emoji.min.js +1 -1
- package/es2018/plugins/export-docs/export-docs.min.js +1 -1
- package/es2018/plugins/finder/finder.min.js +1 -1
- package/es2018/plugins/google-maps/google-maps.min.js +1 -1
- package/es2018/plugins/google-search/google-search.min.js +1 -1
- package/es2018/plugins/highlight-signature/highlight-signature.min.js +1 -1
- package/es2018/plugins/iframe-editor/iframe-editor.min.js +1 -1
- package/es2018/plugins/keyboard/keyboard.min.js +1 -1
- package/es2018/plugins/mobile-view/mobile-view.min.js +1 -1
- package/es2018/plugins/page-break/page-break.min.js +1 -1
- package/es2018/plugins/paste-code/paste-code.min.js +1 -1
- package/es2018/plugins/paste-from-word/paste-from-word.min.js +1 -1
- package/es2018/plugins/show-blocks/show-blocks.min.js +1 -1
- package/es2018/plugins/style/style.min.js +1 -1
- package/es2018/plugins/templates/templates.min.js +1 -1
- package/es2018/plugins/todo-list/todo-list.min.js +1 -1
- package/es2018/plugins/translate/translate.min.js +1 -1
- package/es2018/plugins/tune-block/tune-block.min.js +1 -1
- package/es2021/jodit.css +1 -1
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +8 -8
- package/es2021/jodit.js +38 -2
- package/es2021/jodit.min.js +3 -3
- package/es2021/plugins/ai-assistant-pro/ai-assistant-pro.css +34 -1
- package/es2021/plugins/ai-assistant-pro/ai-assistant-pro.js +569 -42
- package/es2021/plugins/ai-assistant-pro/ai-assistant-pro.min.css +1 -1
- package/es2021/plugins/ai-assistant-pro/ai-assistant-pro.min.js +9 -9
- package/es2021/plugins/autocomplete/autocomplete.css +1 -1
- package/es2021/plugins/autocomplete/autocomplete.js +1 -1
- package/es2021/plugins/autocomplete/autocomplete.min.js +1 -1
- package/es2021/plugins/backup/backup.css +1 -1
- package/es2021/plugins/backup/backup.js +1 -1
- package/es2021/plugins/backup/backup.min.js +1 -1
- package/es2021/plugins/button-generator/button-generator.css +1 -1
- package/es2021/plugins/button-generator/button-generator.js +1 -1
- package/es2021/plugins/button-generator/button-generator.min.js +1 -1
- package/es2021/plugins/change-case/change-case.js +1 -1
- package/es2021/plugins/change-case/change-case.min.js +1 -1
- package/es2021/plugins/color-picker/color-picker.css +1 -1
- package/es2021/plugins/color-picker/color-picker.js +1 -1
- package/es2021/plugins/color-picker/color-picker.min.js +1 -1
- package/es2021/plugins/emoji/emoji.css +1 -1
- package/es2021/plugins/emoji/emoji.js +1 -1
- package/es2021/plugins/emoji/emoji.min.js +1 -1
- package/es2021/plugins/export-docs/export-docs.js +1 -1
- package/es2021/plugins/export-docs/export-docs.min.js +1 -1
- package/es2021/plugins/finder/finder.css +1 -1
- package/es2021/plugins/finder/finder.js +1 -1
- package/es2021/plugins/finder/finder.min.js +1 -1
- package/es2021/plugins/google-maps/google-maps.css +1 -1
- package/es2021/plugins/google-maps/google-maps.js +1 -1
- package/es2021/plugins/google-maps/google-maps.min.js +1 -1
- package/es2021/plugins/google-search/google-search.js +1 -1
- package/es2021/plugins/google-search/google-search.min.js +1 -1
- package/es2021/plugins/highlight-signature/highlight-signature.js +1 -1
- package/es2021/plugins/highlight-signature/highlight-signature.min.js +1 -1
- package/es2021/plugins/iframe-editor/iframe-editor.css +1 -1
- package/es2021/plugins/iframe-editor/iframe-editor.js +1 -1
- package/es2021/plugins/iframe-editor/iframe-editor.min.js +1 -1
- package/es2021/plugins/keyboard/keyboard.css +1 -1
- package/es2021/plugins/keyboard/keyboard.js +1 -1
- package/es2021/plugins/keyboard/keyboard.min.js +1 -1
- package/es2021/plugins/mobile-view/mobile-view.js +1 -1
- package/es2021/plugins/mobile-view/mobile-view.min.js +1 -1
- package/es2021/plugins/page-break/page-break.js +1 -1
- package/es2021/plugins/page-break/page-break.min.js +1 -1
- package/es2021/plugins/paste-code/paste-code.css +1 -1
- package/es2021/plugins/paste-code/paste-code.js +1 -1
- package/es2021/plugins/paste-code/paste-code.min.js +1 -1
- package/es2021/plugins/paste-from-word/paste-from-word.js +1 -1
- package/es2021/plugins/paste-from-word/paste-from-word.min.js +1 -1
- package/es2021/plugins/show-blocks/show-blocks.js +1 -1
- package/es2021/plugins/show-blocks/show-blocks.min.js +1 -1
- package/es2021/plugins/style/style.css +1 -1
- package/es2021/plugins/style/style.js +1 -1
- package/es2021/plugins/style/style.min.js +1 -1
- package/es2021/plugins/templates/templates.css +1 -1
- package/es2021/plugins/templates/templates.js +1 -1
- package/es2021/plugins/templates/templates.min.js +1 -1
- package/es2021/plugins/todo-list/todo-list.css +1 -1
- package/es2021/plugins/todo-list/todo-list.js +1 -1
- package/es2021/plugins/todo-list/todo-list.min.js +1 -1
- package/es2021/plugins/translate/translate.css +1 -1
- package/es2021/plugins/translate/translate.js +1 -1
- package/es2021/plugins/translate/translate.min.js +1 -1
- package/es2021/plugins/tune-block/tune-block.css +1 -1
- package/es2021/plugins/tune-block/tune-block.js +1 -1
- package/es2021/plugins/tune-block/tune-block.min.js +1 -1
- package/es2021.en/jodit.css +1 -1
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +25 -25
- package/es2021.en/jodit.js +38 -2
- package/es2021.en/jodit.min.js +3 -3
- package/es2021.en/plugins/ai-assistant-pro/ai-assistant-pro.css +34 -1
- package/es2021.en/plugins/ai-assistant-pro/ai-assistant-pro.js +569 -42
- package/es2021.en/plugins/ai-assistant-pro/ai-assistant-pro.min.css +1 -1
- package/es2021.en/plugins/ai-assistant-pro/ai-assistant-pro.min.js +9 -9
- package/es2021.en/plugins/autocomplete/autocomplete.css +1 -1
- package/es2021.en/plugins/autocomplete/autocomplete.js +1 -1
- package/es2021.en/plugins/autocomplete/autocomplete.min.js +1 -1
- package/es2021.en/plugins/backup/backup.css +1 -1
- package/es2021.en/plugins/backup/backup.js +1 -1
- package/es2021.en/plugins/backup/backup.min.js +1 -1
- package/es2021.en/plugins/button-generator/button-generator.css +1 -1
- package/es2021.en/plugins/button-generator/button-generator.js +1 -1
- package/es2021.en/plugins/button-generator/button-generator.min.js +1 -1
- package/es2021.en/plugins/change-case/change-case.js +1 -1
- package/es2021.en/plugins/change-case/change-case.min.js +1 -1
- package/es2021.en/plugins/color-picker/color-picker.css +1 -1
- package/es2021.en/plugins/color-picker/color-picker.js +1 -1
- package/es2021.en/plugins/color-picker/color-picker.min.js +1 -1
- package/es2021.en/plugins/emoji/emoji.css +1 -1
- package/es2021.en/plugins/emoji/emoji.js +1 -1
- package/es2021.en/plugins/emoji/emoji.min.js +1 -1
- package/es2021.en/plugins/export-docs/export-docs.js +1 -1
- package/es2021.en/plugins/export-docs/export-docs.min.js +1 -1
- package/es2021.en/plugins/finder/finder.css +1 -1
- package/es2021.en/plugins/finder/finder.js +1 -1
- package/es2021.en/plugins/finder/finder.min.js +1 -1
- package/es2021.en/plugins/google-maps/google-maps.css +1 -1
- package/es2021.en/plugins/google-maps/google-maps.js +1 -1
- package/es2021.en/plugins/google-maps/google-maps.min.js +1 -1
- package/es2021.en/plugins/google-search/google-search.js +1 -1
- package/es2021.en/plugins/google-search/google-search.min.js +1 -1
- package/es2021.en/plugins/highlight-signature/highlight-signature.js +1 -1
- package/es2021.en/plugins/highlight-signature/highlight-signature.min.js +1 -1
- package/es2021.en/plugins/iframe-editor/iframe-editor.css +1 -1
- package/es2021.en/plugins/iframe-editor/iframe-editor.js +1 -1
- package/es2021.en/plugins/iframe-editor/iframe-editor.min.js +1 -1
- package/es2021.en/plugins/keyboard/keyboard.css +1 -1
- package/es2021.en/plugins/keyboard/keyboard.js +1 -1
- package/es2021.en/plugins/keyboard/keyboard.min.js +1 -1
- package/es2021.en/plugins/mobile-view/mobile-view.js +1 -1
- package/es2021.en/plugins/mobile-view/mobile-view.min.js +1 -1
- package/es2021.en/plugins/page-break/page-break.js +1 -1
- package/es2021.en/plugins/page-break/page-break.min.js +1 -1
- package/es2021.en/plugins/paste-code/paste-code.css +1 -1
- package/es2021.en/plugins/paste-code/paste-code.js +1 -1
- package/es2021.en/plugins/paste-code/paste-code.min.js +1 -1
- package/es2021.en/plugins/paste-from-word/paste-from-word.js +1 -1
- package/es2021.en/plugins/paste-from-word/paste-from-word.min.js +1 -1
- package/es2021.en/plugins/show-blocks/show-blocks.js +1 -1
- package/es2021.en/plugins/show-blocks/show-blocks.min.js +1 -1
- package/es2021.en/plugins/style/style.css +1 -1
- package/es2021.en/plugins/style/style.js +1 -1
- package/es2021.en/plugins/style/style.min.js +1 -1
- package/es2021.en/plugins/templates/templates.css +1 -1
- package/es2021.en/plugins/templates/templates.js +1 -1
- package/es2021.en/plugins/templates/templates.min.js +1 -1
- package/es2021.en/plugins/todo-list/todo-list.css +1 -1
- package/es2021.en/plugins/todo-list/todo-list.js +1 -1
- package/es2021.en/plugins/todo-list/todo-list.min.js +1 -1
- package/es2021.en/plugins/translate/translate.css +1 -1
- package/es2021.en/plugins/translate/translate.js +1 -1
- package/es2021.en/plugins/translate/translate.min.js +1 -1
- package/es2021.en/plugins/tune-block/tune-block.css +1 -1
- package/es2021.en/plugins/tune-block/tune-block.js +1 -1
- package/es2021.en/plugins/tune-block/tune-block.min.js +1 -1
- package/es5/jodit.css +2 -2
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +38 -2
- package/es5/jodit.min.css +2 -2
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/ai-assistant-pro/ai-assistant-pro.css +34 -1
- package/es5/plugins/ai-assistant-pro/ai-assistant-pro.js +734 -44
- package/es5/plugins/ai-assistant-pro/ai-assistant-pro.min.css +1 -1
- package/es5/plugins/ai-assistant-pro/ai-assistant-pro.min.js +2 -2
- package/es5/plugins/autocomplete/autocomplete.css +1 -1
- package/es5/plugins/autocomplete/autocomplete.js +1 -1
- package/es5/plugins/autocomplete/autocomplete.min.js +1 -1
- package/es5/plugins/backup/backup.css +1 -1
- package/es5/plugins/backup/backup.js +1 -1
- package/es5/plugins/backup/backup.min.js +1 -1
- package/es5/plugins/button-generator/button-generator.css +1 -1
- package/es5/plugins/button-generator/button-generator.js +1 -1
- package/es5/plugins/button-generator/button-generator.min.js +1 -1
- package/es5/plugins/change-case/change-case.js +1 -1
- package/es5/plugins/change-case/change-case.min.js +1 -1
- package/es5/plugins/color-picker/color-picker.css +1 -1
- package/es5/plugins/color-picker/color-picker.js +1 -1
- package/es5/plugins/color-picker/color-picker.min.js +1 -1
- package/es5/plugins/emoji/emoji.css +1 -1
- package/es5/plugins/emoji/emoji.js +1 -1
- package/es5/plugins/emoji/emoji.min.js +1 -1
- package/es5/plugins/export-docs/export-docs.js +1 -1
- package/es5/plugins/export-docs/export-docs.min.js +1 -1
- package/es5/plugins/finder/finder.css +1 -1
- package/es5/plugins/finder/finder.js +1 -1
- package/es5/plugins/finder/finder.min.js +1 -1
- package/es5/plugins/google-maps/google-maps.css +1 -1
- package/es5/plugins/google-maps/google-maps.js +1 -1
- package/es5/plugins/google-maps/google-maps.min.js +1 -1
- package/es5/plugins/google-search/google-search.js +1 -1
- package/es5/plugins/google-search/google-search.min.js +1 -1
- package/es5/plugins/highlight-signature/highlight-signature.js +1 -1
- package/es5/plugins/highlight-signature/highlight-signature.min.js +1 -1
- package/es5/plugins/iframe-editor/iframe-editor.css +1 -1
- package/es5/plugins/iframe-editor/iframe-editor.js +1 -1
- package/es5/plugins/iframe-editor/iframe-editor.min.js +1 -1
- package/es5/plugins/keyboard/keyboard.css +1 -1
- package/es5/plugins/keyboard/keyboard.js +1 -1
- package/es5/plugins/keyboard/keyboard.min.js +1 -1
- package/es5/plugins/mobile-view/mobile-view.js +1 -1
- package/es5/plugins/mobile-view/mobile-view.min.js +1 -1
- package/es5/plugins/page-break/page-break.js +1 -1
- package/es5/plugins/page-break/page-break.min.js +1 -1
- package/es5/plugins/paste-code/paste-code.css +1 -1
- package/es5/plugins/paste-code/paste-code.js +1 -1
- package/es5/plugins/paste-code/paste-code.min.js +1 -1
- package/es5/plugins/paste-from-word/paste-from-word.js +1 -1
- package/es5/plugins/paste-from-word/paste-from-word.min.js +1 -1
- package/es5/plugins/show-blocks/show-blocks.js +1 -1
- package/es5/plugins/show-blocks/show-blocks.min.js +1 -1
- package/es5/plugins/style/style.css +1 -1
- package/es5/plugins/style/style.js +1 -1
- package/es5/plugins/style/style.min.js +1 -1
- package/es5/plugins/templates/templates.css +1 -1
- package/es5/plugins/templates/templates.js +1 -1
- package/es5/plugins/templates/templates.min.js +1 -1
- package/es5/plugins/todo-list/todo-list.css +1 -1
- package/es5/plugins/todo-list/todo-list.js +1 -1
- package/es5/plugins/todo-list/todo-list.min.js +1 -1
- package/es5/plugins/translate/translate.css +1 -1
- package/es5/plugins/translate/translate.js +1 -1
- package/es5/plugins/translate/translate.min.js +1 -1
- package/es5/plugins/tune-block/tune-block.css +1 -1
- package/es5/plugins/tune-block/tune-block.js +1 -1
- package/es5/plugins/tune-block/tune-block.min.js +1 -1
- package/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/plugins/ai-assistant-pro/config.js +1 -1
- package/esm/plugins/ai-assistant-pro/icons/microphone.svg.js +1 -0
- package/esm/plugins/ai-assistant-pro/interface/options.d.ts +35 -0
- package/esm/plugins/ai-assistant-pro/providers/jodit-ai-adapter.js +1 -1
- package/esm/plugins/ai-assistant-pro/ui/input-area/input-area.d.ts +20 -0
- package/esm/plugins/ai-assistant-pro/ui/input-area/input-area.js +2 -2
- package/esm/plugins/ai-assistant-pro/voice/microphone-streamer.d.ts +26 -0
- package/esm/plugins/ai-assistant-pro/voice/microphone-streamer.js +1 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-engine.d.ts +36 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-engine.js +0 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-input-button.d.ts +85 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-input-button.js +1 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-transcriber.d.ts +55 -0
- package/esm/plugins/ai-assistant-pro/voice/voice-transcriber.js +1 -0
- package/package.json +1 -1
- package/types/plugins/ai-assistant-pro/interface/options.d.ts +35 -0
- package/types/plugins/ai-assistant-pro/ui/input-area/input-area.d.ts +20 -0
- package/types/plugins/ai-assistant-pro/voice/microphone-streamer.d.ts +26 -0
- package/types/plugins/ai-assistant-pro/voice/voice-engine.d.ts +36 -0
- package/types/plugins/ai-assistant-pro/voice/voice-input-button.d.ts +85 -0
- package/types/plugins/ai-assistant-pro/voice/voice-transcriber.d.ts +55 -0
package/es5/polyfills.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var d=Object.defineProperty;var r=(e,t)=>d(e,"name",{value:t,configurable:!0});var n;import{base64ToFile as p}from"../ai-assistant-pro/helpers/base64tofile.js";import m from"./icons/add-context.svg.js";import c from"./icons/ai-assistant.svg.js";import f from"./icons/ai-commands.svg.js";import
|
|
1
|
+
var d=Object.defineProperty;var r=(e,t)=>d(e,"name",{value:t,configurable:!0});var n;import{base64ToFile as p}from"../ai-assistant-pro/helpers/base64tofile.js";import m from"./icons/add-context.svg.js";import c from"./icons/ai-assistant.svg.js";import f from"./icons/ai-commands.svg.js";import h from"./icons/chevron-right.svg.js";import g from"./icons/microphone.svg.js";import A from"./icons/send.svg.js";import x from"./icons/shield.svg.js";import C from"./icons/tool-bolt.svg.js";import{getAIProviderOptions as y,registerAIProvider as I}from"./providers/index.js";import{getToolNames as w}from"./tools/index.js";import{Config as s}from"jodit/esm/config.js";import{Icon as T}from"jodit/esm/core/ui/icon.js";import{aiAssitentCommands as b}from"jodit/esm/plugins/ai-assistant/config.js";import{marked as M}from"marked";T.set("ai-assistant-pro",c).set("ai-commands-pro",f).set("ai-add-context",m).set("send",A).set("microphone",g).set("tool-bolt",C).set("chevron-right",h).set("shield",x),s.prototype.aiAssistantPro={displayMode:"right",panelWidth:400,panelHeight:500,flightPanelHeight:250,dialogFullSize:!1,resizable:!0,apiMode:"incremental",apiRequest:null,maxRetries:3,requestTimeout:6e4*5,retryDelay:1e3,maxRecursionToolCallDepth:1e3,enabledTools:w(),customTools:[],toolPermissions:{},autoApproveTools:["readDocument","readBlocks","readSelection","insertHTML","addHTML"],alwaysDenyTools:[],defaultPermissionScope:"conversation",storage:"indexedDB",maxConversations:50,storageKey:"jodit-ai-assistant-pro",showConversationList:!0,enableMarkdown:!0,enableCodeHighlight:!0,maxMessageHeight:400,placeholderText:"Ask AI assistant...",sendShortcut:"Ctrl+Enter",showTimestamps:!0,formatTimestamp:r((e,t)=>{const o=new Date(e),i=new Date().getTime()-o.getTime();return i<6e4?t("Just now"):i<36e5?t("%dm ago",Math.floor(i/6e4)):i<864e5?t("%dh ago",Math.floor(i/36e5)):o.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})},"formatTimestamp"),formatMessageContent:r((e,t)=>M.parse(e,{breaks:!0,gfm:!0}),"formatMessageContent"),showAvatars:!0,showTypingIndicator:!0,includeSelectionByDefault:!0,maxContextRanges:5,showContextPreview:!0,sendOnEnter:!0,instructions:void 0,includeEditorMetadata:!1,autoOpen:!0,rememberLastConversation:!0,autoFocusInput:!0,voiceInputEnabled:!1,closeAfterInsert:!1,enableSoundNotifications:!1,debug:!1,textAutocompleteEnabled:!1,textAutocompleteApiRequest:null,textAutocompleteMinQueryLength:3,textAutocompleteMaxSuggestions:3,textAutocompleteDebounceMs:500,textAutocompleteCacheTTL:3e4,textAutocompleteCacheMaxSize:50,quickCommandsSilentMode:!1,quickCommandsDisplayMode:"flight",showCopyMessageAction:!0,showRestartMessageAction:!0,showEditMessageAction:!0,showDeleteMessageAction:!0,dialogSettings:{},allowEditDialogSettings:!1,allowEditDisplayMode:!0,allowEditPanelWidth:!0,initiallyOpened:!1,allowClose:!0,persistOpenState:!0,theme:"parent",allowEditTheme:!0,async uploadBase64Artifact(e,t){if(e.type==="image"&&e.data&&e.data.kind==="base64")try{const o=p(e.data.base64,e.id,e.mimeType),a=await t.uploader.upload([o]);return{...e,data:{kind:"url",url:a.baseurl+a.files[0]},metadata:{...e.metadata,filename:a.files[0]}}}catch(o){t.e.fire("error",o)}return e},getAIProviderOptions(e,t){return y(e,t)},registerAIProvider(e,t){I(e,t)}},s.prototype.controls.aiAssistantPro={icon:"ai-assistant-pro",tooltip:"AI Assistant",hotkeys:["ctrl+shift+a","cmd+shift+a"],exec(e){e.e.fire("openAIAssistantPro.ai-assistant-pro")},isDisabled(e){return!e.o.aiAssistantPro.apiRequest},getLabel(e){return e.o.aiAssistantPro.apiRequest?"AI Assistant":"AI Assistant (not configured)"}},s.prototype.controls.aiAddContext={icon:"ai-add-context",tooltip:"Add to AI Context",exec(e){e.e.fire("addContextToAIAssistant")},isDisabled(e){return e.o.aiAssistantPro.apiRequest?e.s.isCollapsed():!0}},s.prototype.controls.aiCommandsPro={icon:"ai-commands-pro",tooltip:"AI Commands",isDisabled(e){return!e.o.aiAssistantPro.apiRequest},list:b,exec(e,t,{control:o}){e.e.fire("executeQuickCommand.ai-assistant-pro",o.name)}};const l=((n=s.prototype.tuneBlock)===null||n===void 0?void 0:n.popup)||{},u={},v=["p","h1","h2","h3","h4","h5","h6","div","section","article","pre","blockquote","ul","ol","li","table","tr","td","th","img","figure"];v.forEach(e=>{const t=l[e]||["tune.up","tune.remove","tune.down"];u[e]=[...t,"|","aiAddContext"]}),s.prototype.tuneBlock&&(s.prototype.tuneBlock.popup={...l,...u});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="9" y="2" width="6" height="12" rx="3"></rect> <path d="M5 10v1a7 7 0 0 0 14 0v-1" fill="none"></path> <line x1="12" y1="18" x2="12" y2="22"></line> <line x1="8" y1="22" x2="16" y2="22"></line> </svg> ';export{e as default};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
5
|
*/
|
|
6
6
|
import type { IDictionary, IJodit, IViewBased } from "jodit/esm/types/index";
|
|
7
|
+
import type { VoiceEngineFactory } from "../voice/voice-engine";
|
|
7
8
|
import type { IAIArtifact } from "./artifacts";
|
|
8
9
|
import type { IAIAssistantrRequseter } from "./requests";
|
|
9
10
|
import type { IAIAssistantStorage } from "./storage";
|
|
@@ -283,6 +284,40 @@ export interface IAIAssistantProOptions {
|
|
|
283
284
|
* @default true
|
|
284
285
|
*/
|
|
285
286
|
autoFocusInput: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Voice dictation into the prompt — show the microphone button.
|
|
289
|
+
* Speech is transcribed through the Jodit transcription proxy
|
|
290
|
+
* (`wss://…/v1/ai/transcribe`). The `jodit-ai-adapter` provider fills
|
|
291
|
+
* `voiceInputUrl`/`voiceInputApiKey` automatically.
|
|
292
|
+
* @default false
|
|
293
|
+
*/
|
|
294
|
+
voiceInputEnabled: boolean;
|
|
295
|
+
/** Transcription proxy URL, e.g. `wss://cloud.xdsoft.net/v1/ai/transcribe`. */
|
|
296
|
+
voiceInputUrl?: string;
|
|
297
|
+
/** Cloud API key for voice transcription. */
|
|
298
|
+
voiceInputApiKey?: string;
|
|
299
|
+
/** Voice transcription model (mirrors `defaultModel`; server default if unset). */
|
|
300
|
+
voiceInputDefaultModel?: string;
|
|
301
|
+
/** Voice language hint, e.g. `en-US`. */
|
|
302
|
+
voiceInputLanguage?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Silence (ms) before a spoken phrase is committed. Lower = more frequent
|
|
305
|
+
* interim/final transcripts on shorter pauses (server clamps to 100–2000ms).
|
|
306
|
+
*/
|
|
307
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
308
|
+
/**
|
|
309
|
+
* Hands-free auto-send: while the microphone is on, if no further speech
|
|
310
|
+
* arrives for this many ms after a phrase, the prompt is sent automatically.
|
|
311
|
+
* `null`/unset disables it.
|
|
312
|
+
*/
|
|
313
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
314
|
+
/**
|
|
315
|
+
* Custom voice recognition engine. When set it **replaces** the built-in
|
|
316
|
+
* transcription-proxy engine, so you can dictate against any backend — e.g.
|
|
317
|
+
* `createOpenAIRealtimeVoiceEngine(...)` to talk to OpenAI Realtime directly.
|
|
318
|
+
* With a custom engine `voiceInputUrl`/`voiceInputApiKey` are not used.
|
|
319
|
+
*/
|
|
320
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
286
321
|
/**
|
|
287
322
|
* Close panel after inserting generated content
|
|
288
323
|
* @default false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var v=Object.defineProperty;var c=(e,t)=>v(e,"name",{value:t,configurable:!0});import{registerAIProvider as y}from"./registry.js";import{Ajax as l}from"jodit/esm/core/request/ajax.js";y("jodit-ai-adapter",(e=>{var t;const i=e.url.replace(/\/+$/,""),d=(t=e.provider)!==null&&t!==void 0?t:"openai",u=e.stream!==!1;return{apiMode:"incremental",maxRetries:0,voiceInputEnabled:!0,voiceInputUrl:`${i.replace(/^http/,"ws")}/v1/ai/transcribe`,voiceInputApiKey:e.apiKey,textAutocompleteEnabled:!0,textAutocompleteApiRequest:c(async(a,s,r)=>{var n;const o=new l({url:`${i}/ai/autocomplete?query=${encodeURIComponent(a)}&key=${encodeURIComponent(e.apiKey)}`,method:"POST",contentType:"application/json",data:{provider:d,context:{maxSuggestions:s}}});r.addEventListener("abort",()=>o.abort(),{once:!0});const p=await(await o.send()).json();return p.success&&(!((n=p.result)===null||n===void 0)&&n.suggestions)?p.result.suggestions:[]},"textAutocompleteApiRequest"),apiRequest:c(async(a,s)=>{const r=new l({url:`${i}/ai/request?key=${encodeURIComponent(e.apiKey)}`,method:"POST",contentType:"application/json",data:{provider:d,context:u?{...a,metadata:{...a.metadata,stream:!0}}:a}});if(s&&s.addEventListener("abort",()=>r.abort(),{once:!0}),!u)return{mode:"final",response:(await(await r.send()).json()).result};const n=r.stream();return{mode:"stream",stream:(async function*(){for await(const o of n)yield JSON.parse(o)})()}},"apiRequest")}}));
|
|
@@ -5,16 +5,26 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { IViewBased } from "jodit/esm/types/index";
|
|
7
7
|
import type { ISelectionContext } from "../../interface/index";
|
|
8
|
+
import type { VoiceEngineFactory } from "../../voice/voice-engine";
|
|
8
9
|
import { UIElement } from "jodit/esm/core/ui/index";
|
|
9
10
|
export declare class UIInputArea extends UIElement<IViewBased> {
|
|
10
11
|
protected options: {
|
|
11
12
|
placeholderText: string;
|
|
12
13
|
sendShortcut: string;
|
|
13
14
|
sendOnEnter: boolean;
|
|
15
|
+
voiceInputEnabled?: boolean;
|
|
16
|
+
voiceInputUrl?: string;
|
|
17
|
+
voiceInputApiKey?: string;
|
|
18
|
+
voiceInputDefaultModel?: string;
|
|
19
|
+
voiceInputLanguage?: string;
|
|
20
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
21
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
22
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
14
23
|
};
|
|
15
24
|
private textarea;
|
|
16
25
|
private sendButton;
|
|
17
26
|
private stopButton;
|
|
27
|
+
private voiceButton;
|
|
18
28
|
private contextBadges;
|
|
19
29
|
private contexts;
|
|
20
30
|
private isLoading;
|
|
@@ -23,11 +33,21 @@ export declare class UIInputArea extends UIElement<IViewBased> {
|
|
|
23
33
|
placeholderText: string;
|
|
24
34
|
sendShortcut: string;
|
|
25
35
|
sendOnEnter: boolean;
|
|
36
|
+
voiceInputEnabled?: boolean;
|
|
37
|
+
voiceInputUrl?: string;
|
|
38
|
+
voiceInputApiKey?: string;
|
|
39
|
+
voiceInputDefaultModel?: string;
|
|
40
|
+
voiceInputLanguage?: string;
|
|
41
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
42
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
43
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
26
44
|
});
|
|
27
45
|
setParentView(view: IViewBased): this;
|
|
28
46
|
protected render(): string;
|
|
29
47
|
protected onInputRowClick(): void;
|
|
30
48
|
protected afterRender(): void;
|
|
49
|
+
/** Grow the textarea to fit its content up to a max height, then scroll. */
|
|
50
|
+
private autosize;
|
|
31
51
|
private createControls;
|
|
32
52
|
private attachHandlers;
|
|
33
53
|
private onSend;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var v=Object.defineProperty;var
|
|
1
|
+
var v=Object.defineProperty;var a=(u,t)=>v(u,"name",{value:t,configurable:!0});var d,h=function(u,t,e,i){var n=arguments.length,s=n<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,e):i,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(u,t,e,i);else for(var l=u.length-1;l>=0;l--)(o=u[l])&&(s=(n<3?o(s):n>3?o(t,e,s):o(t,e))||s);return n>3&&s&&Object.defineProperty(t,e,s),s};import{VoiceInputButton as f}from"../../voice/voice-input-button.js";import{autobind as c,component as x,hook as g,watch as m}from"jodit/esm/core/decorators/index.js";import{assert as _}from"jodit/esm/core/helpers/utils/assert.js";import{UIElement as B}from"jodit/esm/core/ui/index.js";import{UIButton as p}from"jodit/esm/core/ui/button/index.js";import{UITextArea as y}from"jodit/esm/core/ui/form/inputs/area/area.js";let r=(d=class extends B{className(){return"UIInputArea"}constructor(t,e){super(t),this.options=e,this.textarea=null,this.sendButton=null,this.stopButton=null,this.voiceButton=null,this.contexts=[],this.isLoading=!1}setParentView(t){var e,i,n,s;return(e=this.textarea)===null||e===void 0||e.setParentView(t),(i=this.sendButton)===null||i===void 0||i.setParentView(t),(n=this.stopButton)===null||n===void 0||n.setParentView(t),(s=this.voiceButton)===null||s===void 0||s.setParentView(t),super.setParentView(t)}render(){return`<div class="&__container">
|
|
2
2
|
<div class="&__context-badges"></div>
|
|
3
3
|
<div class="&__loading-indicator">
|
|
4
4
|
<span class="&__loading-dot"></span>
|
|
@@ -9,4 +9,4 @@ var v=Object.defineProperty;var h=(d,t)=>v(d,"name",{value:t,configurable:!0});v
|
|
|
9
9
|
<div class="&__textarea-wrapper"></div>
|
|
10
10
|
<div class="&__buttons"></div>
|
|
11
11
|
</div>
|
|
12
|
-
</div>`}onInputRowClick(){var t;this.textarea!==this.j.od.activeElement&&((t=this.textarea)===null||t===void 0||t.focus())}afterRender(){this.contextBadges=this.getElm("context-badges"),this.createControls(),this.attachHandlers()}createControls(){const t=this.getElm("textarea-wrapper"),e=this.getElm("buttons");this.textarea=new
|
|
12
|
+
</div>`}onInputRowClick(){var t;this.textarea!==this.j.od.activeElement&&((t=this.textarea)===null||t===void 0||t.focus())}afterRender(){this.contextBadges=this.getElm("context-badges"),this.createControls(),this.attachHandlers(),this.autosize()}autosize(){var t;const e=(t=this.textarea)===null||t===void 0?void 0:t.nativeInput;if(!e)return;const i=160;e.style.height="auto",e.style.height=`${Math.min(e.scrollHeight,i)}px`,e.style.overflowY=e.scrollHeight>i?"auto":"hidden"}createControls(){const t=this.getElm("textarea-wrapper"),e=this.getElm("buttons");this.textarea=new y(this.j,{name:"message",placeholder:this.options.placeholderText,resizable:!1}),t.appendChild(this.textarea.container),this.sendButton=new p(this.j,{name:"send-message",icon:{name:"send"},variant:"initial",size:"middle"}),this.stopButton=new p(this.j,{name:"abort-message",icon:{name:"cancel"},variant:"default",size:"middle"}),this.stopButton.container.style.display="none",this.options.voiceInputEnabled&&(this.voiceButton=new f(this.j,{url:this.options.voiceInputUrl,apiKey:this.options.voiceInputApiKey,defaultModel:this.options.voiceInputDefaultModel,language:this.options.voiceInputLanguage,silenceTimeoutMs:this.options.voiceInputSilenceTimeoutMs,autoSendSilenceMs:this.options.voiceInputAutoSendSilenceMs,api:this.options.voiceInputApi},{getValue:a(()=>{var i,n;return(n=(i=this.textarea)===null||i===void 0?void 0:i.nativeInput.value)!==null&&n!==void 0?n:""},"getValue"),setValue:a((i,n)=>{if(this.textarea){if(this.textarea.value=i,n!==void 0){const s=this.textarea.nativeInput;s.selectionStart=n,s.selectionEnd=n}this.autosize()}},"setValue"),getSelection:a(()=>{var i,n,s;const o=(i=this.textarea)===null||i===void 0?void 0:i.nativeInput;if(!o)return{start:0,end:0};const l=o.value.length;return{start:(n=o.selectionStart)!==null&&n!==void 0?n:l,end:(s=o.selectionEnd)!==null&&s!==void 0?s:l}},"getSelection"),focus:a(()=>this.focus(),"focus"),send:a(()=>this.onSend(),"send")}),e.appendChild(this.voiceButton.container)),e.appendChild(this.sendButton.container),e.appendChild(this.stopButton.container)}attachHandlers(){this.j.e.on(this.sendButton,"click",this.onSend),this.j.e.on(this.stopButton,"click",this.onStop),this.j.e.on(this.textarea.nativeInput,"input",()=>this.autosize()),this.j.e.on(this.textarea.nativeInput,"keydown",t=>{const{sendShortcut:e,sendOnEnter:i}=this.options;if(e==="Ctrl+Enter"&&t.ctrlKey&&t.key==="Enter"){t.preventDefault(),this.onSend();return}if(t.key==="Escape"){this.j.e.fire("cancelEditMessage.ai-assistant-pro");return}t.key==="Enter"&&(i?t.shiftKey||(t.preventDefault(),this.onSend()):t.shiftKey&&(t.preventDefault(),this.onSend()))})}onSend(){var t;const e=(t=this.textarea)===null||t===void 0?void 0:t.value.trim();!e||this.isLoading||(this.j.e.fire("sendMessage.ai-assistant-pro",e),this.textarea&&(this.textarea.value="",this.autosize(),this.textarea.nativeInput.focus()))}onStop(){this.j.e.fire("abortRequest.ai-assistant-pro")}setContexts(t){this.contexts=t,this.updateContextBadges()}updateContextBadges(){if(this.contextBadges.innerHTML="",this.contexts.length===0){this.contextBadges.style.display="none";return}this.contextBadges.style.display="",this.contexts.forEach((t,e)=>{const i=this.createContextBadge(t,e);this.contextBadges.appendChild(i)})}createContextBadge(t,e){const i=this.j.c.div(this.getFullElName("context-badge")),n=this.j.c.span(),s=t.html.replace(/<[^>]*>/g,"").substring(0,20);n.textContent=t.blockIndex!==void 0?`Block ${t.blockIndex}: ${s}...`:`${s}...`;const o=this.j.c.span(this.getFullElName("context-remove"));return o.textContent="\xD7",o.setAttribute("data-index",String(e)),this.j.e.on(o,"click",()=>{this.j.e.fire("removeContext.ai-assistant-pro",e)}),i.appendChild(n),i.appendChild(o),i}setLoading(t){this.isLoading=t;const{sendButton:e,stopButton:i,textarea:n}=this;_(e&&i&&n,"Buttons must be initialized"),n.setMod("disabled",t),e.setMod("disabled",t),this.setMod("loading",t),t?(e.container.style.display="none",i.container.style.display=""):(e.container.style.display="",i.container.style.display="none")}focus(){var t;(t=this.textarea)===null||t===void 0||t.nativeInput.focus()}setValue(t){this.textarea&&(this.textarea.value=t,this.autosize())}getValue(){var t;return((t=this.textarea)===null||t===void 0?void 0:t.value.trim())||""}destruct(){var t,e,i,n;(t=this.textarea)===null||t===void 0||t.destruct(),(e=this.sendButton)===null||e===void 0||e.destruct(),(i=this.stopButton)===null||i===void 0||i.destruct(),(n=this.voiceButton)===null||n===void 0||n.destruct(),super.destruct()}},a(d,"UIInputArea"),d);h([m("input-row:click")],r.prototype,"onInputRowClick",null),h([g("ready")],r.prototype,"afterRender",null),h([c],r.prototype,"onSend",null),h([c],r.prototype,"onStop",null),r=h([x],r);export{r as UIInputArea};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
export declare class MicrophoneStreamer {
|
|
7
|
+
private readonly onFrame;
|
|
8
|
+
private stream;
|
|
9
|
+
private audioCtx;
|
|
10
|
+
private processor;
|
|
11
|
+
private source;
|
|
12
|
+
private zeroGain;
|
|
13
|
+
private running;
|
|
14
|
+
/**
|
|
15
|
+
* @param onFrame - receives each binary PCM16 audio frame to send upstream.
|
|
16
|
+
*/
|
|
17
|
+
constructor(onFrame: (frame: ArrayBufferView<ArrayBuffer>) => void);
|
|
18
|
+
/**
|
|
19
|
+
* Request the microphone and start streaming audio frames. Rejects if access
|
|
20
|
+
* is denied or the audio graph cannot start.
|
|
21
|
+
*/
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
/** Stop streaming and release the microphone and audio graph. */
|
|
24
|
+
stop(): void;
|
|
25
|
+
private stopTracks;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var h=Object.defineProperty;var a=(o,t)=>h(o,"name",{value:t,configurable:!0});const g=24e3;function d(o){const t=new Int16Array(o.length);for(let s=0;s<o.length;s++){const n=Math.max(-1,Math.min(1,o[s]));t[s]=n<0?n*32768:n*32767}return t}a(d,"floatTo16BitPCM");function f(o,t,s){if(s>=t)return o;const n=t/s,i=Math.round(o.length/n),r=new Float32Array(i);for(let e=0;e<i;e++)r[e]=o[Math.min(Math.round(e*n),o.length-1)];return r}a(f,"downsample");const c=class c{constructor(t){this.onFrame=t,this.stream=null,this.audioCtx=null,this.processor=null,this.source=null,this.zeroGain=null,this.running=!1}async start(){if(this.running=!0,this.stream=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),!this.running){this.stopTracks();return}const t=new AudioContext;if(t.state==="suspended"&&await t.resume(),!this.running){t.close();return}const s=t.createMediaStreamSource(this.stream),n=t.createScriptProcessor(4096,1,1),i=t.createGain();i.gain.value=0,n.onaudioprocess=r=>{if(!this.running)return;const e=r.inputBuffer.getChannelData(0),l=d(f(e,r.inputBuffer.sampleRate,24e3));this.onFrame(l)},s.connect(n),n.connect(i),i.connect(t.destination),this.audioCtx=t,this.source=s,this.processor=n,this.zeroGain=i}stop(){var t,s;this.running=!1,this.processor&&(this.processor.onaudioprocess=null,this.processor.disconnect(),this.processor=null),(t=this.zeroGain)===null||t===void 0||t.disconnect(),(s=this.source)===null||s===void 0||s.disconnect(),this.zeroGain=null,this.source=null,this.audioCtx&&(this.audioCtx.close(),this.audioCtx=null),this.stopTracks()}stopTracks(){var t;(t=this.stream)===null||t===void 0||t.getTracks().forEach(s=>s.stop()),this.stream=null}};a(c,"MicrophoneStreamer");let u=c;export{u as MicrophoneStreamer};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Pluggable voice-recognition engine contract. The mic button drives an engine
|
|
8
|
+
* and reacts to its callbacks; this lets you point voice dictation at any
|
|
9
|
+
* backend — the built-in Jodit transcription proxy, OpenAI Realtime directly, or
|
|
10
|
+
* your own service — via the `voiceInputApi` option.
|
|
11
|
+
*
|
|
12
|
+
* @module plugins/ai-assistant-pro/voice
|
|
13
|
+
*/
|
|
14
|
+
export interface IVoiceEngineCallbacks {
|
|
15
|
+
/** Recognition is live — audio is now streaming. */
|
|
16
|
+
onReady?(): void;
|
|
17
|
+
/** Interim (partial) transcript for the current phrase. */
|
|
18
|
+
onInterim?(text: string): void;
|
|
19
|
+
/** Committed transcript for a finished phrase. */
|
|
20
|
+
onFinal?(text: string): void;
|
|
21
|
+
/** A recoverable error (mic denied, connection/provider error). */
|
|
22
|
+
onError?(message: string): void;
|
|
23
|
+
/** The session ended. */
|
|
24
|
+
onEnd?(): void;
|
|
25
|
+
}
|
|
26
|
+
export interface IVoiceEngine {
|
|
27
|
+
/** Begin capturing and recognising speech. */
|
|
28
|
+
start(): void;
|
|
29
|
+
/** Stop and release resources. */
|
|
30
|
+
stop(): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Factory for a voice engine. Receives the mic button's callbacks and returns an
|
|
34
|
+
* engine bound to them. Assign to `voiceInputApi` to use a custom backend.
|
|
35
|
+
*/
|
|
36
|
+
export type VoiceEngineFactory = (callbacks: IVoiceEngineCallbacks) => IVoiceEngine;
|
|
File without changes
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
import type { IViewBased } from "jodit/esm/types/index";
|
|
7
|
+
import type { VoiceEngineFactory } from "./voice-engine";
|
|
8
|
+
/**
|
|
9
|
+
* Resolved voice settings the mic button needs (built by the input area from the
|
|
10
|
+
* flat `voiceInput*` options).
|
|
11
|
+
*
|
|
12
|
+
* @module plugins/ai-assistant-pro/voice
|
|
13
|
+
*/
|
|
14
|
+
export interface IVoiceInputConfig {
|
|
15
|
+
url?: string;
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
defaultModel?: string;
|
|
18
|
+
language?: string;
|
|
19
|
+
silenceTimeoutMs?: number;
|
|
20
|
+
autoSendSilenceMs?: number | null;
|
|
21
|
+
/** Custom recognition engine; when set it replaces the built-in proxy engine. */
|
|
22
|
+
api?: VoiceEngineFactory;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read/write access to the prompt the dictated text goes into.
|
|
26
|
+
*/
|
|
27
|
+
export interface IVoiceInputIO {
|
|
28
|
+
/** Raw current value (not trimmed). */
|
|
29
|
+
getValue(): string;
|
|
30
|
+
/** Replace the value and optionally place the caret at `caret`. */
|
|
31
|
+
setValue(value: string, caret?: number): void;
|
|
32
|
+
/** Current selection range within the value. */
|
|
33
|
+
getSelection(): {
|
|
34
|
+
start: number;
|
|
35
|
+
end: number;
|
|
36
|
+
};
|
|
37
|
+
focus(): void;
|
|
38
|
+
/** Send the current prompt (no-op if empty or a request is in flight). */
|
|
39
|
+
send(): void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The microphone button for the assistant input area. Toggles a
|
|
43
|
+
* `VoiceTranscriber` session and writes interim/final transcripts into the prompt
|
|
44
|
+
* (interim text is previewed; final phrases are appended).
|
|
45
|
+
*/
|
|
46
|
+
export declare class VoiceInputButton {
|
|
47
|
+
private readonly jodit;
|
|
48
|
+
private readonly config;
|
|
49
|
+
private readonly io;
|
|
50
|
+
private readonly button;
|
|
51
|
+
private engine;
|
|
52
|
+
/** Whether a recognition session is active. */
|
|
53
|
+
private listening;
|
|
54
|
+
/** Whether a phrase is in progress (between its first interim and its final). */
|
|
55
|
+
private phraseActive;
|
|
56
|
+
/** Prompt text before the caret, captured at the start of the current phrase. */
|
|
57
|
+
private before;
|
|
58
|
+
/** Prompt text after the caret (or selection), captured at phrase start. */
|
|
59
|
+
private after;
|
|
60
|
+
/** Pending hands-free auto-send timer id (0 = none). */
|
|
61
|
+
private autoSendTimer;
|
|
62
|
+
constructor(jodit: IViewBased, config: IVoiceInputConfig, io: IVoiceInputIO);
|
|
63
|
+
private onPromptSent;
|
|
64
|
+
get container(): HTMLElement;
|
|
65
|
+
setParentView(view: IViewBased): void;
|
|
66
|
+
private toggle;
|
|
67
|
+
private start;
|
|
68
|
+
private reset;
|
|
69
|
+
/**
|
|
70
|
+
* Schedule a hands-free auto-send after `autoSendSilenceMs` of no new speech.
|
|
71
|
+
* No-op when the option is unset/null.
|
|
72
|
+
*/
|
|
73
|
+
private scheduleAutoSend;
|
|
74
|
+
private clearAutoSend;
|
|
75
|
+
private setActive;
|
|
76
|
+
/**
|
|
77
|
+
* Insert the current phrase at the caret. The text around the caret (or
|
|
78
|
+
* selection) is captured once at the start of each phrase from the live input,
|
|
79
|
+
* so dictation lands where the cursor is, replaces any selection, and respects
|
|
80
|
+
* manual edits / sends between phrases. Subsequent interims of the same phrase
|
|
81
|
+
* replace its preview rather than accumulating.
|
|
82
|
+
*/
|
|
83
|
+
private insertPhrase;
|
|
84
|
+
destruct(): void;
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var u=Object.defineProperty;var n=(a,t)=>u(a,"name",{value:t,configurable:!0});import{VoiceTranscriber as d}from"./voice-transcriber.js";import{UIButton as f}from"jodit/esm/core/ui/button/index.js";const g="jodit-ai-voice-active",o=class o{constructor(t,s,e){this.jodit=t,this.config=s,this.io=e,this.engine=null,this.listening=!1,this.phraseActive=!1,this.before="",this.after="",this.autoSendTimer=0,this.onPromptSent=()=>{this.phraseActive=!1},this.toggle=()=>{var i;if(this.listening){(i=this.engine)===null||i===void 0||i.stop(),this.reset();return}this.start()},this.button=new f(t,{name:"voice-input",icon:{name:"microphone"},variant:"initial",size:"middle"}),this.button.container.setAttribute("title","Dictate"),this.button.container.setAttribute("data-ref","voiceInputButton"),this.jodit.e.on(this.button,"click",this.toggle),this.jodit.e.on("sendMessage.ai-assistant-pro",this.onPromptSent)}get container(){return this.button.container}setParentView(t){this.button.setParentView(t)}start(){const t={onInterim:n(e=>{this.clearAutoSend(),this.insertPhrase(e)},"onInterim"),onFinal:n(e=>{this.insertPhrase(e),this.phraseActive=!1,this.scheduleAutoSend()},"onFinal"),onError:n(()=>this.reset(),"onError"),onEnd:n(()=>this.reset(),"onEnd")};let s;if(this.config.api)s=this.config.api(t);else{const{url:e,apiKey:i}=this.config;if(!e||!i)return;s=new d({url:e,apiKey:i,model:this.config.defaultModel,language:this.config.language,silenceMs:this.config.silenceTimeoutMs,...t})}this.phraseActive=!1,this.engine=s,this.listening=!0,this.setActive(!0),s.start()}reset(){this.clearAutoSend(),this.setActive(!1),this.phraseActive=!1,this.listening=!1,this.engine=null,this.io.focus()}scheduleAutoSend(){this.clearAutoSend();const t=this.config.autoSendSilenceMs;t!=null&&(this.autoSendTimer=this.jodit.async.setTimeout(()=>{this.autoSendTimer=0,this.io.send()},t))}clearAutoSend(){this.autoSendTimer&&(this.jodit.async.clearTimeout(this.autoSendTimer),this.autoSendTimer=0)}setActive(t){this.button.container.classList.toggle(g,t)}insertPhrase(t){if(!this.phraseActive){this.phraseActive=!0;const{start:c,end:l}=this.io.getSelection(),h=this.io.getValue();this.before=h.slice(0,c),this.after=h.slice(l)}const e=(this.before.length>0&&!/\s$/.test(this.before)?" ":"")+t,i=this.before.length+e.length;this.io.setValue(this.before+e+this.after,i)}destruct(){var t;this.clearAutoSend(),this.jodit.e.off("sendMessage.ai-assistant-pro",this.onPromptSent),(t=this.engine)===null||t===void 0||t.stop(),this.engine=null,this.button.destruct()}};n(o,"VoiceInputButton");let r=o;export{r as VoiceInputButton};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
import type { IVoiceEngine } from "./voice-engine";
|
|
7
|
+
/**
|
|
8
|
+
* Streams microphone audio to the Jodit transcription proxy
|
|
9
|
+
* (`wss://…/v1/ai/transcribe`) and reports transcript events back. The cloud key
|
|
10
|
+
* stays on the server; the browser only opens an authenticated socket and sends
|
|
11
|
+
* binary PCM16 audio.
|
|
12
|
+
*
|
|
13
|
+
* The server speaks the JSON protocol `ready` / `delta` / `final` / `error`; this
|
|
14
|
+
* class translates it into callbacks the mic button consumes.
|
|
15
|
+
*
|
|
16
|
+
* @module plugins/ai-assistant-pro/voice
|
|
17
|
+
*/
|
|
18
|
+
export interface IVoiceTranscriberOptions {
|
|
19
|
+
/** Proxy endpoint, e.g. `wss://cloud.xdsoft.net/v1/ai/transcribe`. */
|
|
20
|
+
url: string;
|
|
21
|
+
/** Cloud API key (sent as the `key` query param). */
|
|
22
|
+
apiKey: string;
|
|
23
|
+
/** Transcription model; defaults to the server's default. */
|
|
24
|
+
model?: string;
|
|
25
|
+
/** BCP-47 language hint, e.g. `en-US`. */
|
|
26
|
+
language?: string;
|
|
27
|
+
/** Silence (ms) before a phrase is committed; sent as the `silence` param. */
|
|
28
|
+
silenceMs?: number;
|
|
29
|
+
/** Upstream session is live — audio is now streaming. */
|
|
30
|
+
onReady?: () => void;
|
|
31
|
+
/** Interim (partial) transcript for the current phrase. */
|
|
32
|
+
onInterim?: (text: string) => void;
|
|
33
|
+
/** Committed transcript for a finished phrase. */
|
|
34
|
+
onFinal?: (text: string) => void;
|
|
35
|
+
/** A recoverable error (mic denied, connection/provider error). */
|
|
36
|
+
onError?: (message: string) => void;
|
|
37
|
+
/** The session ended (socket closed). */
|
|
38
|
+
onEnd?: () => void;
|
|
39
|
+
}
|
|
40
|
+
export declare class VoiceTranscriber implements IVoiceEngine {
|
|
41
|
+
private readonly options;
|
|
42
|
+
private ws;
|
|
43
|
+
private streamer;
|
|
44
|
+
private running;
|
|
45
|
+
constructor(options: IVoiceTranscriberOptions);
|
|
46
|
+
get isActive(): boolean;
|
|
47
|
+
/** Open the socket and begin a transcription session. */
|
|
48
|
+
start(): void;
|
|
49
|
+
/** Stop the session and release the microphone. */
|
|
50
|
+
stop(): void;
|
|
51
|
+
private onMessage;
|
|
52
|
+
private startAudio;
|
|
53
|
+
private fail;
|
|
54
|
+
private finish;
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var d=(u,s)=>p(u,"name",{value:s,configurable:!0});import{MicrophoneStreamer as f}from"./microphone-streamer.js";const l=class l{constructor(s){this.options=s,this.ws=null,this.streamer=null,this.running=!1}get isActive(){return this.running}start(){if(this.running)return;this.running=!0;let s;try{const t=new URL(this.options.url);t.searchParams.set("key",this.options.apiKey),this.options.model&&t.searchParams.set("model",this.options.model),this.options.language&&t.searchParams.set("language",this.options.language),this.options.silenceMs!==void 0&&t.searchParams.set("silence",String(this.options.silenceMs)),s=t.toString()}catch{this.fail("Invalid transcription URL");return}const i=new WebSocket(s);i.binaryType="arraybuffer",this.ws=i,i.addEventListener("message",t=>this.onMessage(t)),i.addEventListener("error",()=>this.fail("Transcription connection error")),i.addEventListener("close",()=>this.finish())}stop(){var s;this.running&&(this.running=!1,(s=this.streamer)===null||s===void 0||s.stop(),this.streamer=null,this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING)&&this.ws.close())}onMessage(s){var i,t,n,r,h,a,o;if(typeof s.data!="string")return;let e;try{e=JSON.parse(s.data)}catch{return}switch(e.type){case"ready":(t=(i=this.options).onReady)===null||t===void 0||t.call(i),this.startAudio();break;case"delta":e.text&&((r=(n=this.options).onInterim)===null||r===void 0||r.call(n,e.text));break;case"final":e.text&&((a=(h=this.options).onFinal)===null||a===void 0||a.call(h,e.text));break;case"error":this.fail((o=e.message)!==null&&o!==void 0?o:"Transcription error");break}}startAudio(){if(!this.running||this.streamer)return;const s=new f(i=>{var t;((t=this.ws)===null||t===void 0?void 0:t.readyState)===WebSocket.OPEN&&this.ws.send(i)});this.streamer=s,s.start().catch(()=>{this.fail("Microphone access denied")})}fail(s){var i,t;(t=(i=this.options).onError)===null||t===void 0||t.call(i,s),this.stop()}finish(){var s,i,t;const n=this.running;this.running=!1,(s=this.streamer)===null||s===void 0||s.stop(),this.streamer=null,n&&((t=(i=this.options).onEnd)===null||t===void 0||t.call(i))}};d(l,"VoiceTranscriber");let c=l;export{c as VoiceTranscriber};
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
5
|
*/
|
|
6
6
|
import type { IDictionary, IJodit, IViewBased } from "jodit/esm/types/index";
|
|
7
|
+
import type { VoiceEngineFactory } from "../voice/voice-engine";
|
|
7
8
|
import type { IAIArtifact } from "./artifacts";
|
|
8
9
|
import type { IAIAssistantrRequseter } from "./requests";
|
|
9
10
|
import type { IAIAssistantStorage } from "./storage";
|
|
@@ -283,6 +284,40 @@ export interface IAIAssistantProOptions {
|
|
|
283
284
|
* @default true
|
|
284
285
|
*/
|
|
285
286
|
autoFocusInput: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Voice dictation into the prompt — show the microphone button.
|
|
289
|
+
* Speech is transcribed through the Jodit transcription proxy
|
|
290
|
+
* (`wss://…/v1/ai/transcribe`). The `jodit-ai-adapter` provider fills
|
|
291
|
+
* `voiceInputUrl`/`voiceInputApiKey` automatically.
|
|
292
|
+
* @default false
|
|
293
|
+
*/
|
|
294
|
+
voiceInputEnabled: boolean;
|
|
295
|
+
/** Transcription proxy URL, e.g. `wss://cloud.xdsoft.net/v1/ai/transcribe`. */
|
|
296
|
+
voiceInputUrl?: string;
|
|
297
|
+
/** Cloud API key for voice transcription. */
|
|
298
|
+
voiceInputApiKey?: string;
|
|
299
|
+
/** Voice transcription model (mirrors `defaultModel`; server default if unset). */
|
|
300
|
+
voiceInputDefaultModel?: string;
|
|
301
|
+
/** Voice language hint, e.g. `en-US`. */
|
|
302
|
+
voiceInputLanguage?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Silence (ms) before a spoken phrase is committed. Lower = more frequent
|
|
305
|
+
* interim/final transcripts on shorter pauses (server clamps to 100–2000ms).
|
|
306
|
+
*/
|
|
307
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
308
|
+
/**
|
|
309
|
+
* Hands-free auto-send: while the microphone is on, if no further speech
|
|
310
|
+
* arrives for this many ms after a phrase, the prompt is sent automatically.
|
|
311
|
+
* `null`/unset disables it.
|
|
312
|
+
*/
|
|
313
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
314
|
+
/**
|
|
315
|
+
* Custom voice recognition engine. When set it **replaces** the built-in
|
|
316
|
+
* transcription-proxy engine, so you can dictate against any backend — e.g.
|
|
317
|
+
* `createOpenAIRealtimeVoiceEngine(...)` to talk to OpenAI Realtime directly.
|
|
318
|
+
* With a custom engine `voiceInputUrl`/`voiceInputApiKey` are not used.
|
|
319
|
+
*/
|
|
320
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
286
321
|
/**
|
|
287
322
|
* Close panel after inserting generated content
|
|
288
323
|
* @default false
|
|
@@ -5,16 +5,26 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { IViewBased } from "jodit/esm/types/index";
|
|
7
7
|
import type { ISelectionContext } from "../../interface/index";
|
|
8
|
+
import type { VoiceEngineFactory } from "../../voice/voice-engine";
|
|
8
9
|
import { UIElement } from "jodit/esm/core/ui/index";
|
|
9
10
|
export declare class UIInputArea extends UIElement<IViewBased> {
|
|
10
11
|
protected options: {
|
|
11
12
|
placeholderText: string;
|
|
12
13
|
sendShortcut: string;
|
|
13
14
|
sendOnEnter: boolean;
|
|
15
|
+
voiceInputEnabled?: boolean;
|
|
16
|
+
voiceInputUrl?: string;
|
|
17
|
+
voiceInputApiKey?: string;
|
|
18
|
+
voiceInputDefaultModel?: string;
|
|
19
|
+
voiceInputLanguage?: string;
|
|
20
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
21
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
22
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
14
23
|
};
|
|
15
24
|
private textarea;
|
|
16
25
|
private sendButton;
|
|
17
26
|
private stopButton;
|
|
27
|
+
private voiceButton;
|
|
18
28
|
private contextBadges;
|
|
19
29
|
private contexts;
|
|
20
30
|
private isLoading;
|
|
@@ -23,11 +33,21 @@ export declare class UIInputArea extends UIElement<IViewBased> {
|
|
|
23
33
|
placeholderText: string;
|
|
24
34
|
sendShortcut: string;
|
|
25
35
|
sendOnEnter: boolean;
|
|
36
|
+
voiceInputEnabled?: boolean;
|
|
37
|
+
voiceInputUrl?: string;
|
|
38
|
+
voiceInputApiKey?: string;
|
|
39
|
+
voiceInputDefaultModel?: string;
|
|
40
|
+
voiceInputLanguage?: string;
|
|
41
|
+
voiceInputSilenceTimeoutMs?: number;
|
|
42
|
+
voiceInputAutoSendSilenceMs?: number | null;
|
|
43
|
+
voiceInputApi?: VoiceEngineFactory;
|
|
26
44
|
});
|
|
27
45
|
setParentView(view: IViewBased): this;
|
|
28
46
|
protected render(): string;
|
|
29
47
|
protected onInputRowClick(): void;
|
|
30
48
|
protected afterRender(): void;
|
|
49
|
+
/** Grow the textarea to fit its content up to a max height, then scroll. */
|
|
50
|
+
private autosize;
|
|
31
51
|
private createControls;
|
|
32
52
|
private attachHandlers;
|
|
33
53
|
private onSend;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
export declare class MicrophoneStreamer {
|
|
7
|
+
private readonly onFrame;
|
|
8
|
+
private stream;
|
|
9
|
+
private audioCtx;
|
|
10
|
+
private processor;
|
|
11
|
+
private source;
|
|
12
|
+
private zeroGain;
|
|
13
|
+
private running;
|
|
14
|
+
/**
|
|
15
|
+
* @param onFrame - receives each binary PCM16 audio frame to send upstream.
|
|
16
|
+
*/
|
|
17
|
+
constructor(onFrame: (frame: ArrayBufferView<ArrayBuffer>) => void);
|
|
18
|
+
/**
|
|
19
|
+
* Request the microphone and start streaming audio frames. Rejects if access
|
|
20
|
+
* is denied or the audio graph cannot start.
|
|
21
|
+
*/
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
/** Stop streaming and release the microphone and audio graph. */
|
|
24
|
+
stop(): void;
|
|
25
|
+
private stopTracks;
|
|
26
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor PRO (https://xdsoft.net/jodit/)
|
|
3
|
+
* See LICENSE.md in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net/jodit/pro/
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Pluggable voice-recognition engine contract. The mic button drives an engine
|
|
8
|
+
* and reacts to its callbacks; this lets you point voice dictation at any
|
|
9
|
+
* backend — the built-in Jodit transcription proxy, OpenAI Realtime directly, or
|
|
10
|
+
* your own service — via the `voiceInputApi` option.
|
|
11
|
+
*
|
|
12
|
+
* @module plugins/ai-assistant-pro/voice
|
|
13
|
+
*/
|
|
14
|
+
export interface IVoiceEngineCallbacks {
|
|
15
|
+
/** Recognition is live — audio is now streaming. */
|
|
16
|
+
onReady?(): void;
|
|
17
|
+
/** Interim (partial) transcript for the current phrase. */
|
|
18
|
+
onInterim?(text: string): void;
|
|
19
|
+
/** Committed transcript for a finished phrase. */
|
|
20
|
+
onFinal?(text: string): void;
|
|
21
|
+
/** A recoverable error (mic denied, connection/provider error). */
|
|
22
|
+
onError?(message: string): void;
|
|
23
|
+
/** The session ended. */
|
|
24
|
+
onEnd?(): void;
|
|
25
|
+
}
|
|
26
|
+
export interface IVoiceEngine {
|
|
27
|
+
/** Begin capturing and recognising speech. */
|
|
28
|
+
start(): void;
|
|
29
|
+
/** Stop and release resources. */
|
|
30
|
+
stop(): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Factory for a voice engine. Receives the mic button's callbacks and returns an
|
|
34
|
+
* engine bound to them. Assign to `voiceInputApi` to use a custom backend.
|
|
35
|
+
*/
|
|
36
|
+
export type VoiceEngineFactory = (callbacks: IVoiceEngineCallbacks) => IVoiceEngine;
|