|
|
|
|
|
|
|
|
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"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = ''; |
|
|
|
|
|
|
|
|
|
|
|
const chatLogEditor = await Editor.make() |
|
|
.config((ctx) => { |
|
|
ctx.set(rootCtx, chatLog); |
|
|
ctx.set(editorViewOptionsCtx, { editable: () => false }); |
|
|
}) |
|
|
.use(commonmark) |
|
|
.create(); |
|
|
|
|
|
let availableModels = []; |
|
|
|
|
|
|
|
|
const modelSlashSetup = createModelSlashPlugin({ |
|
|
getModels: () => availableModels, |
|
|
onSlashCommand: onSlashCommand |
|
|
}); |
|
|
|
|
|
|
|
|
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' |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const chatInputEditor = await crepeInput |
|
|
.editor.config(modelSlashSetup.config) |
|
|
.use(modelSlashSetup.plugin) |
|
|
.create(); |
|
|
|
|
|
|
|
|
(async () => { |
|
|
const { id, promise, cancel } = await worker.listChatModels({}, undefined); |
|
|
const out = await promise; |
|
|
|
|
|
|
|
|
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 + '**'); |
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
crepeInput.editor.action((ctx) => { |
|
|
const view = ctx.get(editorViewCtx); |
|
|
if (view && typeof view.focus === 'function') view.focus(); |
|
|
}); |
|
|
|
|
|
return { |
|
|
chatLogEditor, |
|
|
chatInputEditor, |
|
|
crepeInput |
|
|
}; |
|
|
} |
|
|
|