@agent-native/core 0.161.12 → 0.161.14
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/actions/clear-selected-dashboard-object.ts +71 -0
- package/corpus/templates/analytics/actions/view-screen.ts +68 -4
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +41 -66
- package/corpus/templates/analytics/app/lib/selected-object.ts +53 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +21 -0
- package/corpus/templates/analytics/changelog/2026-08-18-ask-no-stale-dashboard-context.md +6 -0
- package/corpus/templates/calendar/app/root.tsx +12 -4
- package/corpus/templates/calendar/changelog/2026-08-18-calendar-stays-responsive-in-the-desktop-app-without-focus-t.md +6 -0
- package/corpus/templates/clips/app/components/library/recording-card.tsx +19 -3
- package/corpus/templates/clips/changelog/2026-08-18-deleting-a-recording-no-longer-freezes-clips.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +9 -10
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +4 -3
- package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +26 -0
- package/corpus/templates/dispatch/app/chat-first-pages.ts +40 -40
- package/corpus/templates/dispatch/app/i18n-data.ts +5 -5
- package/corpus/templates/factory/AGENTS.md +30 -29
- package/dist/action.js +49 -0
- package/dist/client/AssistantChat.js +1 -0
- package/dist/client/chat-first/app-open-actions.js +1 -1
- package/dist/client/chat-first/copy.js +2 -2
- package/dist/client/mcp-apps/McpAppRenderer.js +7 -2
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/mcp/embed-app.js +71 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/styles/agent-conversation.css +25 -4
- package/package.json +1 -1
|
@@ -8,8 +8,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
8
8
|
searchAppsPlaceholder: "依名稱或描述搜尋",
|
|
9
9
|
clearAppSearch: "清除搜尋",
|
|
10
10
|
noAppsMatch: "沒有符合搜尋條件的應用程式",
|
|
11
|
-
pinApp: "
|
|
12
|
-
unpinApp: "
|
|
11
|
+
pinApp: "釘選此應用程式",
|
|
12
|
+
unpinApp: "取消釘選此應用程式",
|
|
13
13
|
appPinSaveFailed: "無法儲存應用程式釘選。",
|
|
14
14
|
appPinSavedLocally: "應用程式釘選只儲存在此裝置上。",
|
|
15
15
|
chatFirstCreateWorkspaceApp: "建立工作區應用程式",
|
|
@@ -18,8 +18,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
18
18
|
chatFirstNoWorkspaceApps: "尚無工作區應用程式。",
|
|
19
19
|
chatFirstCreateApp: "建立應用程式",
|
|
20
20
|
chatFirstRetry: "重試",
|
|
21
|
-
chatFirstUnpinApp: "
|
|
22
|
-
chatFirstPinApp: "
|
|
21
|
+
chatFirstUnpinApp: "取消釘選此應用程式",
|
|
22
|
+
chatFirstPinApp: "釘選此應用程式",
|
|
23
23
|
chatFirstRemovePinned: "從釘選應用程式移除",
|
|
24
24
|
chatFirstPinTop: "將應用程式釘選至頂端",
|
|
25
25
|
chatFirstOpenSideSurfaces: "開啟側邊面板",
|
|
@@ -85,8 +85,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
85
85
|
searchAppsPlaceholder: "按名称或描述搜索",
|
|
86
86
|
clearAppSearch: "清除搜索",
|
|
87
87
|
noAppsMatch: "没有匹配搜索的应用",
|
|
88
|
-
pinApp: "
|
|
89
|
-
unpinApp: "
|
|
88
|
+
pinApp: "固定此应用",
|
|
89
|
+
unpinApp: "取消固定此应用",
|
|
90
90
|
appPinSaveFailed: "无法保存应用固定设置。",
|
|
91
91
|
appPinSavedLocally: "应用固定设置仅保存在此设备上。",
|
|
92
92
|
chatFirstCreateWorkspaceApp: "创建工作区应用",
|
|
@@ -95,8 +95,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
95
95
|
chatFirstNoWorkspaceApps: "尚无工作区应用。",
|
|
96
96
|
chatFirstCreateApp: "创建应用",
|
|
97
97
|
chatFirstRetry: "重试",
|
|
98
|
-
chatFirstUnpinApp: "
|
|
99
|
-
chatFirstPinApp: "
|
|
98
|
+
chatFirstUnpinApp: "取消固定此应用",
|
|
99
|
+
chatFirstPinApp: "固定此应用",
|
|
100
100
|
chatFirstRemovePinned: "从固定应用中移除",
|
|
101
101
|
chatFirstPinTop: "固定应用到顶部",
|
|
102
102
|
chatFirstOpenSideSurfaces: "打开侧边面板",
|
|
@@ -162,8 +162,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
162
162
|
searchAppsPlaceholder: "Buscar por nombre o descripción",
|
|
163
163
|
clearAppSearch: "Borrar búsqueda",
|
|
164
164
|
noAppsMatch: "Ninguna app coincide con tu búsqueda",
|
|
165
|
-
pinApp: "Fijar
|
|
166
|
-
unpinApp: "Desfijar
|
|
165
|
+
pinApp: "Fijar esta app",
|
|
166
|
+
unpinApp: "Desfijar esta app",
|
|
167
167
|
appPinSaveFailed: "No se pudieron guardar las apps fijadas.",
|
|
168
168
|
appPinSavedLocally:
|
|
169
169
|
"Las apps fijadas solo se guardan en este dispositivo.",
|
|
@@ -174,8 +174,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
174
174
|
chatFirstNoWorkspaceApps: "Aún no hay apps del espacio de trabajo.",
|
|
175
175
|
chatFirstCreateApp: "Crear app",
|
|
176
176
|
chatFirstRetry: "Reintentar",
|
|
177
|
-
chatFirstUnpinApp: "Quitar fijación a
|
|
178
|
-
chatFirstPinApp: "Fijar
|
|
177
|
+
chatFirstUnpinApp: "Quitar fijación a esta app",
|
|
178
|
+
chatFirstPinApp: "Fijar esta app",
|
|
179
179
|
chatFirstRemovePinned: "Quitar de las apps fijadas",
|
|
180
180
|
chatFirstPinTop: "Fijar app arriba",
|
|
181
181
|
chatFirstOpenSideSurfaces: "Abrir paneles laterales",
|
|
@@ -248,8 +248,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
248
248
|
searchAppsPlaceholder: "Rechercher par nom ou description",
|
|
249
249
|
clearAppSearch: "Effacer la recherche",
|
|
250
250
|
noAppsMatch: "Aucune application ne correspond à votre recherche",
|
|
251
|
-
pinApp: "Épingler
|
|
252
|
-
unpinApp: "Désépingler
|
|
251
|
+
pinApp: "Épingler cette application",
|
|
252
|
+
unpinApp: "Désépingler cette application",
|
|
253
253
|
appPinSaveFailed: "Impossible d’enregistrer les applications épinglées.",
|
|
254
254
|
appPinSavedLocally:
|
|
255
255
|
"Les applications épinglées sont enregistrées uniquement sur cet appareil.",
|
|
@@ -261,8 +261,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
261
261
|
"Aucune application d’espace de travail pour le moment.",
|
|
262
262
|
chatFirstCreateApp: "Créer une application",
|
|
263
263
|
chatFirstRetry: "Réessayer",
|
|
264
|
-
chatFirstUnpinApp: "Désépingler
|
|
265
|
-
chatFirstPinApp: "Épingler
|
|
264
|
+
chatFirstUnpinApp: "Désépingler cette application",
|
|
265
|
+
chatFirstPinApp: "Épingler cette application",
|
|
266
266
|
chatFirstRemovePinned: "Retirer des applications épinglées",
|
|
267
267
|
chatFirstPinTop: "Épingler l’application en haut",
|
|
268
268
|
chatFirstOpenSideSurfaces: "Ouvrir les panneaux latéraux",
|
|
@@ -336,8 +336,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
336
336
|
searchAppsPlaceholder: "Nach Name oder Beschreibung suchen",
|
|
337
337
|
clearAppSearch: "Suche löschen",
|
|
338
338
|
noAppsMatch: "Keine Apps entsprechen deiner Suche",
|
|
339
|
-
pinApp: "
|
|
340
|
-
unpinApp: "
|
|
339
|
+
pinApp: "Diese App anheften",
|
|
340
|
+
unpinApp: "Diese App loslösen",
|
|
341
341
|
appPinSaveFailed: "App-Anheftungen konnten nicht gespeichert werden.",
|
|
342
342
|
appPinSavedLocally:
|
|
343
343
|
"App-Anheftungen werden nur auf diesem Gerät gespeichert.",
|
|
@@ -348,8 +348,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
348
348
|
chatFirstNoWorkspaceApps: "Noch keine Arbeitsbereich-Apps.",
|
|
349
349
|
chatFirstCreateApp: "App erstellen",
|
|
350
350
|
chatFirstRetry: "Erneut versuchen",
|
|
351
|
-
chatFirstUnpinApp: "
|
|
352
|
-
chatFirstPinApp: "
|
|
351
|
+
chatFirstUnpinApp: "Diese App loslösen",
|
|
352
|
+
chatFirstPinApp: "Diese App anheften",
|
|
353
353
|
chatFirstRemovePinned: "Aus angehefteten Apps entfernen",
|
|
354
354
|
chatFirstPinTop: "App oben anheften",
|
|
355
355
|
chatFirstOpenSideSurfaces: "Seitenflächen öffnen",
|
|
@@ -423,8 +423,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
423
423
|
searchAppsPlaceholder: "名前または説明で検索",
|
|
424
424
|
clearAppSearch: "検索をクリア",
|
|
425
425
|
noAppsMatch: "検索に一致するアプリはありません",
|
|
426
|
-
pinApp: "
|
|
427
|
-
unpinApp: "
|
|
426
|
+
pinApp: "このアプリを固定",
|
|
427
|
+
unpinApp: "このアプリの固定を解除",
|
|
428
428
|
appPinSaveFailed: "アプリの固定を保存できませんでした。",
|
|
429
429
|
appPinSavedLocally: "アプリの固定はこのデバイスにのみ保存されます。",
|
|
430
430
|
chatFirstCreateWorkspaceApp: "ワークスペースアプリを作成",
|
|
@@ -433,8 +433,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
433
433
|
chatFirstNoWorkspaceApps: "ワークスペースアプリはまだありません。",
|
|
434
434
|
chatFirstCreateApp: "アプリを作成",
|
|
435
435
|
chatFirstRetry: "再試行",
|
|
436
|
-
chatFirstUnpinApp: "
|
|
437
|
-
chatFirstPinApp: "
|
|
436
|
+
chatFirstUnpinApp: "このアプリの固定を解除",
|
|
437
|
+
chatFirstPinApp: "このアプリを固定",
|
|
438
438
|
chatFirstRemovePinned: "固定アプリから削除",
|
|
439
439
|
chatFirstPinTop: "アプリを上部に固定",
|
|
440
440
|
chatFirstOpenSideSurfaces: "サイドサーフェスを開く",
|
|
@@ -508,8 +508,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
508
508
|
searchAppsPlaceholder: "이름 또는 설명으로 검색",
|
|
509
509
|
clearAppSearch: "검색 지우기",
|
|
510
510
|
noAppsMatch: "검색 결과가 없습니다",
|
|
511
|
-
pinApp: "
|
|
512
|
-
unpinApp: "
|
|
511
|
+
pinApp: "이 앱 고정",
|
|
512
|
+
unpinApp: "이 앱 고정 해제",
|
|
513
513
|
appPinSaveFailed: "앱 고정을 저장하지 못했습니다.",
|
|
514
514
|
appPinSavedLocally: "앱 고정은 이 기기에만 저장됩니다.",
|
|
515
515
|
chatFirstCreateWorkspaceApp: "워크스페이스 앱 만들기",
|
|
@@ -518,8 +518,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
518
518
|
chatFirstNoWorkspaceApps: "아직 워크스페이스 앱이 없습니다.",
|
|
519
519
|
chatFirstCreateApp: "앱 만들기",
|
|
520
520
|
chatFirstRetry: "다시 시도",
|
|
521
|
-
chatFirstUnpinApp: "
|
|
522
|
-
chatFirstPinApp: "
|
|
521
|
+
chatFirstUnpinApp: "이 앱 고정 해제",
|
|
522
|
+
chatFirstPinApp: "이 앱 고정",
|
|
523
523
|
chatFirstRemovePinned: "고정된 앱에서 제거",
|
|
524
524
|
chatFirstPinTop: "앱을 맨 위에 고정",
|
|
525
525
|
chatFirstOpenSideSurfaces: "사이드 표면 열기",
|
|
@@ -589,8 +589,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
589
589
|
searchAppsPlaceholder: "Pesquisar por nome ou descrição",
|
|
590
590
|
clearAppSearch: "Limpar pesquisa",
|
|
591
591
|
noAppsMatch: "Nenhum app corresponde à sua pesquisa",
|
|
592
|
-
pinApp: "Fixar
|
|
593
|
-
unpinApp: "Desafixar
|
|
592
|
+
pinApp: "Fixar este app",
|
|
593
|
+
unpinApp: "Desafixar este app",
|
|
594
594
|
appPinSaveFailed: "Não foi possível salvar os apps fixados.",
|
|
595
595
|
appPinSavedLocally:
|
|
596
596
|
"Os apps fixados são salvos somente neste dispositivo.",
|
|
@@ -601,8 +601,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
601
601
|
chatFirstNoWorkspaceApps: "Ainda não há apps do espaço de trabalho.",
|
|
602
602
|
chatFirstCreateApp: "Criar app",
|
|
603
603
|
chatFirstRetry: "Tentar novamente",
|
|
604
|
-
chatFirstUnpinApp: "Desafixar
|
|
605
|
-
chatFirstPinApp: "Fixar
|
|
604
|
+
chatFirstUnpinApp: "Desafixar este app",
|
|
605
|
+
chatFirstPinApp: "Fixar este app",
|
|
606
606
|
chatFirstRemovePinned: "Remover dos apps fixados",
|
|
607
607
|
chatFirstPinTop: "Fixar app no topo",
|
|
608
608
|
chatFirstOpenSideSurfaces: "Abrir superfícies laterais",
|
|
@@ -675,8 +675,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
675
675
|
searchAppsPlaceholder: "नाम या विवरण से खोजें",
|
|
676
676
|
clearAppSearch: "खोज साफ़ करें",
|
|
677
677
|
noAppsMatch: "आपकी खोज से कोई ऐप मेल नहीं खाता",
|
|
678
|
-
pinApp: "
|
|
679
|
-
unpinApp: "
|
|
678
|
+
pinApp: "इस ऐप को पिन करें",
|
|
679
|
+
unpinApp: "इस ऐप से पिन हटाएं",
|
|
680
680
|
appPinSaveFailed: "ऐप पिन सहेजे नहीं जा सके।",
|
|
681
681
|
appPinSavedLocally: "ऐप पिन केवल इस डिवाइस पर सहेजे गए हैं।",
|
|
682
682
|
chatFirstCreateWorkspaceApp: "वर्कस्पेस ऐप बनाएँ",
|
|
@@ -685,8 +685,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
685
685
|
chatFirstNoWorkspaceApps: "अभी कोई वर्कस्पेस ऐप नहीं है।",
|
|
686
686
|
chatFirstCreateApp: "ऐप बनाएँ",
|
|
687
687
|
chatFirstRetry: "पुनः प्रयास करें",
|
|
688
|
-
chatFirstUnpinApp: "
|
|
689
|
-
chatFirstPinApp: "
|
|
688
|
+
chatFirstUnpinApp: "इस ऐप से पिन हटाएं",
|
|
689
|
+
chatFirstPinApp: "इस ऐप को पिन करें",
|
|
690
690
|
chatFirstRemovePinned: "पिन किए गए ऐप्स से हटाएँ",
|
|
691
691
|
chatFirstPinTop: "ऐप को सबसे ऊपर पिन करें",
|
|
692
692
|
chatFirstOpenSideSurfaces: "साइड पैनल खोलें",
|
|
@@ -754,8 +754,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
754
754
|
searchAppsPlaceholder: "البحث بالاسم أو الوصف",
|
|
755
755
|
clearAppSearch: "مسح البحث",
|
|
756
756
|
noAppsMatch: "لا توجد تطبيقات تطابق بحثك",
|
|
757
|
-
pinApp: "تثبيت
|
|
758
|
-
unpinApp: "إلغاء تثبيت
|
|
757
|
+
pinApp: "تثبيت هذا التطبيق",
|
|
758
|
+
unpinApp: "إلغاء تثبيت هذا التطبيق",
|
|
759
759
|
appPinSaveFailed: "تعذر حفظ تثبيتات التطبيقات.",
|
|
760
760
|
appPinSavedLocally: "تُحفظ تثبيتات التطبيقات على هذا الجهاز فقط.",
|
|
761
761
|
chatFirstCreateWorkspaceApp: "إنشاء تطبيق مساحة عمل",
|
|
@@ -764,8 +764,8 @@ export const chatFirstPageTranslations: Record<string, ChatFirstPageMessages> =
|
|
|
764
764
|
chatFirstNoWorkspaceApps: "لا توجد تطبيقات لمساحة العمل بعد.",
|
|
765
765
|
chatFirstCreateApp: "إنشاء تطبيق",
|
|
766
766
|
chatFirstRetry: "إعادة المحاولة",
|
|
767
|
-
chatFirstUnpinApp: "إلغاء تثبيت
|
|
768
|
-
chatFirstPinApp: "تثبيت
|
|
767
|
+
chatFirstUnpinApp: "إلغاء تثبيت هذا التطبيق",
|
|
768
|
+
chatFirstPinApp: "تثبيت هذا التطبيق",
|
|
769
769
|
chatFirstRemovePinned: "إزالة من التطبيقات المثبتة",
|
|
770
770
|
chatFirstPinTop: "تثبيت التطبيق في الأعلى",
|
|
771
771
|
chatFirstOpenSideSurfaces: "فتح الأسطح الجانبية",
|
|
@@ -432,11 +432,11 @@ const enUS = {
|
|
|
432
432
|
threadDebugSelectPrompt: "Select a failed run or thread to inspect.",
|
|
433
433
|
chatFirstWorkspaceApps: "Workspace apps",
|
|
434
434
|
searchApps: "Search apps",
|
|
435
|
-
searchAppsPlaceholder: "Search
|
|
435
|
+
searchAppsPlaceholder: "Search apps",
|
|
436
436
|
clearAppSearch: "Clear search",
|
|
437
437
|
noAppsMatch: "No apps match your search",
|
|
438
|
-
pinApp: "Pin
|
|
439
|
-
unpinApp: "Unpin
|
|
438
|
+
pinApp: "Pin this app",
|
|
439
|
+
unpinApp: "Unpin this app",
|
|
440
440
|
appPinSaveFailed: "App pins could not be saved.",
|
|
441
441
|
appPinSavedLocally: "App pins are saved on this device only.",
|
|
442
442
|
chatFirstCreateWorkspaceApp: "Create workspace app",
|
|
@@ -445,8 +445,8 @@ const enUS = {
|
|
|
445
445
|
chatFirstNoWorkspaceApps: "No workspace apps yet.",
|
|
446
446
|
chatFirstCreateApp: "Create app",
|
|
447
447
|
chatFirstRetry: "Retry",
|
|
448
|
-
chatFirstUnpinApp: "Unpin
|
|
449
|
-
chatFirstPinApp: "Pin
|
|
448
|
+
chatFirstUnpinApp: "Unpin this app",
|
|
449
|
+
chatFirstPinApp: "Pin this app",
|
|
450
450
|
chatFirstRemovePinned: "Remove from pinned apps",
|
|
451
451
|
chatFirstPinTop: "Pin app to the top",
|
|
452
452
|
chatFirstOpenSideSurfaces: "Open side surfaces",
|
|
@@ -22,11 +22,20 @@ decisions, feedback, agent runs, and provider audit records.
|
|
|
22
22
|
`reconciliation_required` state.
|
|
23
23
|
- Deduplicate by Factory item and rule/run identity, not provider comment ID.
|
|
24
24
|
- Use the generic Slack adapter: clear-bug automations add 👀 and tag
|
|
25
|
-
`@
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
and
|
|
29
|
-
|
|
25
|
+
`@builder.io`, ask Builder to run `/address-feedback`, and group repeated
|
|
26
|
+
reports into one Builder thread; GitHub/Sentry clear bugs use the Builder run
|
|
27
|
+
API. Clips, Design, and Content stay owner-managed outside autonomous
|
|
28
|
+
dispatch and PR governance.
|
|
29
|
+
- PR governance follows `review-prs`: verify current BuilderIO membership and
|
|
30
|
+
the complete diff/review/check evidence, never approve external or
|
|
31
|
+
unverified authors, and keep ultra-scary security, auth, tenant-isolation,
|
|
32
|
+
secrets, data-loss, execution, payment, and deployment risks manual. The
|
|
33
|
+
verified internal-author evidence does not waive ordinary failed or
|
|
34
|
+
unresolved checks or feedback; those gates remain required and their exact
|
|
35
|
+
states must stay visible. It never waives membership or the ultra-scary
|
|
36
|
+
gate.
|
|
37
|
+
Product/UX ownership still needs the verified owner, with the documented Sid
|
|
38
|
+
exception. Auto-merge also requires a verified Factory Builder run.
|
|
30
39
|
- Graph edits create immutable blueprint versions. AI proposes with `source=ai`;
|
|
31
40
|
a person reviews and publishes through the same action surface.
|
|
32
41
|
- Provider credentials belong to Dispatch/shared workspace integrations, never
|
|
@@ -35,47 +44,39 @@ decisions, feedback, agent runs, and provider audit records.
|
|
|
35
44
|
|
|
36
45
|
## Application state
|
|
37
46
|
|
|
38
|
-
- `navigation.view
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- `navigation.factoryAuditRunId`: selected automation run in the audit view when present.
|
|
43
|
-
- `navigation.factoryNodeId` / `navigation.factoryEdgeId`: selected graph item.
|
|
44
|
-
- A selected graph node or edge is part of `navigation` context. Read
|
|
45
|
-
`view-screen` before answering why a route exists or changing the selected
|
|
46
|
-
Factory.
|
|
47
|
-
- The `/agents` surface shows mounted agentic apps and reusable agent packs from
|
|
48
|
-
the same Dispatch SQL/action registry. Use `view-screen` there before
|
|
49
|
-
answering questions about the visible agent inventory.
|
|
47
|
+
- `navigation.view` is `factory` or `agents`; `factoryId`, `factoryTab`,
|
|
48
|
+
`factoryAuditRunId`, `factoryNodeId`, and `factoryEdgeId` hold the selected
|
|
49
|
+
Factory context. Read `view-screen` before explaining a route, changing the
|
|
50
|
+
selected Factory, or answering about the `/agents` inventory.
|
|
50
51
|
|
|
51
52
|
## Action contract
|
|
52
53
|
|
|
53
54
|
| Action | Purpose |
|
|
54
55
|
| --- | --- |
|
|
55
|
-
| `list-triage-items` / `get-triage-item` | Inspect queue
|
|
56
|
+
| `list-triage-items` / `get-triage-item` | Inspect bounded queue evidence; scheduled reviewers pass `needsReview: true`, `source`, and `limit`. |
|
|
56
57
|
| `poll-slack-channel` | Observe Slack history; never writes to Slack. |
|
|
57
58
|
| `get-slack-feedback-context` | Read the bounded full Slack thread before classification. |
|
|
58
|
-
| `poll-github-sources` / `poll-sentry-errors` | Observe bounded
|
|
59
|
+
| `poll-github-sources` / `poll-sentry-errors` | Observe bounded source queues. |
|
|
59
60
|
| `ingest-github-observation` | Store read-only PR evidence. |
|
|
60
|
-
| `list-triage-rules` / `save-triage-rule` | Tune
|
|
61
|
+
| `list-triage-rules` / `save-triage-rule` | Tune rules and guards. |
|
|
61
62
|
| `evaluate-triage-item` | Append a decision. |
|
|
62
63
|
| `record-triage-feedback` | Capture human correction for learning. |
|
|
63
64
|
| `approve-factory-item` | Explicitly authorize one bounded run. |
|
|
64
65
|
| `start-builder-for-item` | Govern clear-bug dispatch through Slack or Builder API. |
|
|
65
|
-
| `govern-agent-native-pull-request` | Apply
|
|
66
|
-
| `list-factory-automations` / `save-factory-automation` / `run-factory-automation` | Inspect or edit org-owned
|
|
66
|
+
| `govern-agent-native-pull-request` | Apply PR evidence and ownership gates. |
|
|
67
|
+
| `list-factory-automations` / `save-factory-automation` / `run-factory-automation` | Inspect or edit org-owned automations. |
|
|
67
68
|
| `list-factory-audit` | Inspect automation runs, evidence, decisions, and provider actions. |
|
|
68
69
|
| `get-factory-automation-health` | Inspect scheduler heartbeat and last error. |
|
|
69
|
-
| `suggest-factory-rules` | Mine feedback
|
|
70
|
+
| `suggest-factory-rules` | Mine feedback into proposals. |
|
|
70
71
|
| `reconcile-triage-run` | Persist callback/provider reconciliation. |
|
|
71
|
-
| `list-factories` / `get-factory-graph` | Inspect
|
|
72
|
+
| `list-factories` / `get-factory-graph` | Inspect definitions, versions, and metrics. |
|
|
72
73
|
| `save-factory-graph` | Create or version a complete visual graph; never starts provider work. |
|
|
73
74
|
| `list-factory-comments` / `add-factory-comment` | Read or attach comments to a canvas, node, or edge. |
|
|
74
|
-
| `provider-api-catalog` / `provider-api-docs` / `provider-api-request` |
|
|
75
|
-
| `list-workspace-apps` / `update-workspace-app-metadata` | Inventory and edit mounted
|
|
76
|
-
| `list-workspace-resources` / `create-workspace-resource` / `update-workspace-resource` | Manage shared
|
|
77
|
-
| `import-agent` / `import-agent-pack` / `list-agent-pack` | Import
|
|
78
|
-
| `start-workspace-app-creation` | Promote an agent and
|
|
75
|
+
| `provider-api-catalog` / `provider-api-docs` / `provider-api-request` | Use connected provider APIs with shared credentials; never request raw keys. |
|
|
76
|
+
| `list-workspace-apps` / `update-workspace-app-metadata` | Inventory and edit mounted apps. |
|
|
77
|
+
| `list-workspace-resources` / `create-workspace-resource` / `update-workspace-resource` | Manage shared agent resources. |
|
|
78
|
+
| `import-agent` / `import-agent-pack` / `list-agent-pack` | Import profiles or agent packs. |
|
|
79
|
+
| `start-workspace-app-creation` | Promote an agent and its pack into an app handoff. |
|
|
79
80
|
|
|
80
81
|
Rules start in shadow mode; hard guards always apply. Organization automations
|
|
81
82
|
execute stored prompts, and every external mutation needs a durable run,
|
package/dist/action.js
CHANGED
|
@@ -349,6 +349,50 @@ const SUBSCHEMA_MAP_KEYS = [
|
|
|
349
349
|
* `default`, `const`, `enum`, or `examples`, whose objects may legitimately
|
|
350
350
|
* contain a `propertyNames` data key that must be preserved.
|
|
351
351
|
*/
|
|
352
|
+
/**
|
|
353
|
+
* A schema position with no `type` — what Zod emits for `z.unknown()` /
|
|
354
|
+
* `z.any()` — is rejected by OpenAI with "schema must have a 'type' key",
|
|
355
|
+
* 400ing the whole request exactly like `oneOf` did. There are 137 such sites
|
|
356
|
+
* across the templates, so this has to be answered at the boundary rather than
|
|
357
|
+
* by retyping every action.
|
|
358
|
+
*
|
|
359
|
+
* Expressed as a union of concrete JSON types because that shape is already
|
|
360
|
+
* proven against the live validator: `setFilterDefault.value`, a
|
|
361
|
+
* `z.union([string, number, boolean, null])` sitting in the same tool schema,
|
|
362
|
+
* was never flagged while the typeless sibling next to it was. `true` for
|
|
363
|
+
* `additionalProperties` is a boolean, not a subschema, so it needs no type of
|
|
364
|
+
* its own; array items get one bounded level rather than recursing forever.
|
|
365
|
+
*/
|
|
366
|
+
const JSON_VALUE_BRANCHES = [
|
|
367
|
+
{ type: "string" },
|
|
368
|
+
{ type: "number" },
|
|
369
|
+
{ type: "boolean" },
|
|
370
|
+
{ type: "null" },
|
|
371
|
+
{ type: "object", additionalProperties: true },
|
|
372
|
+
{
|
|
373
|
+
type: "array",
|
|
374
|
+
items: {
|
|
375
|
+
anyOf: [
|
|
376
|
+
{ type: "string" },
|
|
377
|
+
{ type: "number" },
|
|
378
|
+
{ type: "boolean" },
|
|
379
|
+
{ type: "null" },
|
|
380
|
+
{ type: "object", additionalProperties: true },
|
|
381
|
+
],
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
];
|
|
385
|
+
/** Keywords that make a `type`-less schema meaningful on their own. */
|
|
386
|
+
const TYPE_SUBSTITUTE_KEYS = [
|
|
387
|
+
"type",
|
|
388
|
+
"anyOf",
|
|
389
|
+
"oneOf",
|
|
390
|
+
"allOf",
|
|
391
|
+
"enum",
|
|
392
|
+
"const",
|
|
393
|
+
"$ref",
|
|
394
|
+
"not",
|
|
395
|
+
];
|
|
352
396
|
function stripUnsupportedSchemaKeywords(node) {
|
|
353
397
|
if (!node || typeof node !== "object" || Array.isArray(node))
|
|
354
398
|
return node;
|
|
@@ -388,6 +432,11 @@ function stripUnsupportedSchemaKeywords(node) {
|
|
|
388
432
|
obj.anyOf = [...existing, ...obj.oneOf];
|
|
389
433
|
delete obj.oneOf;
|
|
390
434
|
}
|
|
435
|
+
// Last, so a node that only became typed above (oneOf -> anyOf) is not also
|
|
436
|
+
// given a redundant value union.
|
|
437
|
+
if (!TYPE_SUBSTITUTE_KEYS.some((key) => obj[key] !== undefined)) {
|
|
438
|
+
obj.anyOf = JSON_VALUE_BRANCHES.map((branch) => ({ ...branch }));
|
|
439
|
+
}
|
|
391
440
|
return node;
|
|
392
441
|
}
|
|
393
442
|
/**
|
|
@@ -2603,6 +2603,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2603
2603
|
// A restored tab can be reclassified as client-only after the thread list
|
|
2604
2604
|
// loads. Once that happens, there is no server row to restore, so show the
|
|
2605
2605
|
// empty composer instead of leaving the per-thread restore skeleton up.
|
|
2606
|
+
setThreadRestoreError(null);
|
|
2606
2607
|
setIsRestoring(false);
|
|
2607
2608
|
}, [isNewThread, threadId]);
|
|
2608
2609
|
// Restore messages from server on mount (when threadId is set). The
|
|
@@ -21,5 +21,5 @@ export function AppOpenActions({ name, href, target, rel, labels: labelOverrides
|
|
|
21
21
|
if (!canOpen && !hasMenu) {
|
|
22
22
|
return (_jsx(Button, { size: "sm", variant: "outline", disabled: true, children: labels.openApp }));
|
|
23
23
|
}
|
|
24
|
-
return (_jsxs("div", { className: cn("app-open-actions flex shrink-0 overflow-hidden rounded-md border border-border focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2", className), children: [_jsx(Button, { asChild: primaryUsesHref, size: "sm", variant: "outline", className: "app-open-actions__primary h-7 rounded-none border-0 border-e border-border px-0 pe-2 ps-3 text-xs", disabled: !canOpen, onClick: onOpen, type: primaryUsesHref ? undefined : "button", "aria-label": !primaryUsesHref ? `Open ${name}` : undefined, children: primaryUsesHref ? (_jsx("a", { href: href ?? undefined, target: target, rel: rel, children: labels.openApp })) : (_jsx("span", { children: labels.openApp })) }), hasMenu ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "app-open-actions__menu size-7 rounded-none border-0 p-0 text-xs", "aria-label": `Open options for ${name}`, children: _jsx(IconChevronDown, { size: 15 }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: APP_ACTION_MENU_CONTENT_CLASS, children: [onAddApp ? (_jsxs(DropdownMenuItem, { onSelect: onAddApp, children: [_jsx(IconPlus, { size: 14, "aria-hidden": "true" }), labels.addApp] })) : null, showInlineOption && href && onOpenInline ? (_jsxs(DropdownMenuItem, { onSelect: onOpenInline, children: [_jsx(IconAppWindow, { size: 14, "aria-hidden": "true" }), labels.openInline] })) : null, canOfferNewTab && href ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: href ?? undefined, target: "_blank", rel: "noreferrer", children: [_jsx(IconExternalLink, { size: 14, "aria-hidden": "true" }), labels.openInNewTab] }) })) : null, menuItems?.map((item) => (_jsxs(DropdownMenuItem, { onSelect: item.onSelect, children: [item.icon ? (_jsx("span", { "aria-hidden": "true", className: "shrink-0", children: item.icon })) : null, item.label] }, item.id)))] })] })) : null] }));
|
|
24
|
+
return (_jsxs("div", { className: cn("app-open-actions flex shrink-0 overflow-hidden rounded-md border border-border focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2", className), children: [_jsx(Button, { asChild: primaryUsesHref, size: "sm", variant: "outline", className: "app-open-actions__primary h-7 rounded-none border-0 border-e border-border px-0 pe-2 ps-3 text-xs", disabled: !canOpen, onClick: onOpen, type: primaryUsesHref ? undefined : "button", "aria-label": !primaryUsesHref ? `Open ${name}` : undefined, children: primaryUsesHref ? (_jsx("a", { href: href ?? undefined, target: target, rel: rel, children: labels.openApp })) : (_jsx("span", { children: labels.openApp })) }), hasMenu ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "app-open-actions__menu size-7 rounded-none border-0 p-0 text-xs", "aria-label": `Open options for ${name}`, children: _jsx(IconChevronDown, { size: 15 }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: cn(APP_ACTION_MENU_CONTENT_CLASS, "min-w-max"), children: [onAddApp ? (_jsxs(DropdownMenuItem, { onSelect: onAddApp, children: [_jsx(IconPlus, { size: 14, "aria-hidden": "true" }), labels.addApp] })) : null, showInlineOption && href && onOpenInline ? (_jsxs(DropdownMenuItem, { onSelect: onOpenInline, children: [_jsx(IconAppWindow, { size: 14, "aria-hidden": "true" }), labels.openInline] })) : null, canOfferNewTab && href ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs("a", { href: href ?? undefined, target: "_blank", rel: "noreferrer", children: [_jsx(IconExternalLink, { size: 14, "aria-hidden": "true" }), labels.openInNewTab] }) })) : null, menuItems?.map((item) => (_jsxs(DropdownMenuItem, { onSelect: item.onSelect, children: [item.icon ? (_jsx("span", { "aria-hidden": "true", className: "shrink-0", children: item.icon })) : null, item.label] }, item.id)))] })] })) : null] }));
|
|
25
25
|
}
|
|
@@ -12,8 +12,8 @@ const DEFAULT_COPY = {
|
|
|
12
12
|
createApp: "Create app",
|
|
13
13
|
retry: "Retry",
|
|
14
14
|
dismiss: "Dismiss",
|
|
15
|
-
unpinApp: "Unpin
|
|
16
|
-
pinApp: "Pin
|
|
15
|
+
unpinApp: "Unpin this app",
|
|
16
|
+
pinApp: "Pin this app",
|
|
17
17
|
removePinned: "Remove from pinned apps",
|
|
18
18
|
pinTop: "Pin app to the top",
|
|
19
19
|
moveUp: "Move up",
|
|
@@ -55,6 +55,11 @@ export function McpAppRenderer({ app, className }) {
|
|
|
55
55
|
setReady(true);
|
|
56
56
|
setError(null);
|
|
57
57
|
}, []);
|
|
58
|
+
const handleIframeError = useCallback(() => {
|
|
59
|
+
readyRef.current = false;
|
|
60
|
+
setReady(false);
|
|
61
|
+
setError("MCP App iframe failed to load.");
|
|
62
|
+
}, []);
|
|
58
63
|
const applyHeight = useCallback((desiredHeight) => {
|
|
59
64
|
if (typeof desiredHeight === "number" &&
|
|
60
65
|
Number.isFinite(desiredHeight) &&
|
|
@@ -228,9 +233,9 @@ export function McpAppRenderer({ app, className }) {
|
|
|
228
233
|
// new-but-equal `app` object reference does not tear down a live bridge.
|
|
229
234
|
}, [applyHeight, markReady, srcDoc]);
|
|
230
235
|
if (!resourceHtml) {
|
|
231
|
-
return (_jsxs("div", { className: cn("agent-mcp-app agent-mcp-app--error", className), children: [_jsx(IconAlertTriangle, { size: 15 }), _jsx("span", { children: "MCP App resource was not available." })] }));
|
|
236
|
+
return (_jsxs("div", { className: cn("agent-mcp-app agent-mcp-app--error", className), children: [_jsx(IconAlertTriangle, { size: 15 }), _jsx("span", { children: "MCP App resource was not available." }), externalOpenUrl && (_jsx("button", { type: "button", className: "agent-mcp-app__open", onClick: () => window.open(externalOpenUrl, "_blank", "noopener,noreferrer"), children: "Open in new tab" }))] }));
|
|
232
237
|
}
|
|
233
|
-
return (_jsxs("div", { className: cn("agent-mcp-app", uiMeta.prefersBorder === false && "agent-mcp-app--flush", className), children: [!ready && !error && (_jsxs("div", { className: "agent-mcp-app__loading", children: [_jsx(IconLoader2, { size: 14, className: "agent-conversation-spin" }), _jsx("span", { children: "Loading MCP App" })] })), error && (_jsxs("div", { className: "agent-mcp-app__error", children: [_jsx(IconAlertTriangle, { size: 15 }), _jsx("span", { children: error }), externalOpenUrl && (_jsx("button", { type: "button", className: "agent-mcp-app__open", onClick: () => window.open(externalOpenUrl, "_blank", "noopener,noreferrer"), children: "Open in new tab" }))] })), _jsx("iframe", { ref: iframeRef, title: app.tool?.title ?? app.originalToolName, srcDoc: srcDoc, sandbox: SANDBOX_FLAGS, allow: buildAllowAttribute(supportedPermissions), style: { height } })] }));
|
|
238
|
+
return (_jsxs("div", { className: cn("agent-mcp-app", uiMeta.prefersBorder === false && "agent-mcp-app--flush", className), children: [!ready && !error && (_jsxs("div", { className: "agent-mcp-app__loading", children: [_jsx(IconLoader2, { size: 14, className: "agent-conversation-spin" }), _jsx("span", { children: "Loading MCP App" })] })), error && (_jsx("div", { className: "agent-mcp-app__error", role: "alert", children: _jsxs("div", { className: "agent-mcp-app__error-box", children: [_jsx(IconAlertTriangle, { size: 15 }), _jsx("span", { children: error }), externalOpenUrl && (_jsx("button", { type: "button", className: "agent-mcp-app__open", onClick: () => window.open(externalOpenUrl, "_blank", "noopener,noreferrer"), children: "Open in new tab" }))] }) })), _jsx("iframe", { ref: iframeRef, title: app.tool?.title ?? app.originalToolName, srcDoc: srcDoc, sandbox: SANDBOX_FLAGS, allow: buildAllowAttribute(supportedPermissions), style: { height }, onError: handleIframeError })] }));
|
|
234
239
|
}
|
|
235
240
|
function messageTextFromMcpUiMessage(params) {
|
|
236
241
|
return textPartsFromMcpContent(params.content).join("\n\n").trim();
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/mcp/embed-app.js
CHANGED
|
@@ -47,6 +47,8 @@ export function embedApp(options = {}) {
|
|
|
47
47
|
iframe { display: block; width: 100%; height: var(--agent-native-viewport-height); border: 0; background: Canvas; }
|
|
48
48
|
.message { display: grid; place-items: center; min-height: var(--agent-native-viewport-height); padding: 18px; color: color-mix(in srgb, CanvasText 62%, Canvas); font-size: 13px; line-height: 1.45; text-align: center; }
|
|
49
49
|
.fallback { display: grid; align-content: center; justify-items: center; gap: 12px; min-height: var(--agent-native-viewport-height); padding: 24px; background: Canvas; color: CanvasText; text-align: center; }
|
|
50
|
+
.fallback-overlay { position: absolute; inset: 0; z-index: 2; display: grid; align-items: start; justify-items: end; padding: 12px; pointer-events: none; }
|
|
51
|
+
.fallback-overlay .fallback { width: min(100%, 560px); min-height: 0; border: 1px solid color-mix(in srgb, CanvasText 18%, Canvas); border-radius: 9px; background: color-mix(in srgb, Canvas 96%, transparent); box-shadow: 0 8px 24px color-mix(in srgb, CanvasText 16%, transparent); pointer-events: auto; }
|
|
50
52
|
.fallback-title { max-width: 440px; font-size: 14px; font-weight: 700; }
|
|
51
53
|
.fallback-copy { max-width: 520px; color: color-mix(in srgb, CanvasText 64%, Canvas); font-size: 13px; line-height: 1.45; }
|
|
52
54
|
.fallback-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }
|
|
@@ -1073,14 +1075,64 @@ export function embedApp(options = {}) {
|
|
|
1073
1075
|
} catch {}
|
|
1074
1076
|
}
|
|
1075
1077
|
|
|
1078
|
+
function clearFallbackOverlay() {
|
|
1079
|
+
stage.querySelector("[data-fallback-overlay]")?.remove();
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
function renderFallbackOverlay({ title, copyHtml, retryLabel, onRetry }) {
|
|
1083
|
+
if (!appFrame || appFrame.parentElement !== stage) return false;
|
|
1084
|
+
clearFallbackOverlay();
|
|
1085
|
+
const overlay = document.createElement("div");
|
|
1086
|
+
overlay.className = "fallback-overlay";
|
|
1087
|
+
overlay.dataset.fallbackOverlay = "1";
|
|
1088
|
+
overlay.innerHTML =
|
|
1089
|
+
'<div class="fallback">' +
|
|
1090
|
+
'<div class="fallback-title">' + esc(title) + '</div>' +
|
|
1091
|
+
'<div class="fallback-copy">' + copyHtml + '</div>' +
|
|
1092
|
+
'<div class="fallback-actions">' +
|
|
1093
|
+
'<button type="button" class="primary" data-fallback-open>Open in new tab</button>' +
|
|
1094
|
+
'<button type="button" data-fallback-retry>' + esc(retryLabel) + '</button>' +
|
|
1095
|
+
'</div>' +
|
|
1096
|
+
(openUrl ? '<a class="fallback-url" href="' + esc(openUrl) + '" target="_blank" rel="noreferrer">' + esc(openUrl) + '</a>' : '') +
|
|
1097
|
+
'</div>';
|
|
1098
|
+
stage.appendChild(overlay);
|
|
1099
|
+
|
|
1100
|
+
const fallbackOpen = overlay.querySelector("[data-fallback-open]");
|
|
1101
|
+
const fallbackRetry = overlay.querySelector("[data-fallback-retry]");
|
|
1102
|
+
if (fallbackOpen) {
|
|
1103
|
+
fallbackOpen.disabled = !openUrl;
|
|
1104
|
+
fallbackOpen.onclick = () => {
|
|
1105
|
+
if (openUrl) void openFallbackExternal();
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
if (fallbackRetry) {
|
|
1109
|
+
fallbackRetry.disabled = typeof onRetry !== "function";
|
|
1110
|
+
fallbackRetry.onclick = () => {
|
|
1111
|
+
if (typeof onRetry === "function") void onRetry();
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1076
1117
|
function renderFrameFallback() {
|
|
1077
1118
|
clearFrameReadyTimer();
|
|
1078
1119
|
clearFrameLoadTimer();
|
|
1079
|
-
|
|
1120
|
+
appFrameReady = false;
|
|
1080
1121
|
const fallbackCopy = openUrl
|
|
1081
1122
|
? "This chat host did not allow the embedded app frame to load inline. You can still open the same app route through the host or use the URL below."
|
|
1082
1123
|
: "This chat host did not allow the embedded app frame to load inline.";
|
|
1083
1124
|
reportEmbedError("frame-fallback", fallbackCopy);
|
|
1125
|
+
if (renderFallbackOverlay({
|
|
1126
|
+
title: "Open this app in its own tab",
|
|
1127
|
+
copyHtml: esc(fallbackCopy),
|
|
1128
|
+
retryLabel: "Try inline again",
|
|
1129
|
+
onRetry: lastFrameSrc
|
|
1130
|
+
? () => renderFrame(lastFrameSrc)
|
|
1131
|
+
: undefined
|
|
1132
|
+
})) {
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
appFrame = null;
|
|
1084
1136
|
stage.innerHTML =
|
|
1085
1137
|
'<div class="fallback">' +
|
|
1086
1138
|
'<div class="fallback-title">Open this app in its own tab</div>' +
|
|
@@ -1110,7 +1162,7 @@ export function embedApp(options = {}) {
|
|
|
1110
1162
|
function renderAppLaunchError(message) {
|
|
1111
1163
|
clearFrameReadyTimer();
|
|
1112
1164
|
clearFrameLoadTimer();
|
|
1113
|
-
|
|
1165
|
+
appFrameReady = false;
|
|
1114
1166
|
const fallbackCopy = openUrl
|
|
1115
1167
|
? "The inline MCP app could not load in this chat host. You can open the same app route in a new tab or retry the inline load."
|
|
1116
1168
|
: "The inline MCP app could not load in this chat host.";
|
|
@@ -1118,6 +1170,18 @@ export function embedApp(options = {}) {
|
|
|
1118
1170
|
const copyHtml = message
|
|
1119
1171
|
? '<div>' + esc(message) + '</div><div>' + esc(fallbackCopy) + '</div>'
|
|
1120
1172
|
: esc(fallbackCopy);
|
|
1173
|
+
if (renderFallbackOverlay({
|
|
1174
|
+
title: "App did not load",
|
|
1175
|
+
copyHtml,
|
|
1176
|
+
retryLabel: "Retry",
|
|
1177
|
+
onRetry: () => {
|
|
1178
|
+
startedFor = "";
|
|
1179
|
+
void launchEmbed();
|
|
1180
|
+
}
|
|
1181
|
+
})) {
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
appFrame = null;
|
|
1121
1185
|
stage.innerHTML =
|
|
1122
1186
|
'<div class="fallback">' +
|
|
1123
1187
|
'<div class="fallback-title">App did not load</div>' +
|
|
@@ -1178,6 +1242,10 @@ export function embedApp(options = {}) {
|
|
|
1178
1242
|
sendFrameReadyMessages(frame);
|
|
1179
1243
|
startFrameReadyTimer(frame);
|
|
1180
1244
|
});
|
|
1245
|
+
frame.addEventListener("error", () => {
|
|
1246
|
+
if (appFrame !== frame) return;
|
|
1247
|
+
renderFrameFallback();
|
|
1248
|
+
});
|
|
1181
1249
|
stage.replaceChildren(frame);
|
|
1182
1250
|
notifyHostHeight();
|
|
1183
1251
|
appFrameLoadTimer = setTimeout(() => {
|
|
@@ -1475,6 +1543,7 @@ export function embedApp(options = {}) {
|
|
|
1475
1543
|
const data = event.data.data || {};
|
|
1476
1544
|
if (message.type === "agentNative.embeddedAppReady") {
|
|
1477
1545
|
appFrameReady = true;
|
|
1546
|
+
clearFallbackOverlay();
|
|
1478
1547
|
embedSessionRefreshAttempts = 0;
|
|
1479
1548
|
clearFrameLoadTimer();
|
|
1480
1549
|
clearFrameReadyTimer();
|
|
@@ -42,22 +42,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
44
|
error?: undefined;
|
|
45
|
-
ok?: undefined;
|
|
46
45
|
summary: import("./types.js").TraceSummary;
|
|
47
46
|
spans: import("./types.js").TraceSpan[];
|
|
48
47
|
id?: undefined;
|
|
48
|
+
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
50
|
error?: undefined;
|
|
51
|
-
ok?: undefined;
|
|
52
51
|
summary?: undefined;
|
|
53
52
|
spans?: undefined;
|
|
54
53
|
id: string;
|
|
55
|
-
} | {
|
|
56
54
|
ok?: undefined;
|
|
55
|
+
} | {
|
|
57
56
|
summary?: undefined;
|
|
58
57
|
spans?: undefined;
|
|
59
58
|
id?: undefined;
|
|
60
59
|
error: any;
|
|
60
|
+
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
62
|
error?: undefined;
|
|
63
63
|
summary?: undefined;
|