@agent-native/core 0.77.4 → 0.77.7
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/core/CHANGELOG.md +31 -0
- package/corpus/core/package.json +3 -3
- package/corpus/core/src/agent/production-agent.ts +35 -0
- package/corpus/core/src/agent/run-store.ts +2 -0
- package/corpus/core/src/agent/thread-data-builder.ts +21 -2
- package/corpus/core/src/cli/create.ts +35 -1
- package/corpus/core/src/cli/skills.ts +8 -0
- package/corpus/core/src/client/AgentPanel.tsx +57 -25
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -1
- package/corpus/core/src/client/analytics.ts +24 -2
- package/corpus/core/src/client/changelog/Changelog.tsx +22 -10
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +405 -35
- package/corpus/core/src/client/use-agent-engine-configured.ts +29 -15
- package/corpus/core/src/client/use-chat-threads.ts +104 -55
- package/corpus/core/src/server/analytics.ts +27 -3
- package/corpus/core/src/sharing/access.ts +35 -13
- package/corpus/core/src/sharing/actions/share-resource.ts +32 -9
- package/corpus/core/src/sharing/actions/unshare-resource.ts +25 -2
- package/corpus/core/src/sharing/registry.ts +9 -0
- package/corpus/core/src/vite/client.ts +3 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +25 -14
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +2 -2
- package/corpus/templates/analytics/app/lib/data-source-status.ts +47 -6
- package/corpus/templates/analytics/app/lib/data-sources.ts +14 -3
- package/corpus/templates/analytics/app/pages/DataSources.tsx +24 -5
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +15 -43
- package/corpus/templates/analytics/changelog/2026-06-25-fixed-hubspot-data-source-status-so-private-app-tokens-legac.md +6 -0
- package/corpus/templates/analytics/netlify.toml +1 -0
- package/corpus/templates/analytics/server/lib/credential-keys.ts +3 -1
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +12 -3
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +5 -2
- package/corpus/templates/assets/changelog/2026-06-25-create-now-returns-from-agent-settings-to-the-asset-chat-eve.md +6 -0
- package/corpus/templates/assets/netlify.toml +1 -0
- package/corpus/templates/brain/netlify.toml +1 -0
- package/corpus/templates/calendar/app/i18n-data.ts +12 -0
- package/corpus/templates/calendar/app/lib/clipboard.ts +58 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +15 -9
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +6 -2
- package/corpus/templates/calendar/changelog/2026-06-25-booking-link-copy-buttons-no-longer-fail-when-clipboard-perm.md +6 -0
- package/corpus/templates/calendar/netlify.toml +1 -0
- package/corpus/templates/chat/netlify.toml +1 -0
- package/corpus/templates/clips/AGENTS.md +9 -7
- package/corpus/templates/clips/actions/add-vocabulary-term.ts +2 -2
- package/corpus/templates/clips/actions/archive-recording.ts +5 -2
- package/corpus/templates/clips/actions/clear-edits.ts +5 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -2
- package/corpus/templates/clips/actions/delete-folder.ts +7 -4
- package/corpus/templates/clips/actions/delete-recording-permanent.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +5 -2
- package/corpus/templates/clips/actions/import-loom-recording.ts +2 -1
- package/corpus/templates/clips/actions/list-notifications.ts +9 -5
- package/corpus/templates/clips/actions/list-organization-state.ts +2 -1
- package/corpus/templates/clips/actions/list-recordings.ts +4 -1
- package/corpus/templates/clips/actions/move-recording.ts +5 -1
- package/corpus/templates/clips/actions/rename-folder.ts +6 -3
- package/corpus/templates/clips/actions/request-transcript.ts +5 -2
- package/corpus/templates/clips/actions/restore-recording.ts +5 -2
- package/corpus/templates/clips/actions/save-browser-diagnostics.ts +21 -8
- package/corpus/templates/clips/actions/set-chapters.ts +5 -2
- package/corpus/templates/clips/actions/set-thumbnail.ts +5 -2
- package/corpus/templates/clips/actions/split-recording.ts +5 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +6 -2
- package/corpus/templates/clips/actions/trash-recording.ts +5 -2
- package/corpus/templates/clips/actions/undo-edit.ts +5 -2
- package/corpus/templates/clips/actions/view-screen.ts +2 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +24 -7
- package/corpus/templates/clips/app/i18n/ar-SA.ts +14 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +14 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +14 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +14 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +14 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +14 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +14 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +14 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +14 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +14 -0
- package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +5 -1
- package/corpus/templates/clips/app/root.tsx +2 -2
- package/corpus/templates/clips/app/routes/_app.extensions.$id.tsx +4 -1
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +4 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +12 -5
- package/corpus/templates/clips/changelog/2026-06-25-chrome-extension-recordings-now-upload-large-capture-bursts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-console-diagnostics-keep-more-useful-non-secret-details-when.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-fixed-owner-recognition-so-clips-created-from-desktop-and-we.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-localized-clips-settings-changelog-and-extension-sidebar-lab.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +3 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +85 -9
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +55 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +79 -3
- package/corpus/templates/clips/chrome-extension/src/options.ts +10 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +6 -0
- package/corpus/templates/clips/chrome-extension/src/permission.ts +8 -1
- package/corpus/templates/clips/chrome-extension/src/popup.ts +65 -39
- package/corpus/templates/clips/chrome-extension/src/sentry.ts +206 -0
- package/corpus/templates/clips/chrome-extension/vite.config.ts +47 -0
- package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +4 -2
- package/corpus/templates/clips/desktop/src/styles.css +15 -1
- package/corpus/templates/clips/netlify.toml +1 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/lib/google-calendar-oauth.ts +35 -23
- package/corpus/templates/clips/server/lib/public-agent-context.ts +8 -1
- package/corpus/templates/clips/server/lib/recordings.ts +18 -2
- package/corpus/templates/clips/server/lib/slack-oauth.ts +9 -6
- package/corpus/templates/clips/server/plugins/onboarding-calendar.ts +6 -2
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +2 -2
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +5 -2
- package/corpus/templates/clips/shared/browser-diagnostics.ts +14 -4
- package/corpus/templates/content/netlify.toml +1 -0
- package/corpus/templates/design/netlify.toml +1 -0
- package/corpus/templates/dispatch/netlify.toml +1 -0
- package/corpus/templates/forms/netlify.toml +1 -0
- package/corpus/templates/macros/netlify.toml +1 -0
- package/corpus/templates/mail/app/components/email/EmailList.tsx +7 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +4 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +10 -2
- package/corpus/templates/mail/app/hooks/use-compose-state.ts +15 -5
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +47 -9
- package/corpus/templates/mail/changelog/2026-06-25-account-avatars-stay-stable-while-mail-refreshes-google-acco.md +6 -0
- package/corpus/templates/mail/changelog/2026-06-25-mail-background-draft-saves-and-thread-prefetches-no-longer.md +6 -0
- package/corpus/templates/mail/netlify.toml +1 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +8 -0
- package/corpus/templates/plan/netlify.toml +1 -0
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/videos/netlify.toml +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +31 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts +2 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +2 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +23 -2
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +28 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +8 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +8 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +29 -15
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +4 -4
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +22 -2
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/changelog/Changelog.d.ts +7 -2
- package/dist/client/changelog/Changelog.d.ts.map +1 -1
- package/dist/client/changelog/Changelog.js +9 -7
- package/dist/client/changelog/Changelog.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +339 -11
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +23 -13
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +4 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +49 -4
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +7 -7
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/analytics.d.ts +4 -0
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +19 -3
- package/dist/server/analytics.js.map +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +26 -12
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +20 -9
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +13 -2
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +9 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +3 -3
|
@@ -117,13 +117,29 @@ export function RecordingCard({
|
|
|
117
117
|
return (local || "?").slice(0, 2).toUpperCase();
|
|
118
118
|
}, [recording.ownerEmail]);
|
|
119
119
|
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
const recordingPath = `/r/${recording.id}`;
|
|
121
|
+
|
|
122
|
+
const handleOpen = useCallback(
|
|
123
|
+
(event: React.MouseEvent<HTMLElement>) => {
|
|
124
|
+
const shouldOpenNewTab =
|
|
125
|
+
event.button === 1 ||
|
|
126
|
+
(event.button === 0 && (event.metaKey || event.ctrlKey));
|
|
127
|
+
|
|
128
|
+
if (shouldOpenNewTab) {
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
event.stopPropagation();
|
|
131
|
+
window.open(recordingPath, "_blank", "noopener,noreferrer");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (selectionMode) {
|
|
136
|
+
onToggleSelect?.(recording.id);
|
|
137
|
+
} else {
|
|
138
|
+
navigate(recordingPath);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
[navigate, onToggleSelect, recording.id, recordingPath, selectionMode],
|
|
142
|
+
);
|
|
127
143
|
|
|
128
144
|
const handleCheckbox = useCallback(
|
|
129
145
|
(e: React.MouseEvent) => {
|
|
@@ -145,6 +161,7 @@ export function RecordingCard({
|
|
|
145
161
|
<div
|
|
146
162
|
role="article"
|
|
147
163
|
onClick={handleOpen}
|
|
164
|
+
onAuxClick={handleOpen}
|
|
148
165
|
onMouseEnter={() => setHovered(true)}
|
|
149
166
|
onMouseLeave={() => setHovered(false)}
|
|
150
167
|
className={cn(
|
|
@@ -547,6 +547,20 @@ const messages = {
|
|
|
547
547
|
languageDescription:
|
|
548
548
|
"اختر لغة الواجهة لهذا الحساب. سيتذكرها Clips عبر أجهزتك.",
|
|
549
549
|
languageLabel: "لغة الواجهة",
|
|
550
|
+
whatsNew: "ما الجديد",
|
|
551
|
+
changelogEmpty: "لا توجد تحديثات بعد.",
|
|
552
|
+
viewAllUpdates: "عرض كل التحديثات",
|
|
553
|
+
expand: "توسيع",
|
|
554
|
+
collapse: "طي",
|
|
555
|
+
changelogMarkdown: `# سجل التغييرات
|
|
556
|
+
|
|
557
|
+
يتم توثيق كل التغييرات المرئية لمستخدمي Clips هنا. يمكنك فتحه في أي وقت من قائمة الأوامر (Cmd+K -> "ما الجديد") أو من الإعدادات.
|
|
558
|
+
|
|
559
|
+
## 2026-06-23
|
|
560
|
+
|
|
561
|
+
### تمت الإضافة
|
|
562
|
+
|
|
563
|
+
- يمكنك الآن رؤية الجديد مباشرة داخل Clips. أصبح سجل التغييرات متاحًا في قائمة الأوامر (Cmd+K) وفي الإعدادات.`,
|
|
550
564
|
profile: "الملف الشخصي",
|
|
551
565
|
email: "البريد الإلكتروني",
|
|
552
566
|
displayName: "اسم العرض",
|
|
@@ -569,6 +569,20 @@ const messages = {
|
|
|
569
569
|
languageDescription:
|
|
570
570
|
"Wähle die Oberflächensprache für dieses Konto. Clips merkt sie sich geräteübergreifend.",
|
|
571
571
|
languageLabel: "Oberflächensprache",
|
|
572
|
+
whatsNew: "Neuigkeiten",
|
|
573
|
+
changelogEmpty: "Noch keine Updates.",
|
|
574
|
+
viewAllUpdates: "Alle Updates anzeigen",
|
|
575
|
+
expand: "Erweitern",
|
|
576
|
+
collapse: "Einklappen",
|
|
577
|
+
changelogMarkdown: `# Änderungsprotokoll
|
|
578
|
+
|
|
579
|
+
Alle sichtbaren Änderungen für Clips-Nutzer werden hier dokumentiert. Du kannst es jederzeit über das Befehlsmenü (Cmd+K -> "Neuigkeiten") oder über die Einstellungen öffnen.
|
|
580
|
+
|
|
581
|
+
## 2026-06-23
|
|
582
|
+
|
|
583
|
+
### Hinzugefügt
|
|
584
|
+
|
|
585
|
+
- Du kannst Neuigkeiten jetzt direkt in Clips ansehen. Das Änderungsprotokoll ist im Befehlsmenü (Cmd+K) und in den Einstellungen verfügbar.`,
|
|
572
586
|
profile: "Profil",
|
|
573
587
|
email: "E-Mail",
|
|
574
588
|
displayName: "Anzeigename",
|
|
@@ -547,6 +547,20 @@ const messages = {
|
|
|
547
547
|
languageDescription:
|
|
548
548
|
"Choose the interface language for this account. Clips remembers it across devices.",
|
|
549
549
|
languageLabel: "Interface language",
|
|
550
|
+
whatsNew: "What's new",
|
|
551
|
+
changelogEmpty: "No updates yet.",
|
|
552
|
+
viewAllUpdates: "View all updates",
|
|
553
|
+
expand: "Expand",
|
|
554
|
+
collapse: "Collapse",
|
|
555
|
+
changelogMarkdown: `# Changelog
|
|
556
|
+
|
|
557
|
+
All notable user-facing changes to Clips are documented here. Open it any time from the command menu (Cmd+K -> "What's new") or from Settings.
|
|
558
|
+
|
|
559
|
+
## 2026-06-23
|
|
560
|
+
|
|
561
|
+
### Added
|
|
562
|
+
|
|
563
|
+
- See what's new right inside Clips. A changelog now lives in the command menu (Cmd+K) and in Settings.`,
|
|
550
564
|
profile: "Profile",
|
|
551
565
|
email: "Email",
|
|
552
566
|
displayName: "Display name",
|
|
@@ -562,6 +562,20 @@ const messages = {
|
|
|
562
562
|
languageDescription:
|
|
563
563
|
"Elige el idioma de la interfaz para esta cuenta. Clips lo recordará en todos tus dispositivos.",
|
|
564
564
|
languageLabel: "Idioma de la interfaz",
|
|
565
|
+
whatsNew: "Novedades",
|
|
566
|
+
changelogEmpty: "Aún no hay actualizaciones.",
|
|
567
|
+
viewAllUpdates: "Ver todas las actualizaciones",
|
|
568
|
+
expand: "Expandir",
|
|
569
|
+
collapse: "Contraer",
|
|
570
|
+
changelogMarkdown: `# Registro de cambios
|
|
571
|
+
|
|
572
|
+
Todos los cambios visibles para los usuarios de Clips se documentan aquí. Puedes abrirlo en cualquier momento desde el menú de comandos (Cmd+K -> "Novedades") o desde Ajustes.
|
|
573
|
+
|
|
574
|
+
## 2026-06-23
|
|
575
|
+
|
|
576
|
+
### Añadido
|
|
577
|
+
|
|
578
|
+
- Ahora puedes ver las novedades directamente dentro de Clips. El registro de cambios vive en el menú de comandos (Cmd+K) y en Ajustes.`,
|
|
565
579
|
profile: "Perfil",
|
|
566
580
|
email: "Correo electrónico",
|
|
567
581
|
displayName: "Nombre visible",
|
|
@@ -562,6 +562,20 @@ const messages = {
|
|
|
562
562
|
languageDescription:
|
|
563
563
|
"Choisissez la langue de l’interface pour ce compte. Clips s’en souviendra sur tous vos appareils.",
|
|
564
564
|
languageLabel: "Langue de l’interface",
|
|
565
|
+
whatsNew: "Nouveautés",
|
|
566
|
+
changelogEmpty: "Aucune mise à jour pour le moment.",
|
|
567
|
+
viewAllUpdates: "Voir toutes les mises à jour",
|
|
568
|
+
expand: "Développer",
|
|
569
|
+
collapse: "Replier",
|
|
570
|
+
changelogMarkdown: `# Journal des modifications
|
|
571
|
+
|
|
572
|
+
Tous les changements visibles par les utilisateurs de Clips sont documentés ici. Vous pouvez l’ouvrir à tout moment depuis le menu de commandes (Cmd+K -> "Nouveautés") ou depuis les paramètres.
|
|
573
|
+
|
|
574
|
+
## 2026-06-23
|
|
575
|
+
|
|
576
|
+
### Ajouté
|
|
577
|
+
|
|
578
|
+
- Vous pouvez maintenant voir les nouveautés directement dans Clips. Le journal des modifications est disponible dans le menu de commandes (Cmd+K) et dans les paramètres.`,
|
|
565
579
|
profile: "Profil",
|
|
566
580
|
email: "E-mail",
|
|
567
581
|
displayName: "Nom affiché",
|
|
@@ -544,6 +544,20 @@ const messages = {
|
|
|
544
544
|
languageDescription:
|
|
545
545
|
"इस खाते के लिए इंटरफ़ेस भाषा चुनें। Clips इसे आपके डिवाइसों पर याद रखेगा।",
|
|
546
546
|
languageLabel: "इंटरफ़ेस भाषा",
|
|
547
|
+
whatsNew: "नया क्या है",
|
|
548
|
+
changelogEmpty: "अभी कोई अपडेट नहीं है।",
|
|
549
|
+
viewAllUpdates: "सभी अपडेट देखें",
|
|
550
|
+
expand: "फैलाएं",
|
|
551
|
+
collapse: "समेटें",
|
|
552
|
+
changelogMarkdown: `# बदलाव लॉग
|
|
553
|
+
|
|
554
|
+
Clips में उपयोगकर्ताओं को दिखने वाले सभी महत्वपूर्ण बदलाव यहां दर्ज किए जाते हैं। आप इसे कमांड मेनू (Cmd+K -> "नया क्या है") या सेटिंग्स से कभी भी खोल सकते हैं।
|
|
555
|
+
|
|
556
|
+
## 2026-06-23
|
|
557
|
+
|
|
558
|
+
### जोड़ा गया
|
|
559
|
+
|
|
560
|
+
- अब आप Clips के अंदर ही नया क्या है देख सकते हैं। बदलाव लॉग अब कमांड मेनू (Cmd+K) और सेटिंग्स में उपलब्ध है।`,
|
|
547
561
|
profile: "प्रोफ़ाइल",
|
|
548
562
|
email: "ईमेल",
|
|
549
563
|
displayName: "दिखने वाला नाम",
|
|
@@ -558,6 +558,20 @@ const messages = {
|
|
|
558
558
|
languageDescription:
|
|
559
559
|
"このアカウントのインターフェイス言語を選択します。Clips はデバイス間で設定を記憶します。",
|
|
560
560
|
languageLabel: "インターフェイス言語",
|
|
561
|
+
whatsNew: "最新情報",
|
|
562
|
+
changelogEmpty: "まだ更新はありません。",
|
|
563
|
+
viewAllUpdates: "すべての更新を見る",
|
|
564
|
+
expand: "展開",
|
|
565
|
+
collapse: "折りたたむ",
|
|
566
|
+
changelogMarkdown: `# 変更履歴
|
|
567
|
+
|
|
568
|
+
Clips のユーザー向けの主な変更はここに記録されます。コマンドメニュー(Cmd+K -> "最新情報")または設定からいつでも開けます。
|
|
569
|
+
|
|
570
|
+
## 2026-06-23
|
|
571
|
+
|
|
572
|
+
### 追加
|
|
573
|
+
|
|
574
|
+
- Clips 内で最新情報を直接確認できるようになりました。変更履歴はコマンドメニュー(Cmd+K)と設定にあります。`,
|
|
561
575
|
profile: "プロフィール",
|
|
562
576
|
email: "メール",
|
|
563
577
|
displayName: "表示名",
|
|
@@ -551,6 +551,20 @@ const messages = {
|
|
|
551
551
|
languageDescription:
|
|
552
552
|
"이 계정의 인터페이스 언어를 선택하세요. Clips가 여러 기기에서 기억합니다.",
|
|
553
553
|
languageLabel: "인터페이스 언어",
|
|
554
|
+
whatsNew: "새 소식",
|
|
555
|
+
changelogEmpty: "아직 업데이트가 없습니다.",
|
|
556
|
+
viewAllUpdates: "모든 업데이트 보기",
|
|
557
|
+
expand: "펼치기",
|
|
558
|
+
collapse: "접기",
|
|
559
|
+
changelogMarkdown: `# 변경 로그
|
|
560
|
+
|
|
561
|
+
Clips의 모든 사용자 대상 변경 사항은 여기에 기록됩니다. 명령 메뉴(Cmd+K -> "새 소식") 또는 설정에서 언제든지 열 수 있습니다.
|
|
562
|
+
|
|
563
|
+
## 2026-06-23
|
|
564
|
+
|
|
565
|
+
### 추가됨
|
|
566
|
+
|
|
567
|
+
- 이제 Clips 안에서 바로 새 소식을 볼 수 있습니다. 변경 로그는 명령 메뉴(Cmd+K)와 설정에 있습니다.`,
|
|
554
568
|
profile: "프로필",
|
|
555
569
|
email: "이메일",
|
|
556
570
|
displayName: "표시 이름",
|
|
@@ -560,6 +560,20 @@ const messages = {
|
|
|
560
560
|
languageDescription:
|
|
561
561
|
"Escolha o idioma da interface para esta conta. O Clips lembrará em todos os seus dispositivos.",
|
|
562
562
|
languageLabel: "Idioma da interface",
|
|
563
|
+
whatsNew: "Novidades",
|
|
564
|
+
changelogEmpty: "Ainda não há atualizações.",
|
|
565
|
+
viewAllUpdates: "Ver todas as atualizações",
|
|
566
|
+
expand: "Expandir",
|
|
567
|
+
collapse: "Recolher",
|
|
568
|
+
changelogMarkdown: `# Registro de alterações
|
|
569
|
+
|
|
570
|
+
Todas as mudanças visíveis para usuários do Clips são documentadas aqui. Você pode abrir a qualquer momento pelo menu de comandos (Cmd+K -> "Novidades") ou pelas Configurações.
|
|
571
|
+
|
|
572
|
+
## 2026-06-23
|
|
573
|
+
|
|
574
|
+
### Adicionado
|
|
575
|
+
|
|
576
|
+
- Agora você pode ver as novidades diretamente dentro do Clips. O registro de alterações fica no menu de comandos (Cmd+K) e nas Configurações.`,
|
|
563
577
|
profile: "Perfil",
|
|
564
578
|
email: "E-mail",
|
|
565
579
|
displayName: "Nome de exibição",
|
|
@@ -526,6 +526,20 @@ const messages = {
|
|
|
526
526
|
languageDescription:
|
|
527
527
|
"选择此账号的界面语言。Clips 会在不同设备上记住你的选择。",
|
|
528
528
|
languageLabel: "界面语言",
|
|
529
|
+
whatsNew: "最新变化",
|
|
530
|
+
changelogEmpty: "暂无更新。",
|
|
531
|
+
viewAllUpdates: "查看所有更新",
|
|
532
|
+
expand: "展开",
|
|
533
|
+
collapse: "收起",
|
|
534
|
+
changelogMarkdown: `# 更新日志
|
|
535
|
+
|
|
536
|
+
Clips 中所有面向用户的重要更改都会记录在这里。你可以随时从命令菜单(Cmd+K -> “最新变化”)或设置中打开。
|
|
537
|
+
|
|
538
|
+
## 2026-06-23
|
|
539
|
+
|
|
540
|
+
### 新增
|
|
541
|
+
|
|
542
|
+
- 现在可以直接在 Clips 中查看最新变化。更新日志已加入命令菜单(Cmd+K)和设置。`,
|
|
529
543
|
profile: "个人资料",
|
|
530
544
|
email: "邮箱",
|
|
531
545
|
displayName: "显示名称",
|
|
@@ -26,8 +26,12 @@ function redactString(value: string): string {
|
|
|
26
26
|
return redactBrowserDiagnosticString(value);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function redactUrlString(value: string): string {
|
|
30
|
+
return redactBrowserDiagnosticString(value, { redactQueryValues: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
function sanitizeUrl(raw: string): string {
|
|
30
|
-
const redacted =
|
|
34
|
+
const redacted = redactUrlString(raw);
|
|
31
35
|
try {
|
|
32
36
|
const parsed = new URL(redacted, window.location.href);
|
|
33
37
|
parsed.username = "";
|
|
@@ -43,7 +43,6 @@ import {
|
|
|
43
43
|
import { Toaster } from "@/components/ui/sonner";
|
|
44
44
|
import { useNavigationState } from "@/hooks/use-navigation-state";
|
|
45
45
|
|
|
46
|
-
import changelog from "../CHANGELOG.md?raw";
|
|
47
46
|
import { i18nCatalog, loadI18nMessages } from "./i18n";
|
|
48
47
|
|
|
49
48
|
import stylesheet from "./global.css?url";
|
|
@@ -349,7 +348,8 @@ function AppContent() {
|
|
|
349
348
|
<CommandMenu
|
|
350
349
|
open={cmdkOpen}
|
|
351
350
|
onOpenChange={setCmdkOpen}
|
|
352
|
-
changelog={
|
|
351
|
+
changelog={t("settings.changelogMarkdown")}
|
|
352
|
+
changelogLabel={t("settings.whatsNew")}
|
|
353
353
|
changelogKey="clips"
|
|
354
354
|
>
|
|
355
355
|
<CommandMenu.Group heading={t("root.commandActions")}>
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client";
|
|
1
2
|
import { ExtensionViewerPage } from "@agent-native/core/client/extensions";
|
|
2
3
|
|
|
3
4
|
import { PageHeader } from "@/components/library/page-header";
|
|
4
5
|
|
|
5
6
|
export default function ExtensionViewerRoute() {
|
|
7
|
+
const t = useT();
|
|
8
|
+
|
|
6
9
|
return (
|
|
7
10
|
<>
|
|
8
11
|
<PageHeader>
|
|
9
12
|
<h1 className="text-base font-semibold tracking-tight truncate">
|
|
10
|
-
|
|
13
|
+
{t("navigation.extensions")}
|
|
11
14
|
</h1>
|
|
12
15
|
</PageHeader>
|
|
13
16
|
<ExtensionViewerPage />
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client";
|
|
1
2
|
import { ExtensionsListPage } from "@agent-native/core/client/extensions";
|
|
2
3
|
|
|
3
4
|
import { PageHeader } from "@/components/library/page-header";
|
|
4
5
|
|
|
5
6
|
export default function ExtensionsRoute() {
|
|
7
|
+
const t = useT();
|
|
8
|
+
|
|
6
9
|
return (
|
|
7
10
|
<>
|
|
8
11
|
<PageHeader>
|
|
9
12
|
<h1 className="text-base font-semibold tracking-tight truncate">
|
|
10
|
-
|
|
13
|
+
{t("navigation.extensions")}
|
|
11
14
|
</h1>
|
|
12
15
|
</PageHeader>
|
|
13
16
|
<ExtensionsListPage />
|
|
@@ -66,8 +66,6 @@ import { useVideoStorageStatus } from "@/hooks/use-video-storage-status";
|
|
|
66
66
|
import enMessages from "@/i18n/en-US";
|
|
67
67
|
import { cn } from "@/lib/utils";
|
|
68
68
|
|
|
69
|
-
import changelog from "../../CHANGELOG.md?raw";
|
|
70
|
-
|
|
71
69
|
export function meta() {
|
|
72
70
|
return [{ title: enMessages.settings.pageTitle }];
|
|
73
71
|
}
|
|
@@ -343,7 +341,12 @@ async function saveRegisteredSecret(key: string, value: string): Promise<void> {
|
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
function CompactChangelogAside() {
|
|
346
|
-
const
|
|
344
|
+
const t = useT();
|
|
345
|
+
const localizedChangelog = t("settings.changelogMarkdown");
|
|
346
|
+
const entries = useMemo(
|
|
347
|
+
() => parseChangelog(localizedChangelog),
|
|
348
|
+
[localizedChangelog],
|
|
349
|
+
);
|
|
347
350
|
const [expanded, setExpanded] = useState(false);
|
|
348
351
|
|
|
349
352
|
if (entries.length === 0) return null;
|
|
@@ -361,8 +364,12 @@ function CompactChangelogAside() {
|
|
|
361
364
|
)}
|
|
362
365
|
>
|
|
363
366
|
<ChangelogSettingsCard
|
|
364
|
-
markdown={
|
|
367
|
+
markdown={localizedChangelog}
|
|
365
368
|
limit={1}
|
|
369
|
+
title={t("settings.whatsNew")}
|
|
370
|
+
closeLabel={t("common.cancel")}
|
|
371
|
+
emptyText={t("settings.changelogEmpty")}
|
|
372
|
+
viewAllLabel={t("settings.viewAllUpdates")}
|
|
366
373
|
className="rounded-md"
|
|
367
374
|
/>
|
|
368
375
|
</div>
|
|
@@ -378,7 +385,7 @@ function CompactChangelogAside() {
|
|
|
378
385
|
className="h-7 px-2 text-xs text-muted-foreground"
|
|
379
386
|
onClick={() => setExpanded((value) => !value)}
|
|
380
387
|
>
|
|
381
|
-
{expanded ? "
|
|
388
|
+
{expanded ? t("settings.collapse") : t("settings.expand")}
|
|
382
389
|
</Button>
|
|
383
390
|
</div>
|
|
384
391
|
) : null}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Agent-Native Clips",
|
|
4
4
|
"short_name": "Clips",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.3",
|
|
6
6
|
"description": "Start Clips recordings from Chrome with optional redacted console and network diagnostics.",
|
|
7
7
|
"minimum_chrome_version": "116",
|
|
8
8
|
"action": {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { captureExtensionError, initExtensionSentry } from "./sentry";
|
|
2
|
+
|
|
3
|
+
initExtensionSentry("background");
|
|
4
|
+
|
|
1
5
|
const DEFAULT_CLIPS_BASE_URL = "https://clips.agent-native.com";
|
|
2
6
|
const DEBUGGER_PROTOCOL_VERSION = "1.3";
|
|
3
7
|
const MAX_CONSOLE_LOGS = 400;
|
|
@@ -149,6 +153,15 @@ type OffscreenStatusMessage = {
|
|
|
149
153
|
error?: string;
|
|
150
154
|
};
|
|
151
155
|
|
|
156
|
+
type ExtensionErrorMessage = {
|
|
157
|
+
type: "CLIPS_EXTENSION_ERROR";
|
|
158
|
+
surface?: string;
|
|
159
|
+
name?: string;
|
|
160
|
+
message?: string;
|
|
161
|
+
stack?: string;
|
|
162
|
+
context?: Record<string, unknown>;
|
|
163
|
+
};
|
|
164
|
+
|
|
152
165
|
type PendingNetworkRequest = {
|
|
153
166
|
requestId: string;
|
|
154
167
|
timestampMs: number;
|
|
@@ -516,19 +529,24 @@ function truncate(value: string, maxLength: number): string {
|
|
|
516
529
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
517
530
|
}
|
|
518
531
|
|
|
519
|
-
function redactString(
|
|
520
|
-
|
|
532
|
+
function redactString(
|
|
533
|
+
value: string,
|
|
534
|
+
options: { redactQueryValues?: boolean } = {},
|
|
535
|
+
): string {
|
|
536
|
+
const redacted = value
|
|
521
537
|
.replace(AUTHORIZATION_SCHEME_RE, "$1$2<redacted>")
|
|
522
538
|
.replace(/\b(bearer|basic)\s+[a-z0-9._~+/-]+=*/gi, "$1 <redacted>")
|
|
523
539
|
.replace(DOUBLE_QUOTED_SECRET_VALUE_RE, '$1$2$1$3"<redacted>"')
|
|
524
540
|
.replace(SINGLE_QUOTED_SECRET_VALUE_RE, "$1$2$1$3'<redacted>'")
|
|
525
|
-
.replace(UNQUOTED_SECRET_VALUE_RE, "$1$2$1$3<redacted>")
|
|
526
|
-
|
|
541
|
+
.replace(UNQUOTED_SECRET_VALUE_RE, "$1$2$1$3<redacted>");
|
|
542
|
+
return options.redactQueryValues
|
|
543
|
+
? redacted.replace(/([?&][^=\s&?#]+)=([^&\s#]+)/g, "$1=<redacted>")
|
|
544
|
+
: redacted;
|
|
527
545
|
}
|
|
528
546
|
|
|
529
547
|
function sanitizeUrl(raw: string | null | undefined): string | null {
|
|
530
548
|
if (!raw) return null;
|
|
531
|
-
const redacted = redactString(raw);
|
|
549
|
+
const redacted = redactString(raw, { redactQueryValues: true });
|
|
532
550
|
try {
|
|
533
551
|
const parsed = new URL(redacted);
|
|
534
552
|
parsed.username = "";
|
|
@@ -1016,6 +1034,17 @@ async function armRecording(args: {
|
|
|
1016
1034
|
visibility: "public",
|
|
1017
1035
|
});
|
|
1018
1036
|
} catch (err) {
|
|
1037
|
+
captureExtensionError(err, {
|
|
1038
|
+
tags: {
|
|
1039
|
+
surface: "background",
|
|
1040
|
+
recordingStep: "create-recording",
|
|
1041
|
+
},
|
|
1042
|
+
extra: {
|
|
1043
|
+
captureSurface: settings.captureSurface,
|
|
1044
|
+
includeCamera: settings.includeCamera,
|
|
1045
|
+
includeMicrophone: settings.includeMicrophone,
|
|
1046
|
+
},
|
|
1047
|
+
});
|
|
1019
1048
|
await abortArming();
|
|
1020
1049
|
throw err;
|
|
1021
1050
|
}
|
|
@@ -1070,6 +1099,18 @@ async function armRecording(args: {
|
|
|
1070
1099
|
});
|
|
1071
1100
|
} catch (err) {
|
|
1072
1101
|
console.error("[clips-bg] arm: BEGIN failed", err);
|
|
1102
|
+
captureExtensionError(err, {
|
|
1103
|
+
tags: {
|
|
1104
|
+
surface: "background",
|
|
1105
|
+
recordingStep: "offscreen-begin",
|
|
1106
|
+
},
|
|
1107
|
+
extra: {
|
|
1108
|
+
recordingId: created.id,
|
|
1109
|
+
captureSurface: settings.captureSurface,
|
|
1110
|
+
includeCamera: settings.includeCamera,
|
|
1111
|
+
includeMicrophone: settings.includeMicrophone,
|
|
1112
|
+
},
|
|
1113
|
+
});
|
|
1073
1114
|
await cancelRecording();
|
|
1074
1115
|
throw err;
|
|
1075
1116
|
}
|
|
@@ -1553,9 +1594,15 @@ function pushConsole(
|
|
|
1553
1594
|
const timestampMs = Number.isFinite(entry.timestampMs)
|
|
1554
1595
|
? (entry.timestampMs as number)
|
|
1555
1596
|
: nowMs();
|
|
1556
|
-
const message = truncate(
|
|
1597
|
+
const message = truncate(
|
|
1598
|
+
redactString(entry.message, { redactQueryValues: true }),
|
|
1599
|
+
MAX_MESSAGE_LENGTH,
|
|
1600
|
+
);
|
|
1557
1601
|
const stack = entry.stack
|
|
1558
|
-
? truncate(
|
|
1602
|
+
? truncate(
|
|
1603
|
+
redactString(entry.stack, { redactQueryValues: true }),
|
|
1604
|
+
MAX_MESSAGE_LENGTH,
|
|
1605
|
+
)
|
|
1559
1606
|
: "";
|
|
1560
1607
|
session.consoleLogs.push({
|
|
1561
1608
|
timestampMs,
|
|
@@ -1762,7 +1809,10 @@ function handleResponseReceived(
|
|
|
1762
1809
|
pending.ok = response.status >= 200 && response.status < 400;
|
|
1763
1810
|
}
|
|
1764
1811
|
if (typeof response.statusText === "string") {
|
|
1765
|
-
pending.statusText = truncate(
|
|
1812
|
+
pending.statusText = truncate(
|
|
1813
|
+
redactString(response.statusText, { redactQueryValues: true }),
|
|
1814
|
+
120,
|
|
1815
|
+
);
|
|
1766
1816
|
}
|
|
1767
1817
|
}
|
|
1768
1818
|
|
|
@@ -1792,7 +1842,12 @@ function finalizeNetworkRequest(
|
|
|
1792
1842
|
...(typeof pending.ok === "boolean" ? { ok: pending.ok } : {}),
|
|
1793
1843
|
durationMs: Math.round(durationMs),
|
|
1794
1844
|
...(error
|
|
1795
|
-
? {
|
|
1845
|
+
? {
|
|
1846
|
+
error: truncate(
|
|
1847
|
+
redactString(error, { redactQueryValues: true }),
|
|
1848
|
+
MAX_MESSAGE_LENGTH,
|
|
1849
|
+
),
|
|
1850
|
+
}
|
|
1796
1851
|
: {}),
|
|
1797
1852
|
});
|
|
1798
1853
|
}
|
|
@@ -1923,6 +1978,12 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
1923
1978
|
(message as { type?: unknown })?.type,
|
|
1924
1979
|
err,
|
|
1925
1980
|
);
|
|
1981
|
+
captureExtensionError(err, {
|
|
1982
|
+
tags: {
|
|
1983
|
+
surface: "background",
|
|
1984
|
+
messageType: String((message as { type?: unknown })?.type ?? ""),
|
|
1985
|
+
},
|
|
1986
|
+
});
|
|
1926
1987
|
response = {
|
|
1927
1988
|
ok: false,
|
|
1928
1989
|
error: err instanceof Error ? err.message : "Could not use Clips.",
|
|
@@ -1940,6 +2001,21 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
1940
2001
|
async function dispatchRuntimeMessage(message: unknown): Promise<unknown> {
|
|
1941
2002
|
const type = (message as { type?: unknown }).type;
|
|
1942
2003
|
|
|
2004
|
+
if (type === "CLIPS_EXTENSION_ERROR") {
|
|
2005
|
+
const report = message as ExtensionErrorMessage;
|
|
2006
|
+
const error = new Error(report.message || "Chrome extension error");
|
|
2007
|
+
error.name = report.name || "ExtensionError";
|
|
2008
|
+
if (report.stack) error.stack = report.stack;
|
|
2009
|
+
captureExtensionError(error, {
|
|
2010
|
+
tags: {
|
|
2011
|
+
surface: report.surface || "content-script",
|
|
2012
|
+
mechanism: "content-script-report",
|
|
2013
|
+
},
|
|
2014
|
+
extra: report.context,
|
|
2015
|
+
});
|
|
2016
|
+
return { ok: true };
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1943
2019
|
// Status updates streamed from the offscreen recorder.
|
|
1944
2020
|
if (type === "CLIPS_NATIVE_STATUS") {
|
|
1945
2021
|
const status = message as OffscreenStatusMessage;
|
|
@@ -18,6 +18,61 @@
|
|
|
18
18
|
const ALL_PARTS: OverlayPart[] = ["bubble", "countdown", "toolbar", "saving"];
|
|
19
19
|
const flags = window as unknown as { __clipsOverlayHostReady?: boolean };
|
|
20
20
|
|
|
21
|
+
function errorPayload(error: unknown): {
|
|
22
|
+
name: string;
|
|
23
|
+
message: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
} {
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
return {
|
|
28
|
+
name: error.name || "Error",
|
|
29
|
+
message: error.message || "Unknown content-script error",
|
|
30
|
+
stack: error.stack,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
name: "Error",
|
|
35
|
+
message: String(error ?? "Unknown content-script error"),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function reportContentScriptError(
|
|
40
|
+
error: unknown,
|
|
41
|
+
context: Record<string, unknown> = {},
|
|
42
|
+
): void {
|
|
43
|
+
try {
|
|
44
|
+
chrome.runtime.sendMessage(
|
|
45
|
+
{
|
|
46
|
+
type: "CLIPS_EXTENSION_ERROR",
|
|
47
|
+
surface: "content-script",
|
|
48
|
+
...errorPayload(error),
|
|
49
|
+
context: {
|
|
50
|
+
...context,
|
|
51
|
+
pageUrl: location.href,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
() => void chrome.runtime.lastError,
|
|
55
|
+
);
|
|
56
|
+
} catch {
|
|
57
|
+
/* background unavailable */
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
window.addEventListener("error", (event) => {
|
|
62
|
+
reportContentScriptError(event.error || event.message, {
|
|
63
|
+
mechanism: "global-error",
|
|
64
|
+
filename: event.filename,
|
|
65
|
+
lineno: event.lineno,
|
|
66
|
+
colno: event.colno,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
71
|
+
reportContentScriptError(event.reason, {
|
|
72
|
+
mechanism: "unhandled-rejection",
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
21
76
|
// ----- Draggable, resizable camera bubble ---------------------------------
|
|
22
77
|
// Size + position persist in storage so the bubble stays where the user put it
|
|
23
78
|
// across pages and recordings (like the desktop app). The iframe can't move or
|