Changeset 0.23.2 (#155)

This commit is contained in:
2026-03-06 23:17:03 +00:00
parent 4c6555cb06
commit 2dc4514a57
36 changed files with 2784 additions and 192 deletions

View File

@@ -206,22 +206,41 @@ const ChannelModels = {
// Build match list from ALL enabled models + personas (not just roster)
const allModels = (App.models || []).filter(m => !m.hidden);
const matches = allModels.filter(m => {
// Match against persona handle
const modelMatches = allModels.filter(m => {
const handle = (m.personaHandle || '').toLowerCase().replace(/-/g, ' ');
// Match against model ID
const modelId = (m.baseModelId || m.id || '').toLowerCase().replace(/-/g, ' ');
// Match against display name
const name = (m.name || '').toLowerCase().replace(/-/g, ' ');
const firstName = name.split(' ')[0] || '';
if (partial.length === 0) return true; // show all on bare @
if (partial.length === 0) return true;
return handle.startsWith(partial)
|| modelId.startsWith(partial)
|| name.startsWith(partial)
|| firstName.startsWith(partial);
});
// v0.23.2: Include users in autocomplete (after personas, before models)
const userMatches = (App.users || []).filter(u => {
const uname = u.username.toLowerCase();
const dname = (u.displayName || '').toLowerCase();
if (partial.length === 0) return true;
return uname.startsWith(partial) || dname.startsWith(partial);
}).map(u => ({
id: u.username,
name: u.displayName || u.username,
baseModelId: u.username,
isPersona: false,
isUser: true,
personaHandle: null,
personaAvatar: null,
provider: '',
}));
// Resolution order: personas first, then users, then models
const personas = modelMatches.filter(m => m.isPersona);
const models = modelMatches.filter(m => !m.isPersona);
const matches = [...personas, ...userMatches, ...models];
if (matches.length === 0) { this.hideAutocomplete(); return; }
// Cap at 10 to keep dropdown manageable
this.showAutocomplete(inputEl, atIdx, cursorPos, matches.slice(0, 10));
@@ -253,13 +272,17 @@ const ChannelModels = {
? `<img src="${esc(m.personaAvatar)}" class="mention-ac-avatar" alt="">`
: m.isPersona
? `<span class="mention-ac-avatar mention-ac-avatar-fallback">⚡</span>`
: `<span class="mention-ac-avatar mention-ac-avatar-fallback">🤖</span>`;
: m.isUser
? `<span class="mention-ac-avatar mention-ac-avatar-fallback mention-ac-user">👤</span>`
: `<span class="mention-ac-avatar mention-ac-avatar-fallback">🤖</span>`;
const handleText = m.isPersona && m.personaHandle
? `@${esc(m.personaHandle)}`
: `@${esc(m.baseModelId || m.id)}`;
: m.isUser
? `@${esc(m.baseModelId)}`
: `@${esc(m.baseModelId || m.id)}`;
const providerHint = m.provider ? esc(m.provider) : '';
const providerHint = m.isUser ? 'user' : (m.provider ? esc(m.provider) : '');
item.innerHTML = `${avatar}<div class="mention-ac-info"><span class="mention-ac-name">${esc(m.name || m.id)}</span><span class="mention-ac-handle">${handleText}</span></div><span class="mention-ac-model">${providerHint}</span>`;
item.addEventListener('click', () => {