File size: 3,709 Bytes
811916b 37fed31 0282567 811916b 0282567 638c2d6 2a0250a 0282567 811916b 5d0136a 37fed31 4dc14dc 37fed31 5d0136a 37fed31 c86c048 4dc14dc 37fed31 811916b eeb4c01 811916b 638c2d6 2d06121 c86c048 4dc14dc c86c048 0282567 2d06121 c86c048 5e0e4e8 c86c048 638c2d6 4dc14dc 5e0e4e8 4dc14dc 638c2d6 45a40b2 638c2d6 4dc14dc 811916b c86c048 638c2d6 bca7b90 811916b c86c048 811916b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
// @ts-check
import {
defaultValueCtx,
Editor,
editorViewCtx,
editorViewOptionsCtx,
rootCtx
} from '@milkdown/core';
import { Crepe } from '@milkdown/crepe';
import { commonmark } from '@milkdown/kit/preset/commonmark';
import { createModelSlashPlugin } from './model-slash';
import { outputMessage } from './output-message';
import "@milkdown/crepe/theme/common/style.css";
import "@milkdown/crepe/theme/frame.css";
/**
* @typedef {{
* chatLog: HTMLElement,
* chatInput: HTMLElement,
* inputPlugins?: any[],
* onSlashCommand?: (command: string) => void | boolean | Promise<void | boolean>,
* worker?: any
* }} InitMilkdownOptions
*/
/**
* @param {InitMilkdownOptions} options
*/
export async function initMilkdown({
chatLog,
chatInput,
inputPlugins = [], // Keep for backward compatibility but not used for Crepe
onSlashCommand,
worker
}) {
if (chatLog) chatLog.textContent = 'Loading Milkdown...';
if (chatLog) chatLog.innerHTML = '';
if (chatInput) chatInput.innerHTML = '';
// Create read-only editor in .chat-log
const chatLogEditor = await Editor.make()
.config((ctx) => {
ctx.set(rootCtx, chatLog);
ctx.set(editorViewOptionsCtx, { editable: () => false });
})
.use(commonmark)
.create();
let availableModels = [];
// Create the model slash plugin configuration
const modelSlashSetup = createModelSlashPlugin({
getModels: () => availableModels,
onSlashCommand: onSlashCommand
});
// Create editable Crepe editor in .chat-input (without BlockEdit)
const crepeInput = new Crepe({
root: chatInput,
defaultValue: '',
features: {
[Crepe.Feature.BlockEdit]: false,
[Crepe.Feature.Placeholder]: true,
[Crepe.Feature.Cursor]: true,
[Crepe.Feature.ListItem]: true,
[Crepe.Feature.CodeMirror]: true,
[Crepe.Feature.ImageBlock]: true,
[Crepe.Feature.Table]: true,
[Crepe.Feature.Latex]: true,
[Crepe.Feature.Toolbar]: true,
[Crepe.Feature.LinkTooltip]: true,
},
featureConfigs: {
[Crepe.Feature.Placeholder]: {
text: 'Prompt or /model...',
mode: 'block'
}
}
});
// Create input editor with model slash plugin
// Apply the model slash plugin configuration before creating the editor
const chatInputEditor = await crepeInput
.editor.config(modelSlashSetup.config)
.use(modelSlashSetup.plugin)
.create();
// Fetch models in background and add model slash plugin when ready
(async () => {
const { id, promise, cancel } = await worker.listChatModels({}, undefined);
const out = await promise;
// Normalize possible response shapes
let entries = [];
if (Array.isArray(out)) entries = out;
else if (out && Array.isArray(out.models)) entries = out.models;
else if (out && Array.isArray(out.results)) entries = out.results;
else entries = [];
availableModels = entries.map(e => ({
id: e.id || e.modelId || '',
name: e.name || (e.id || e.modelId || '').split('/').pop(),
size:
((e.size_hint || '') + ' ' +
(e.info?.params || '')).trim(),
requiresAuth: e.classification === 'auth-protected' || e.requiresAuth,
}));
outputMessage('Models discovered: **' + availableModels.length + '**');
})();
// Auto-focus the Crepe input editor when ready
// Crepe exposes the underlying milkdown editor through .editor property
crepeInput.editor.action((ctx) => {
const view = ctx.get(editorViewCtx);
if (view && typeof view.focus === 'function') view.focus();
});
return {
chatLogEditor,
chatInputEditor,
crepeInput // Return the crepe instance for additional control
};
}
|