@jini-ai/ui 0.3.11 → 0.3.13

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.
Files changed (27) hide show
  1. package/dist/features/i18n/dictionaries/settings-dialog.ar.js +2 -2
  2. package/dist/features/i18n/dictionaries/settings-dialog.bn.js +2 -2
  3. package/dist/features/i18n/dictionaries/settings-dialog.de.js +2 -2
  4. package/dist/features/i18n/dictionaries/settings-dialog.en.js +2 -2
  5. package/dist/features/i18n/dictionaries/settings-dialog.es.js +2 -2
  6. package/dist/features/i18n/dictionaries/settings-dialog.fa.js +2 -2
  7. package/dist/features/i18n/dictionaries/settings-dialog.fr.js +2 -2
  8. package/dist/features/i18n/dictionaries/settings-dialog.hi.js +2 -2
  9. package/dist/features/i18n/dictionaries/settings-dialog.hu.js +2 -2
  10. package/dist/features/i18n/dictionaries/settings-dialog.id.js +2 -2
  11. package/dist/features/i18n/dictionaries/settings-dialog.it.js +2 -2
  12. package/dist/features/i18n/dictionaries/settings-dialog.ja.js +2 -2
  13. package/dist/features/i18n/dictionaries/settings-dialog.ko.js +2 -2
  14. package/dist/features/i18n/dictionaries/settings-dialog.pl.js +2 -2
  15. package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +2 -2
  16. package/dist/features/i18n/dictionaries/settings-dialog.ru.js +2 -2
  17. package/dist/features/i18n/dictionaries/settings-dialog.th.js +2 -2
  18. package/dist/features/i18n/dictionaries/settings-dialog.tr.js +2 -2
  19. package/dist/features/i18n/dictionaries/settings-dialog.uk.js +2 -2
  20. package/dist/features/i18n/dictionaries/settings-dialog.ur.js +2 -2
  21. package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +2 -2
  22. package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +2 -2
  23. package/dist/features/mcp-ui/surfaces/checkbox.d.ts +10 -0
  24. package/dist/features/mcp-ui/surfaces/checkbox.js +4 -0
  25. package/dist/features/mcp-ui/surfaces/confirmation.d.ts +26 -0
  26. package/dist/features/mcp-ui/surfaces/confirmation.js +95 -1
  27. package/package.json +3 -3
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_AR = {
48
48
  'Copy': 'نسخ',
49
49
  'Copy to clipboard': 'نسخ إلى الحافظة',
50
50
  'Could not load live models: {message}': 'تعذّر تحميل النماذج المباشرة: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'لا يوجد مفتاح API — يحتاج اختبار الاتصال إلى المفتاح من هذا المتصفح.',
52
- 'No API key — model discovery needs the key from this browser.': 'لا يوجد مفتاح API — يحتاج اكتشاف النماذج إلى المفتاح من هذا المتصفح.',
51
+ 'No API key saved. Save one to test the connection.': 'لا يوجد مفتاح API محفوظ. احفظ مفتاحًا لاختبار الاتصال.',
52
+ 'No API key saved. Save one to load models.': 'لا يوجد مفتاح API محفوظ. احفظ مفتاحًا لتحميل النماذج.',
53
53
  'Could not load skills: {error}': 'تعذّر تحميل المهارات: {error}',
54
54
  'Could not reach the daemon: {error}': 'تعذّر الوصول إلى الخدمة الخلفية: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'تعذّر الوصول إلى الخادم. تُعرض التغييرات المحلية فقط.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_BN = {
48
48
  'Copy': 'কপি করুন',
49
49
  'Copy to clipboard': 'ক্লিপবোর্ডে কপি করুন',
50
50
  'Could not load live models: {message}': 'লাইভ মডেল লোড করা যায়নি: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'কোনো API কী নেই — সংযোগ পরীক্ষার জন্য এই ব্রাউজার থেকে কী প্রয়োজন।',
52
- 'No API key — model discovery needs the key from this browser.': 'কোনো API কী নেই — মডেল খুঁজে পেতে এই ব্রাউজার থেকে কী প্রয়োজন।',
51
+ 'No API key saved. Save one to test the connection.': 'কোনো API কী সংরক্ষিত নেই। সংযোগ পরীক্ষা করতে একটি কী সংরক্ষণ করুন।',
52
+ 'No API key saved. Save one to load models.': 'কোনো API কী সংরক্ষিত নেই। মডেল লোড করতে একটি কী সংরক্ষণ করুন।',
53
53
  'Could not load skills: {error}': 'স্কিল লোড করা যায়নি: {error}',
54
54
  'Could not reach the daemon: {error}': 'ডিমনে পৌঁছানো যায়নি: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'সার্ভারে পৌঁছানো যায়নি। শুধু স্থানীয় পরিবর্তন দেখানো হচ্ছে।',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_DE = {
48
48
  'Copy': 'Kopieren',
49
49
  'Copy to clipboard': 'In die Zwischenablage kopieren',
50
50
  'Could not load live models: {message}': 'Live-Modelle konnten nicht geladen werden: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Kein API-Schlüssel — der Verbindungstest benötigt den Schlüssel aus diesem Browser.',
52
- 'No API key — model discovery needs the key from this browser.': 'Kein API-Schlüssel — die Modellerkennung benötigt den Schlüssel aus diesem Browser.',
51
+ 'No API key saved. Save one to test the connection.': 'Kein API-Schlüssel gespeichert. Speichern Sie einen, um die Verbindung zu testen.',
52
+ 'No API key saved. Save one to load models.': 'Kein API-Schlüssel gespeichert. Speichern Sie einen, um Modelle zu laden.',
53
53
  'Could not load skills: {error}': 'Skills konnten nicht geladen werden: {error}',
54
54
  'Could not reach the daemon: {error}': 'Der Daemon konnte nicht erreicht werden: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Der Server konnte nicht erreicht werden. Es werden nur lokale Änderungen angezeigt.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_EN = {
48
48
  'Copy': 'Copy',
49
49
  'Copy to clipboard': 'Copy to clipboard',
50
50
  'Could not load live models: {message}': 'Could not load live models: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'No API key — connection test needs the key from this browser.',
52
- 'No API key — model discovery needs the key from this browser.': 'No API key — model discovery needs the key from this browser.',
51
+ 'No API key saved. Save one to test the connection.': 'No API key saved. Save one to test the connection.',
52
+ 'No API key saved. Save one to load models.': 'No API key saved. Save one to load models.',
53
53
  'Could not load skills: {error}': 'Could not load skills: {error}',
54
54
  'Could not reach the daemon: {error}': 'Could not reach the daemon: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Could not reach the server. Showing local changes only.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_ES = {
48
48
  'Copy': 'Copiar',
49
49
  'Copy to clipboard': 'Copiar al portapapeles',
50
50
  'Could not load live models: {message}': 'No se pudieron cargar los modelos en vivo: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Sin clave de API: la prueba de conexión necesita la clave desde este navegador.',
52
- 'No API key — model discovery needs the key from this browser.': 'Sin clave de API: la detección de modelos necesita la clave desde este navegador.',
51
+ 'No API key saved. Save one to test the connection.': 'No hay ninguna clave de API guardada. Guarde una para probar la conexión.',
52
+ 'No API key saved. Save one to load models.': 'No hay ninguna clave de API guardada. Guarde una para cargar los modelos.',
53
53
  'Could not load skills: {error}': 'No se pudieron cargar las skills: {error}',
54
54
  'Could not reach the daemon: {error}': 'No se pudo contactar con el daemon: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'No se pudo contactar con el servidor. Mostrando solo cambios locales.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_FA = {
48
48
  'Copy': 'کپی',
49
49
  'Copy to clipboard': 'کپی در کلیپ‌بورد',
50
50
  'Could not load live models: {message}': 'بارگذاری مدل‌های زنده ممکن نشد: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'کلید API وجود ندارد — آزمون اتصال به کلید از همین مرورگر نیاز دارد.',
52
- 'No API key — model discovery needs the key from this browser.': 'کلید API وجود ندارد — کشف مدل‌ها به کلید از همین مرورگر نیاز دارد.',
51
+ 'No API key saved. Save one to test the connection.': 'هیچ کلید API ذخیره نشده است. برای آزمون اتصال یک کلید ذخیره کنید.',
52
+ 'No API key saved. Save one to load models.': 'هیچ کلید API ذخیره نشده است. برای بارگیری مدل‌ها یک کلید ذخیره کنید.',
53
53
  'Could not load skills: {error}': 'بارگذاری مهارت‌ها ممکن نشد: {error}',
54
54
  'Could not reach the daemon: {error}': 'ارتباط با دیمون برقرار نشد: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'ارتباط با سرور برقرار نشد. فقط تغییرات محلی نمایش داده می‌شود.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_FR = {
48
48
  'Copy': 'Copier',
49
49
  'Copy to clipboard': 'Copier dans le presse-papiers',
50
50
  'Could not load live models: {message}': 'Impossible de charger les modèles en direct : {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Aucune clé API — le test de connexion nécessite la clé depuis ce navigateur.',
52
- 'No API key — model discovery needs the key from this browser.': 'Aucune clé API — la découverte des modèles nécessite la clé depuis ce navigateur.',
51
+ 'No API key saved. Save one to test the connection.': 'Aucune clé API enregistrée. Enregistrez-en une pour tester la connexion.',
52
+ 'No API key saved. Save one to load models.': 'Aucune clé API enregistrée. Enregistrez-en une pour charger les modèles.',
53
53
  'Could not load skills: {error}': 'Impossible de charger les compétences : {error}',
54
54
  'Could not reach the daemon: {error}': 'Impossible de contacter le daemon : {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Impossible de contacter le serveur. Affichage des modifications locales uniquement.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_HI = {
48
48
  'Copy': 'कॉपी करें',
49
49
  'Copy to clipboard': 'क्लिपबोर्ड पर कॉपी करें',
50
50
  'Could not load live models: {message}': 'लाइव मॉडल लोड नहीं हो सके: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'कोई API कुंजी नहीं — कनेक्शन परीक्षण के लिए इस ब्राउज़र से कुंजी चाहिए।',
52
- 'No API key — model discovery needs the key from this browser.': 'कोई API कुंजी नहीं — मॉडल खोजने के लिए इस ब्राउज़र से कुंजी चाहिए।',
51
+ 'No API key saved. Save one to test the connection.': 'कोई API कुंजी सहेजी नहीं गई है। कनेक्शन जाँचने के लिए एक कुंजी सहेजें।',
52
+ 'No API key saved. Save one to load models.': 'कोई API कुंजी सहेजी नहीं गई है। मॉडल लोड करने के लिए एक कुंजी सहेजें।',
53
53
  'Could not load skills: {error}': 'स्किल्स लोड नहीं हो सकीं: {error}',
54
54
  'Could not reach the daemon: {error}': 'डेमन तक नहीं पहुंच सके: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'सर्वर तक नहीं पहुंच सके। केवल स्थानीय बदलाव दिखाए जा रहे हैं।',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_HU = {
48
48
  'Copy': 'Másolás',
49
49
  'Copy to clipboard': 'Másolás vágólapra',
50
50
  'Could not load live models: {message}': 'Nem sikerült betölteni az élő modelleket: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Nincs API-kulcs — a kapcsolati teszthez a kulcs szükséges ebből a böngészőből.',
52
- 'No API key — model discovery needs the key from this browser.': 'Nincs API-kulcs — a modellek felderítéséhez a kulcs szükséges ebből a böngészőből.',
51
+ 'No API key saved. Save one to test the connection.': 'Nincs mentett API-kulcs. Mentsen egyet a kapcsolat teszteléséhez.',
52
+ 'No API key saved. Save one to load models.': 'Nincs mentett API-kulcs. Mentsen egyet a modellek betöltéséhez.',
53
53
  'Could not load skills: {error}': 'Nem sikerült betölteni a képességeket: {error}',
54
54
  'Could not reach the daemon: {error}': 'Nem sikerült elérni a démont: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Nem sikerült elérni a szervert. Csak a helyi módosítások jelennek meg.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_ID = {
48
48
  'Copy': 'Salin',
49
49
  'Copy to clipboard': 'Salin ke clipboard',
50
50
  'Could not load live models: {message}': 'Tidak dapat memuat model live: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Tidak ada kunci API — uji koneksi memerlukan kunci dari browser ini.',
52
- 'No API key — model discovery needs the key from this browser.': 'Tidak ada kunci API — penemuan model memerlukan kunci dari browser ini.',
51
+ 'No API key saved. Save one to test the connection.': 'Belum ada kunci API yang disimpan. Simpan kunci untuk menguji koneksi.',
52
+ 'No API key saved. Save one to load models.': 'Belum ada kunci API yang disimpan. Simpan kunci untuk memuat model.',
53
53
  'Could not load skills: {error}': 'Tidak dapat memuat skill: {error}',
54
54
  'Could not reach the daemon: {error}': 'Tidak dapat menjangkau daemon: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Tidak dapat menjangkau server. Hanya menampilkan perubahan lokal.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_IT = {
48
48
  'Copy': 'Copia',
49
49
  'Copy to clipboard': 'Copia negli appunti',
50
50
  'Could not load live models: {message}': 'Impossibile caricare i modelli in tempo reale: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Nessuna chiave API — il test di connessione richiede la chiave da questo browser.',
52
- 'No API key — model discovery needs the key from this browser.': 'Nessuna chiave API — il rilevamento dei modelli richiede la chiave da questo browser.',
51
+ 'No API key saved. Save one to test the connection.': 'Nessuna chiave API salvata. Salvane una per testare la connessione.',
52
+ 'No API key saved. Save one to load models.': 'Nessuna chiave API salvata. Salvane una per caricare i modelli.',
53
53
  'Could not load skills: {error}': 'Impossibile caricare le competenze: {error}',
54
54
  'Could not reach the daemon: {error}': 'Impossibile contattare il daemon: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Impossibile contattare il server. Vengono mostrate solo le modifiche locali.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_JA = {
48
48
  'Copy': 'コピー',
49
49
  'Copy to clipboard': 'クリップボードにコピー',
50
50
  'Could not load live models: {message}': 'ライブモデルを読み込めませんでした:{message}',
51
- 'No API key — connection test needs the key from this browser.': 'API キーがありません — 接続テストには、このブラウザーからのキーが必要です。',
52
- 'No API key — model discovery needs the key from this browser.': 'API キーがありません — モデルの検出には、このブラウザーからのキーが必要です。',
51
+ 'No API key saved. Save one to test the connection.': 'API キーが保存されていません。接続をテストするにはキーを保存してください。',
52
+ 'No API key saved. Save one to load models.': 'API キーが保存されていません。モデルを読み込むにはキーを保存してください。',
53
53
  'Could not load skills: {error}': 'スキルを読み込めませんでした:{error}',
54
54
  'Could not reach the daemon: {error}': 'デーモンに接続できませんでした:{error}',
55
55
  'Could not reach the server. Showing local changes only.': 'サーバーに接続できませんでした。ローカルの変更のみ表示しています。',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_KO = {
48
48
  'Copy': '복사',
49
49
  'Copy to clipboard': '클립보드에 복사',
50
50
  'Could not load live models: {message}': '실시간 모델을 불러올 수 없습니다: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'API 키가 없습니다 — 연결 테스트에는 이 브라우저의 키가 필요합니다.',
52
- 'No API key — model discovery needs the key from this browser.': 'API 키가 없습니다 — 모델 검색에는 이 브라우저의 키가 필요합니다.',
51
+ 'No API key saved. Save one to test the connection.': '저장된 API 키가 없습니다. 연결을 테스트하려면 키를 저장하세요.',
52
+ 'No API key saved. Save one to load models.': '저장된 API 키가 없습니다. 모델을 불러오려면 키를 저장하세요.',
53
53
  'Could not load skills: {error}': '스킬을 불러올 수 없습니다: {error}',
54
54
  'Could not reach the daemon: {error}': '데몬에 연결할 수 없습니다: {error}',
55
55
  'Could not reach the server. Showing local changes only.': '서버에 연결할 수 없습니다. 로컬 변경 사항만 표시합니다.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_PL = {
48
48
  'Copy': 'Kopiuj',
49
49
  'Copy to clipboard': 'Kopiuj do schowka',
50
50
  'Could not load live models: {message}': 'Nie udało się wczytać modeli na żywo: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Brak klucza API — test połączenia wymaga klucza z tej przeglądarki.',
52
- 'No API key — model discovery needs the key from this browser.': 'Brak klucza API — wykrywanie modeli wymaga klucza z tej przeglądarki.',
51
+ 'No API key saved. Save one to test the connection.': 'Nie zapisano klucza API. Zapisz klucz, aby przetestować połączenie.',
52
+ 'No API key saved. Save one to load models.': 'Nie zapisano klucza API. Zapisz klucz, aby wczytać modele.',
53
53
  'Could not load skills: {error}': 'Nie udało się wczytać umiejętności: {error}',
54
54
  'Could not reach the daemon: {error}': 'Nie udało się połączyć z demonem: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Nie udało się połączyć z serwerem. Wyświetlane są tylko zmiany lokalne.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_PT_BR = {
48
48
  'Copy': 'Copiar',
49
49
  'Copy to clipboard': 'Copiar para a área de transferência',
50
50
  'Could not load live models: {message}': 'Não foi possível carregar os modelos em tempo real: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Sem chave de API — o teste de conexão precisa da chave deste navegador.',
52
- 'No API key — model discovery needs the key from this browser.': 'Sem chave de API — a descoberta de modelos precisa da chave deste navegador.',
51
+ 'No API key saved. Save one to test the connection.': 'Nenhuma chave de API salva. Salve uma para testar a conexão.',
52
+ 'No API key saved. Save one to load models.': 'Nenhuma chave de API salva. Salve uma para carregar os modelos.',
53
53
  'Could not load skills: {error}': 'Não foi possível carregar as skills: {error}',
54
54
  'Could not reach the daemon: {error}': 'Não foi possível contatar o daemon: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Não foi possível contatar o servidor. Mostrando apenas as alterações locais.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_RU = {
48
48
  'Copy': 'Копировать',
49
49
  'Copy to clipboard': 'Копировать в буфер обмена',
50
50
  'Could not load live models: {message}': 'Не удалось загрузить актуальные модели: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Нет API-ключа — для проверки подключения нужен ключ из этого браузера.',
52
- 'No API key — model discovery needs the key from this browser.': 'Нет API-ключа — для поиска моделей нужен ключ из этого браузера.',
51
+ 'No API key saved. Save one to test the connection.': 'API-ключ не сохранён. Сохраните ключ, чтобы проверить подключение.',
52
+ 'No API key saved. Save one to load models.': 'API-ключ не сохранён. Сохраните ключ, чтобы загрузить модели.',
53
53
  'Could not load skills: {error}': 'Не удалось загрузить навыки: {error}',
54
54
  'Could not reach the daemon: {error}': 'Не удалось связаться с демоном: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Не удалось связаться с сервером. Показаны только локальные изменения.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_TH = {
48
48
  'Copy': 'คัดลอก',
49
49
  'Copy to clipboard': 'คัดลอกไปยังคลิปบอร์ด',
50
50
  'Could not load live models: {message}': 'ไม่สามารถโหลดโมเดลแบบเรียลไทม์ได้: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'ไม่มีคีย์ API — การทดสอบการเชื่อมต่อต้องใช้คีย์จากเบราว์เซอร์นี้',
52
- 'No API key — model discovery needs the key from this browser.': 'ไม่มีคีย์ API — การค้นหาโมเดลต้องใช้คีย์จากเบราว์เซอร์นี้',
51
+ 'No API key saved. Save one to test the connection.': 'ยังไม่ได้บันทึกคีย์ API บันทึกคีย์ก่อนเพื่อทดสอบการเชื่อมต่อ',
52
+ 'No API key saved. Save one to load models.': 'ยังไม่ได้บันทึกคีย์ API บันทึกคีย์ก่อนเพื่อโหลดโมเดล',
53
53
  'Could not load skills: {error}': 'ไม่สามารถโหลดทักษะได้: {error}',
54
54
  'Could not reach the daemon: {error}': 'ไม่สามารถติดต่อดีมอนได้: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'ไม่สามารถติดต่อเซิร์ฟเวอร์ได้ กำลังแสดงเฉพาะการเปลี่ยนแปลงในเครื่อง',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_TR = {
48
48
  'Copy': 'Kopyala',
49
49
  'Copy to clipboard': 'Panoya kopyala',
50
50
  'Could not load live models: {message}': 'Canlı modeller yüklenemedi: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'API anahtarı yok — bağlantı testi için bu tarayıcıdan anahtar gerekiyor.',
52
- 'No API key — model discovery needs the key from this browser.': 'API anahtarı yok — model keşfi için bu tarayıcıdan anahtar gerekiyor.',
51
+ 'No API key saved. Save one to test the connection.': 'Kayıtlı API anahtarı yok. Bağlantıyı test etmek için bir anahtar kaydedin.',
52
+ 'No API key saved. Save one to load models.': 'Kayıtlı API anahtarı yok. Modelleri yüklemek için bir anahtar kaydedin.',
53
53
  'Could not load skills: {error}': 'Beceriler yüklenemedi: {error}',
54
54
  'Could not reach the daemon: {error}': 'Arka plan sürecine ulaşılamadı: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Sunucuya ulaşılamadı. Yalnızca yerel değişiklikler gösteriliyor.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_UK = {
48
48
  'Copy': 'Копіювати',
49
49
  'Copy to clipboard': 'Копіювати в буфер обміну',
50
50
  'Could not load live models: {message}': 'Не вдалося завантажити актуальні моделі: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'Немає API-ключа — для перевірки підключення потрібен ключ із цього браузера.',
52
- 'No API key — model discovery needs the key from this browser.': 'Немає API-ключа — для пошуку моделей потрібен ключ із цього браузера.',
51
+ 'No API key saved. Save one to test the connection.': 'API-ключ не збережено. Збережіть ключ, щоб перевірити підключення.',
52
+ 'No API key saved. Save one to load models.': 'API-ключ не збережено. Збережіть ключ, щоб завантажити моделі.',
53
53
  'Could not load skills: {error}': 'Не вдалося завантажити навички: {error}',
54
54
  'Could not reach the daemon: {error}': 'Не вдалося з\'єднатися з демоном: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'Не вдалося з\'єднатися з сервером. Показано лише локальні зміни.',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_UR = {
48
48
  'Copy': 'کاپی کریں',
49
49
  'Copy to clipboard': 'کلپ بورڈ پر کاپی کریں',
50
50
  'Could not load live models: {message}': 'لائیو ماڈلز لوڈ نہیں ہو سکے: {message}',
51
- 'No API key — connection test needs the key from this browser.': 'کوئی API کلید نہیں — کنکشن ٹیسٹ کے لیے اسی براؤزر سے کلید درکار ہے۔',
52
- 'No API key — model discovery needs the key from this browser.': 'کوئی API کلید نہیں — ماڈلز کی دریافت کے لیے اسی براؤزر سے کلید درکار ہے۔',
51
+ 'No API key saved. Save one to test the connection.': 'کوئی API کلید محفوظ نہیں ہے۔ کنکشن ٹیسٹ کرنے کے لیے ایک کلید محفوظ کریں۔',
52
+ 'No API key saved. Save one to load models.': 'کوئی API کلید محفوظ نہیں ہے۔ ماڈلز لوڈ کرنے کے لیے ایک کلید محفوظ کریں۔',
53
53
  'Could not load skills: {error}': 'اسکلز لوڈ نہیں ہو سکیں: {error}',
54
54
  'Could not reach the daemon: {error}': 'ڈیمن تک رسائی نہیں ہو سکی: {error}',
55
55
  'Could not reach the server. Showing local changes only.': 'سرور تک رسائی نہیں ہو سکی۔ صرف مقامی تبدیلیاں دکھائی جا رہی ہیں۔',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_ZH_CN = {
48
48
  'Copy': '复制',
49
49
  'Copy to clipboard': '复制到剪贴板',
50
50
  'Could not load live models: {message}': '无法加载实时模型列表:{message}',
51
- 'No API key — connection test needs the key from this browser.': '没有 API 密钥——连接测试需要来自此浏览器的密钥。',
52
- 'No API key — model discovery needs the key from this browser.': '没有 API 密钥——模型发现需要来自此浏览器的密钥。',
51
+ 'No API key saved. Save one to test the connection.': '未保存 API 密钥。请先保存密钥再测试连接。',
52
+ 'No API key saved. Save one to load models.': '未保存 API 密钥。请先保存密钥再加载模型。',
53
53
  'Could not load skills: {error}': '无法加载技能:{error}',
54
54
  'Could not reach the daemon: {error}': '无法连接到守护进程:{error}',
55
55
  'Could not reach the server. Showing local changes only.': '无法连接到服务器,仅显示本地更改。',
@@ -48,8 +48,8 @@ export const SETTINGS_DIALOG_ZH_TW = {
48
48
  'Copy': '複製',
49
49
  'Copy to clipboard': '複製到剪貼簿',
50
50
  'Could not load live models: {message}': '無法載入即時模型清單:{message}',
51
- 'No API key — connection test needs the key from this browser.': '沒有 API 金鑰——連線測試需要來自此瀏覽器的金鑰。',
52
- 'No API key — model discovery needs the key from this browser.': '沒有 API 金鑰——模型探索需要來自此瀏覽器的金鑰。',
51
+ 'No API key saved. Save one to test the connection.': '尚未儲存 API 金鑰。請先儲存金鑰再測試連線。',
52
+ 'No API key saved. Save one to load models.': '尚未儲存 API 金鑰。請先儲存金鑰再載入模型。',
53
53
  'Could not load skills: {error}': '無法載入技能:{error}',
54
54
  'Could not reach the daemon: {error}': '無法連上背景程序:{error}',
55
55
  'Could not reach the server. Showing local changes only.': '無法連上伺服器,僅顯示本機變更。',
@@ -13,6 +13,16 @@ export interface CheckboxProps {
13
13
  */
14
14
  readonly required?: boolean;
15
15
  readonly disabled?: boolean;
16
+ /**
17
+ * One extra `data-*` attribute on the `<input>`, escaped like every other value. For a caller
18
+ * that needs to look the box up by something other than its DOM `name` — e.g. the confirmation
19
+ * surface's per-choice ids, which are caller data and may contain characters `fieldElementId`'s
20
+ * `name` validation disallows.
21
+ */
22
+ readonly dataAttribute?: {
23
+ readonly name: string;
24
+ readonly value: string;
25
+ };
16
26
  }
17
27
  /**
18
28
  * Renders one boolean field.
@@ -16,10 +16,14 @@ import { fieldDescribedBy, fieldElementId, renderFieldLabel } from './document.j
16
16
  */
17
17
  export function renderCheckbox(props) {
18
18
  const id = fieldElementId(props.name);
19
+ const dataAttribute = props.dataAttribute === undefined
20
+ ? ''
21
+ : ` ${escapeHtml(props.dataAttribute.name)}="${escapeHtml(props.dataAttribute.value)}"`;
19
22
  const attributes = ` id="${escapeHtml(id)}" name="${escapeHtml(props.name)}"` +
20
23
  (props.value === true ? ' checked' : '') +
21
24
  (props.required === true ? ' required' : '') +
22
25
  (props.disabled === true ? ' disabled' : '') +
26
+ dataAttribute +
23
27
  fieldDescribedBy(props);
24
28
  return `<div class="mcpui-field mcpui-field-inline">\n<input class="mcpui-checkbox" type="checkbox"${attributes}>\n<span>${renderFieldLabel(props)}</span>\n</div>`;
25
29
  }
@@ -38,11 +38,37 @@ export interface ConfirmationToolAction {
38
38
  /** Passed verbatim as the tool's `arguments`. The only safe home for a confirmation token. */
39
39
  readonly params: Readonly<Record<string, unknown>>;
40
40
  }
41
+ /** One row of an optional per-item checkbox list — see {@link ConfirmationSurfaceSpec.choices}. */
42
+ export interface ConfirmationChoice {
43
+ /**
44
+ * The value reported back when this box is ticked. Caller data, not a DOM name: it may contain
45
+ * any character, because it never becomes an HTML `name`/`id` (those are `choice-<index>` in the
46
+ * DOM; see `renderChoices`) — only a `data-mcpui-choice` attribute value, which any string escapes
47
+ * into safely.
48
+ */
49
+ readonly id: string;
50
+ readonly label: string;
51
+ readonly hint?: string;
52
+ }
41
53
  export interface ConfirmationSurfaceSpec {
42
54
  readonly title: string;
43
55
  readonly description?: string;
44
56
  /** The facts being agreed about. A dialog that says "delete this?" without naming *this* is not consent. */
45
57
  readonly details?: readonly SurfaceDetail[];
58
+ /**
59
+ * Optional per-row checkboxes, rendered unchecked between the details and the warning. Ticking one
60
+ * never confirms anything by itself — the same property the module doc opens with, extended to a
61
+ * second input: a tick reaches a tool call ONLY by riding along on confirm's own trusted,
62
+ * past-dwell click, merged into {@link ConfirmationToolAction.params} under {@link choicesParam}
63
+ * at the moment of that click and never before. With no `choices`, the rendered document and the
64
+ * params confirm posts are byte-identical to a spec written before this field existed.
65
+ */
66
+ readonly choices?: readonly ConfirmationChoice[];
67
+ /**
68
+ * The params key the ticked ids are posted under, merged into (never replacing) `confirm.params`.
69
+ * Defaults to `"overwrite"`.
70
+ */
71
+ readonly choicesParam?: string;
46
72
  /** A callout above the buttons — the consequence that is not obvious from the details alone. */
47
73
  readonly warning?: string;
48
74
  /** Styles the affirmative button as destructive. Affects presentation only; it changes no behavior. */
@@ -30,6 +30,7 @@
30
30
  import { createUIResource } from '../resource.js';
31
31
  import { escapeHtml, escapeJsValue } from '../escape.js';
32
32
  import { DEFAULT_SURFACE_STATUS_TEXT, SURFACE_SCRIPT_PRELUDE, renderActions, renderDetailList, renderStatusRegion, renderSurfaceDocument, renderSurfaceHeader, } from './document.js';
33
+ import { renderCheckbox } from './checkbox.js';
33
34
  /**
34
35
  * How long the dialog must have been visible before a confirm click counts, in ms. A click sooner
35
36
  * than a person could have read the dialog is ignored — the same dwell browsers put on permission
@@ -42,6 +43,38 @@ const DEFAULT_APP = { appName: 'jini-mcp-ui-confirmation', appVersion: '1' };
42
43
  function isToolAction(action) {
43
44
  return action !== undefined && 'toolName' in action;
44
45
  }
46
+ /**
47
+ * Renders the optional choice checkboxes, one unchecked box per {@link ConfirmationChoice}.
48
+ *
49
+ * Named `choice-<index>` in the DOM — never by `choice.id`, which is caller data and may contain
50
+ * characters `fieldElementId`'s `name` validation rejects — with the real id carried on the
51
+ * `data-mcpui-choice` attribute instead, which the script reads back on change.
52
+ *
53
+ * @returns `''` for an empty list, matching every other optional fragment in this document.
54
+ */
55
+ function renderChoices(choices) {
56
+ if (choices.length === 0)
57
+ return '';
58
+ // Ticked state is keyed by id, so two boxes sharing one would tick and report as one.
59
+ const seen = new Set();
60
+ for (const choice of choices) {
61
+ if (seen.has(choice.id)) {
62
+ throw new Error(`Confirmation choices must have unique ids; ${JSON.stringify(choice.id)} appears more than once.`);
63
+ }
64
+ seen.add(choice.id);
65
+ }
66
+ const boxes = choices
67
+ .map((choice, index) => renderCheckbox({
68
+ name: `choice-${index}`,
69
+ label: choice.label,
70
+ ...(choice.hint === undefined ? {} : { hint: choice.hint }),
71
+ dataAttribute: { name: 'data-mcpui-choice', value: choice.id },
72
+ }))
73
+ .join('\n');
74
+ // Reuses form.ts's `.mcpui-fields` spacing rather than inventing a second stylesheet rule for the
75
+ // same "stack of controls" layout.
76
+ return `<fieldset class="mcpui-fields">\n${boxes}\n</fieldset>`;
77
+ }
45
78
  /**
46
79
  * Renders the confirmation dialog as a complete, self-contained HTML document.
47
80
  *
@@ -67,11 +100,18 @@ function confirmationActions(spec) {
67
100
  }
68
101
  export function renderConfirmationDocument(spec) {
69
102
  const text = { ...DEFAULT_SURFACE_STATUS_TEXT, ...spec.text };
103
+ const choicesParam = spec.choicesParam ?? 'overwrite';
104
+ // The ticked ids are merged into confirm.params at click time; a key already there (the token,
105
+ // say) would be silently replaced by an array.
106
+ if ((spec.choices ?? []).length > 0 && Object.prototype.hasOwnProperty.call(spec.confirm.params, choicesParam)) {
107
+ throw new Error(`choicesParam ${JSON.stringify(choicesParam)} collides with a key already in confirm.params.`);
108
+ }
70
109
  const actions = confirmationActions(spec);
71
110
  const warning = spec.warning === undefined ? '' : `<p class="mcpui-warning">${escapeHtml(spec.warning)}</p>`;
72
111
  const bodyHtml = [
73
112
  renderSurfaceHeader(spec.description === undefined ? { title: spec.title } : { title: spec.title, description: spec.description }),
74
113
  renderDetailList(spec.details ?? []),
114
+ renderChoices(spec.choices ?? []),
75
115
  warning,
76
116
  // Confirm starts disabled; the script enables it once the dwell has run out.
77
117
  renderActions(actions.map((action) => (action.id === 'confirm' ? { ...action, disabled: true } : action))),
@@ -96,6 +136,7 @@ ${SURFACE_SCRIPT_PRELUDE}
96
136
  var PLAN = ${escapeJsValue(plan)};
97
137
  var TEXT = ${escapeJsValue(text)};
98
138
  var DWELL_MS = ${CONFIRM_DWELL_MS};
139
+ var CHOICES_PARAM = ${escapeJsValue(choicesParam)};
99
140
 
100
141
  // Monotonic where available: a wall clock set backwards would otherwise stretch the dwell.
101
142
  function now() {
@@ -141,6 +182,47 @@ ${SURFACE_SCRIPT_PRELUDE}
141
182
  actionButtons[i].addEventListener("click", onClick);
142
183
  }
143
184
 
185
+ // Ticked state, tracked ourselves rather than trusted from each input's own \`.checked\` at
186
+ // confirm-time -- the same "only a browser-attributed action counts" rule \`onClick\` applies to
187
+ // the buttons, extended to the one other interactive element this document can contain. Keyed by
188
+ // \`data-mcpui-choice\` (the caller's id), not DOM order, so a checkbox reordering upstream could
189
+ // never silently swap which id a tick reports.
190
+ var choiceInputs = Array.prototype.slice.call(document.querySelectorAll("[data-mcpui-choice]"));
191
+ var checkedIds = {};
192
+ for (var c = 0; c < choiceInputs.length; c++) {
193
+ choiceInputs[c].addEventListener("change", onChoiceChange);
194
+ }
195
+
196
+ function onChoiceChange(event) {
197
+ var id = event.currentTarget.getAttribute("data-mcpui-choice");
198
+ if (event.isTrusted !== true) {
199
+ // Put the box back to what we last recorded, so a script-driven toggle from anywhere in this
200
+ // document can never leave the visible box and the ids confirm would send disagreeing.
201
+ event.currentTarget.checked = checkedIds[id] === true;
202
+ return;
203
+ }
204
+ if (event.currentTarget.checked) checkedIds[id] = true;
205
+ else delete checkedIds[id];
206
+ }
207
+
208
+ // Frozen with the buttons while a call is in flight and for good once one settles the dialog, so
209
+ // the ticks on screen are always the ones that were sent.
210
+ function setChoicesDisabled(disabled) {
211
+ for (var k = 0; k < choiceInputs.length; k++) choiceInputs[k].disabled = disabled;
212
+ }
213
+
214
+ // DOM order, not \`for...in\` over checkedIds: object key order for arbitrary caller-supplied
215
+ // strings is not something to depend on, even where every engine we run on happens to preserve it.
216
+ function checkedChoiceIds() {
217
+ var ids = [];
218
+ for (var j = 0; j < choiceInputs.length; j++) {
219
+ var choiceId = choiceInputs[j].getAttribute("data-mcpui-choice");
220
+ // Both: a trusted tick recorded, and the box still showing it. Never send what isn't on screen.
221
+ if (checkedIds[choiceId] === true && choiceInputs[j].checked) ids.push(choiceId);
222
+ }
223
+ return ids;
224
+ }
225
+
144
226
  function onClick(event) {
145
227
  // Only a click the browser attributes to the user counts. element.click() and dispatchEvent
146
228
  // from any script in this document produce isTrusted === false.
@@ -151,15 +233,26 @@ ${SURFACE_SCRIPT_PRELUDE}
151
233
  // Cancel is exempt: backing out early is never the harm this guards against.
152
234
  if (action === "confirm" && !dwellDone()) return;
153
235
  locked = true;
236
+ setChoicesDisabled(true);
154
237
  if (step === null) {
155
238
  setBusy(true);
156
239
  setStatus(TEXT.dismissed, "dismissed");
157
240
  api.requestTeardown();
158
241
  return;
159
242
  }
243
+ // Choices ride only on confirm, and only when this document has any -- with none, \`params\` stays
244
+ // the exact \`step.params\` reference PLAN was built from, byte-identical to before this existed.
245
+ var params = step.params;
246
+ if (action === "confirm" && choiceInputs.length > 0) {
247
+ var merged = {};
248
+ var key;
249
+ for (key in step.params) if (Object.prototype.hasOwnProperty.call(step.params, key)) merged[key] = step.params[key];
250
+ merged[CHOICES_PARAM] = checkedChoiceIds();
251
+ params = merged;
252
+ }
160
253
  setBusy(true);
161
254
  setStatus(TEXT.working, "pending");
162
- api.callTool(step.toolName, step.params).then(function () {
255
+ api.callTool(step.toolName, params).then(function () {
163
256
  setStatus(TEXT.done, "done");
164
257
  api.requestTeardown();
165
258
  }, function (error) {
@@ -167,6 +260,7 @@ ${SURFACE_SCRIPT_PRELUDE}
167
260
  // or cancel), unless the Host says this dialog is no longer pending -- see reportCallFailure.
168
261
  if (!reportCallFailure(error)) return;
169
262
  locked = false;
263
+ setChoicesDisabled(false);
170
264
  // reportCallFailure re-enabled every button; confirm still waits out an unfinished dwell.
171
265
  syncConfirm();
172
266
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/ui",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "description": "Generic, product-neutral React UI primitives and feature domains. Framework-free types, decision rules, catalogs, and host port contracts live behind ./core (no React, no DOM). The Excalidraw and Lexical editors live behind ./sketch-editor and ./lexical-rich-text-editor; the GrapesJS-backed inline HTML editor lives behind ./html-editor.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -107,9 +107,9 @@
107
107
  "shiki": "^1.24.4",
108
108
  "tailwind-merge": "^2.6.0",
109
109
  "zod": "^3.25.76",
110
- "@jini-ai/agentic": "0.3.6",
111
110
  "@jini-ai/platform": "0.3.0",
112
- "@jini-ai/protocol": "0.3.0"
111
+ "@jini-ai/protocol": "0.3.0",
112
+ "@jini-ai/agentic": "0.3.7"
113
113
  },
114
114
  "devDependencies": {
115
115
  "@excalidraw/excalidraw": "0.18.1",