@agent-native/core 0.90.9 → 0.90.10
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/README.md +7 -28
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +10 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +3 -3
- package/corpus/core/docs/content/tracking.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +15 -4
- package/corpus/core/src/client/analytics.ts +17 -3
- package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +3 -1
- package/corpus/core/src/client/blocks/library/wireframe.tsx +6 -1
- package/corpus/core/src/file-upload/builder.ts +10 -23
- package/corpus/core/src/file-upload/types.ts +3 -3
- package/corpus/core/src/styles/blocks.css +7 -0
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +9 -4
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +21 -7
- package/corpus/templates/analytics/app/entry.client.tsx +6 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-07-07-analytics-now-recovers-from-stale-route-chunks-after-deploys.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-07-metric-dashboard-cards-now-show-warehouse-backed-numeric-val.md +6 -0
- package/corpus/templates/clips/actions/create-recording.ts +1 -1
- package/corpus/templates/clips/actions/finalize-recording.ts +2 -2
- package/corpus/templates/clips/actions/import-loom-recording.ts +1 -1
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +1 -1
- package/corpus/templates/clips/changelog/2026-07-07-clip-video-uploads-now-compress-in-the-background-while-keeping.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-desktop-settings-and-fn-dictation-are-more-reliable.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-desktop-settings-now-includes-a-manual-update-check-with-res.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +95 -8
- package/corpus/templates/clips/desktop/src/lib/updater.ts +60 -43
- package/corpus/templates/clips/desktop/src/styles.css +5 -0
- package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +93 -23
- package/corpus/templates/dispatch/changelog/2026-07-07-overview-is-now-just-ask-dispatch-and-a-list-of-apps.md +6 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +16 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +14 -3
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +1 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.js +2 -1
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +6 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +9 -19
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/file-upload/types.d.ts +3 -3
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/styles/blocks.css +7 -0
- package/docs/content/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/ar-SA/tracking.mdx +3 -3
- package/docs/content/locales/de-DE/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/de-DE/tracking.mdx +3 -3
- package/docs/content/locales/es-ES/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/es-ES/tracking.mdx +3 -3
- package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/fr-FR/tracking.mdx +3 -3
- package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/hi-IN/tracking.mdx +3 -3
- package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/ja-JP/tracking.mdx +3 -3
- package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/ko-KR/tracking.mdx +3 -3
- package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/pt-BR/tracking.mdx +3 -3
- package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/zh-CN/tracking.mdx +3 -3
- package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +1 -1
- package/docs/content/locales/zh-TW/tracking.mdx +3 -3
- package/docs/content/tracking.mdx +3 -3
- package/package.json +1 -1
|
@@ -23,7 +23,7 @@ being rebuilt in slightly different ways every time.
|
|
|
23
23
|
<Screen
|
|
24
24
|
surface="desktop"
|
|
25
25
|
html={
|
|
26
|
-
"<div style='min-height:560px;box-sizing:border-box;
|
|
26
|
+
"<div style='min-height:560px;box-sizing:border-box;display:grid;grid-template-columns:200px 1fr 280px;gap:16px'><aside class='wf-card' style='display:flex;flex-direction:column;gap:8px;padding:14px'><div style='display:flex;align-items:center;gap:8px'><div style='width:26px;height:26px;border-radius:8px;background:var(--wf-accent-soft);display:flex;align-items:center;justify-content:center;font-size:12px;flex:none'>A</div><strong style='flex:1'>Acme</strong><span data-icon='chevronDown'></span></div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:8px;background:var(--wf-accent-soft)'><span data-icon='search'></span> Home</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='edit'></span> Documents</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='user'></span> Team</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='settings'></span> Settings</div><div style='flex:1'></div><div style='display:flex;align-items:center;gap:8px;padding-top:10px;border-top:1.4px solid var(--wf-line)'><div style='width:24px;height:24px;border-radius:999px;background:var(--wf-accent-soft);flex:none'></div><small style='flex:1'>Steve</small><span data-icon='dots'></span></div></aside><main class='wf-card' style='display:flex;flex-direction:column;gap:14px'><div style='display:flex;align-items:center;gap:10px'><h2 style='margin:0'>Q3 Forecast</h2><div style='flex:1'></div><div style='display:flex'><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div></div><button class='primary'><span data-icon='user'></span> Share</button></div><div class='wf-box' style='display:flex;flex-direction:column;gap:10px'><small class='wf-muted'>Revenue by month</small><div style='display:flex;align-items:flex-end;gap:10px;height:120px'><div style='flex:1;height:45%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:65%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:55%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:80%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:95%;background:var(--wf-accent);border-radius:4px'></div></div></div><div style='display:flex;gap:10px'><div class='wf-box' style='flex:1'><small class='wf-muted'>ARR</small><br/><strong>$4.2M</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Win rate</small><br/><strong>28%</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Pipeline</small><br/><strong>3.2x</strong></div></div></main><aside class='wf-card' style='display:flex;flex-direction:column;gap:10px'><strong>Agent</strong><div class='wf-box'>Summarize Q3 versus Q2 and flag risks.</div><div class='wf-box' style='background:var(--wf-accent-soft)'>Revenue up 12%. Two pipeline risks flagged.</div><div style='flex:1'></div><div class='wf-card' style='padding:10px;display:flex;flex-direction:column;gap:8px'><span class='wf-muted'>Ask about this dashboard...</span><div style='display:flex;align-items:center;gap:6px'><span class='wf-pill'>Q3 Forecast</span><span class='wf-pill'>GPT-5</span><div style='flex:1'></div><button class='primary'><span data-icon='send'></span></button></div></div></aside></div>"
|
|
27
27
|
}
|
|
28
28
|
/>
|
|
29
29
|
</WireframeBlock>
|
|
@@ -200,7 +200,7 @@ configureTracking({
|
|
|
200
200
|
endpoint: "https://analytics.example.com/api/analytics/track",
|
|
201
201
|
sessionReplay: {
|
|
202
202
|
enabled: true,
|
|
203
|
-
sampleRate:
|
|
203
|
+
sampleRate: 1,
|
|
204
204
|
},
|
|
205
205
|
getDefaultProps: (_event, props) => ({
|
|
206
206
|
...props,
|
|
@@ -218,14 +218,14 @@ As raízes dos modelos do Agent Native já chamam `configureTracking()`. As impl
|
|
|
218
218
|
VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY=anpk_...
|
|
219
219
|
VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT=https://analytics.example.com/api/analytics/track
|
|
220
220
|
VITE_AGENT_NATIVE_SESSION_REPLAY_ENABLED=true
|
|
221
|
-
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=
|
|
221
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=1
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
O auxiliar do navegador também realiza uma leitura best-effort e não bloqueante da sessão de autenticação atual do Agent Native. O replay é, por padrão, exclusivo para usuários conectados: quando `sessionReplay` está habilitado, a gravação não começa a menos que a sessão seja resolvida para um endereço de e-mail de usuário. Replays de usuários conectados incluem `userId`/`userEmail` baseados em e-mail, além de `orgId`.
|
|
225
225
|
|
|
226
226
|
Defina `sessionReplay.requireSignedInUser: false` ou `VITE_AGENT_NATIVE_SESSION_REPLAY_REQUIRE_AUTH=false` apenas para uma implantação de replay anônimo intencional. Quando o controle de autenticação está desabilitado, as gravações anônimas permanecem consultáveis por visitante anônimo, sessão, aplicativo/modelo, hostname e caminho.
|
|
227
227
|
|
|
228
|
-
O replay de sessão é amostrado de forma determinística por sessão do navegador. Um `sampleRate` de `
|
|
228
|
+
O replay de sessão é amostrado de forma determinística por sessão do navegador. Um `sampleRate` de `1` registra todas as sessões elegíveis; use valores menores, como `0.1`, quando a população elegível for intencionalmente ampla.
|
|
229
229
|
|
|
230
230
|
Os padrões de privacidade são intencionalmente conservadores, mas ainda úteis para a reprodução:
|
|
231
231
|
|
|
@@ -23,7 +23,7 @@ being rebuilt in slightly different ways every time.
|
|
|
23
23
|
<Screen
|
|
24
24
|
surface="desktop"
|
|
25
25
|
html={
|
|
26
|
-
"<div style='min-height:560px;box-sizing:border-box;
|
|
26
|
+
"<div style='min-height:560px;box-sizing:border-box;display:grid;grid-template-columns:200px 1fr 280px;gap:16px'><aside class='wf-card' style='display:flex;flex-direction:column;gap:8px;padding:14px'><div style='display:flex;align-items:center;gap:8px'><div style='width:26px;height:26px;border-radius:8px;background:var(--wf-accent-soft);display:flex;align-items:center;justify-content:center;font-size:12px;flex:none'>A</div><strong style='flex:1'>Acme</strong><span data-icon='chevronDown'></span></div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:8px;background:var(--wf-accent-soft)'><span data-icon='search'></span> Home</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='edit'></span> Documents</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='user'></span> Team</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='settings'></span> Settings</div><div style='flex:1'></div><div style='display:flex;align-items:center;gap:8px;padding-top:10px;border-top:1.4px solid var(--wf-line)'><div style='width:24px;height:24px;border-radius:999px;background:var(--wf-accent-soft);flex:none'></div><small style='flex:1'>Steve</small><span data-icon='dots'></span></div></aside><main class='wf-card' style='display:flex;flex-direction:column;gap:14px'><div style='display:flex;align-items:center;gap:10px'><h2 style='margin:0'>Q3 Forecast</h2><div style='flex:1'></div><div style='display:flex'><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div></div><button class='primary'><span data-icon='user'></span> Share</button></div><div class='wf-box' style='display:flex;flex-direction:column;gap:10px'><small class='wf-muted'>Revenue by month</small><div style='display:flex;align-items:flex-end;gap:10px;height:120px'><div style='flex:1;height:45%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:65%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:55%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:80%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:95%;background:var(--wf-accent);border-radius:4px'></div></div></div><div style='display:flex;gap:10px'><div class='wf-box' style='flex:1'><small class='wf-muted'>ARR</small><br/><strong>$4.2M</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Win rate</small><br/><strong>28%</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Pipeline</small><br/><strong>3.2x</strong></div></div></main><aside class='wf-card' style='display:flex;flex-direction:column;gap:10px'><strong>Agent</strong><div class='wf-box'>Summarize Q3 versus Q2 and flag risks.</div><div class='wf-box' style='background:var(--wf-accent-soft)'>Revenue up 12%. Two pipeline risks flagged.</div><div style='flex:1'></div><div class='wf-card' style='padding:10px;display:flex;flex-direction:column;gap:8px'><span class='wf-muted'>Ask about this dashboard...</span><div style='display:flex;align-items:center;gap:6px'><span class='wf-pill'>Q3 Forecast</span><span class='wf-pill'>GPT-5</span><div style='flex:1'></div><button class='primary'><span data-icon='send'></span></button></div></div></aside></div>"
|
|
27
27
|
}
|
|
28
28
|
/>
|
|
29
29
|
</WireframeBlock>
|
|
@@ -200,7 +200,7 @@ configureTracking({
|
|
|
200
200
|
endpoint: "https://analytics.example.com/api/analytics/track",
|
|
201
201
|
sessionReplay: {
|
|
202
202
|
enabled: true,
|
|
203
|
-
sampleRate:
|
|
203
|
+
sampleRate: 1,
|
|
204
204
|
},
|
|
205
205
|
getDefaultProps: (_event, props) => ({
|
|
206
206
|
...props,
|
|
@@ -218,14 +218,14 @@ Agent Native 模板根已经调用了 `configureTracking()`。托管模板部署
|
|
|
218
218
|
VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY=anpk_...
|
|
219
219
|
VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT=https://analytics.example.com/api/analytics/track
|
|
220
220
|
VITE_AGENT_NATIVE_SESSION_REPLAY_ENABLED=true
|
|
221
|
-
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=
|
|
221
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=1
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
浏览器端辅助函数还会尽力地、非阻塞地读取当前 Agent Native 认证会话。默认情况下,重放仅限已登录用户:启用 `sessionReplay` 后,除非会话解析出用户邮箱地址,否则不会开始录制。已登录用户的重放会包含基于邮箱的 `userId`/`userEmail` 以及 `orgId`。
|
|
225
225
|
|
|
226
226
|
仅在有意进行匿名重放部署时,才设置 `sessionReplay.requireSignedInUser: false` 或 `VITE_AGENT_NATIVE_SESSION_REPLAY_REQUIRE_AUTH=false`。禁用认证门控后,匿名录制仍可按匿名访客、会话、应用/模板、主机名和路径进行查询。
|
|
227
227
|
|
|
228
|
-
会话重放按浏览器会话确定性采样。`sampleRate` 为 `
|
|
228
|
+
会话重放按浏览器会话确定性采样。`sampleRate` 为 `1` 时,会记录所有符合条件的会话;当符合条件的用户群体有意较大时,可使用较低值,例如 `0.1`。
|
|
229
229
|
|
|
230
230
|
隐私默认设置刻意保持保守,但仍能满足回放的可用性:
|
|
231
231
|
|
|
@@ -23,7 +23,7 @@ being rebuilt in slightly different ways every time.
|
|
|
23
23
|
<Screen
|
|
24
24
|
surface="desktop"
|
|
25
25
|
html={
|
|
26
|
-
"<div style='min-height:560px;box-sizing:border-box;
|
|
26
|
+
"<div style='min-height:560px;box-sizing:border-box;display:grid;grid-template-columns:200px 1fr 280px;gap:16px'><aside class='wf-card' style='display:flex;flex-direction:column;gap:8px;padding:14px'><div style='display:flex;align-items:center;gap:8px'><div style='width:26px;height:26px;border-radius:8px;background:var(--wf-accent-soft);display:flex;align-items:center;justify-content:center;font-size:12px;flex:none'>A</div><strong style='flex:1'>Acme</strong><span data-icon='chevronDown'></span></div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:8px;background:var(--wf-accent-soft)'><span data-icon='search'></span> Home</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='edit'></span> Documents</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='user'></span> Team</div><div style='display:flex;align-items:center;gap:8px;padding:7px 9px'><span data-icon='settings'></span> Settings</div><div style='flex:1'></div><div style='display:flex;align-items:center;gap:8px;padding-top:10px;border-top:1.4px solid var(--wf-line)'><div style='width:24px;height:24px;border-radius:999px;background:var(--wf-accent-soft);flex:none'></div><small style='flex:1'>Steve</small><span data-icon='dots'></span></div></aside><main class='wf-card' style='display:flex;flex-direction:column;gap:14px'><div style='display:flex;align-items:center;gap:10px'><h2 style='margin:0'>Q3 Forecast</h2><div style='flex:1'></div><div style='display:flex'><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent-soft);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div><div style='width:26px;height:26px;border-radius:999px;background:var(--wf-accent);border:2px solid var(--wf-card);margin-left:-8px;flex:none'></div></div><button class='primary'><span data-icon='user'></span> Share</button></div><div class='wf-box' style='display:flex;flex-direction:column;gap:10px'><small class='wf-muted'>Revenue by month</small><div style='display:flex;align-items:flex-end;gap:10px;height:120px'><div style='flex:1;height:45%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:65%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:55%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:80%;background:var(--wf-accent-soft);border-radius:4px'></div><div style='flex:1;height:95%;background:var(--wf-accent);border-radius:4px'></div></div></div><div style='display:flex;gap:10px'><div class='wf-box' style='flex:1'><small class='wf-muted'>ARR</small><br/><strong>$4.2M</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Win rate</small><br/><strong>28%</strong></div><div class='wf-box' style='flex:1'><small class='wf-muted'>Pipeline</small><br/><strong>3.2x</strong></div></div></main><aside class='wf-card' style='display:flex;flex-direction:column;gap:10px'><strong>Agent</strong><div class='wf-box'>Summarize Q3 versus Q2 and flag risks.</div><div class='wf-box' style='background:var(--wf-accent-soft)'>Revenue up 12%. Two pipeline risks flagged.</div><div style='flex:1'></div><div class='wf-card' style='padding:10px;display:flex;flex-direction:column;gap:8px'><span class='wf-muted'>Ask about this dashboard...</span><div style='display:flex;align-items:center;gap:6px'><span class='wf-pill'>Q3 Forecast</span><span class='wf-pill'>GPT-5</span><div style='flex:1'></div><button class='primary'><span data-icon='send'></span></button></div></div></aside></div>"
|
|
27
27
|
}
|
|
28
28
|
/>
|
|
29
29
|
</WireframeBlock>
|
|
@@ -200,7 +200,7 @@ configureTracking({
|
|
|
200
200
|
endpoint: "https://analytics.example.com/api/analytics/track",
|
|
201
201
|
sessionReplay: {
|
|
202
202
|
enabled: true,
|
|
203
|
-
sampleRate:
|
|
203
|
+
sampleRate: 1,
|
|
204
204
|
},
|
|
205
205
|
getDefaultProps: (_event, props) => ({
|
|
206
206
|
...props,
|
|
@@ -218,14 +218,14 @@ Agent Native 範本根目錄已經呼叫了 `configureTracking()`。託管範本
|
|
|
218
218
|
VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY=anpk_...
|
|
219
219
|
VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT=https://analytics.example.com/api/analytics/track
|
|
220
220
|
VITE_AGENT_NATIVE_SESSION_REPLAY_ENABLED=true
|
|
221
|
-
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=
|
|
221
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=1
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
瀏覽器輔助程式也會盡力執行、非阻塞式讀取目前的 Agent Native 驗證工作階段。重播預設僅限已登入使用者:當 `sessionReplay` 啟用時,除非工作階段解析出使用者電子郵件地址,否則不會開始錄製。已登入使用者的重播包含以電子郵件為基礎的 `userId`/`userEmail` 以及 `orgId`。
|
|
225
225
|
|
|
226
226
|
僅在刻意進行匿名重播部署時,才設定 `sessionReplay.requireSignedInUser: false` 或 `VITE_AGENT_NATIVE_SESSION_REPLAY_REQUIRE_AUTH=false`。停用驗證閘控後,匿名錄製仍可依匿名訪客、工作階段、應用程式/範本、主機名稱與路徑進行查詢。
|
|
227
227
|
|
|
228
|
-
工作階段重播是依瀏覽器工作階段進行確定性取樣的。`sampleRate` 為 `
|
|
228
|
+
工作階段重播是依瀏覽器工作階段進行確定性取樣的。`sampleRate` 為 `1` 表示記錄所有符合條件的工作階段;當符合條件的母體刻意較大時,可使用較低值,例如 `0.1`。
|
|
229
229
|
|
|
230
230
|
隱私預設值刻意設計得保守,但仍足以支援播放:
|
|
231
231
|
|
|
@@ -200,7 +200,7 @@ configureTracking({
|
|
|
200
200
|
endpoint: "https://analytics.example.com/api/analytics/track",
|
|
201
201
|
sessionReplay: {
|
|
202
202
|
enabled: true,
|
|
203
|
-
sampleRate:
|
|
203
|
+
sampleRate: 1,
|
|
204
204
|
},
|
|
205
205
|
getDefaultProps: (_event, props) => ({
|
|
206
206
|
...props,
|
|
@@ -218,14 +218,14 @@ Agent Native template roots already call `configureTracking()`. Hosted template
|
|
|
218
218
|
VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY=anpk_...
|
|
219
219
|
VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT=https://analytics.example.com/api/analytics/track
|
|
220
220
|
VITE_AGENT_NATIVE_SESSION_REPLAY_ENABLED=true
|
|
221
|
-
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=
|
|
221
|
+
VITE_AGENT_NATIVE_SESSION_REPLAY_SAMPLE_RATE=1
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
The browser helper also performs a best-effort, non-blocking read of the current Agent Native auth session. Replay is signed-in-only by default: when `sessionReplay` is enabled, recording does not start unless the session resolves to a user email address. Signed-in replays include email-backed `userId`/`userEmail` plus `orgId`.
|
|
225
225
|
|
|
226
226
|
Set `sessionReplay.requireSignedInUser: false` or `VITE_AGENT_NATIVE_SESSION_REPLAY_REQUIRE_AUTH=false` only for an intentional anonymous replay deployment. When auth gating is disabled, anonymous recordings remain queryable by anonymous visitor, session, app/template, hostname, and path.
|
|
227
227
|
|
|
228
|
-
Session replay is sampled deterministically per browser session. A `sampleRate` of `
|
|
228
|
+
Session replay is sampled deterministically per browser session. A `sampleRate` of `1` records all eligible sessions; use lower values, such as `0.1`, when the eligible population is intentionally broad.
|
|
229
229
|
|
|
230
230
|
Privacy defaults are intentionally conservative but still useful for playback:
|
|
231
231
|
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.90.
|
|
3
|
+
"version": "0.90.10",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -1015,6 +1015,7 @@ const TOOL_INPUT_ACTIVITY_INTERVAL_MS = 1500;
|
|
|
1015
1015
|
const ACTION_PREPARATION_NO_PROGRESS_TIMEOUT_MS = 90_000;
|
|
1016
1016
|
const ACTION_PREPARATION_ZERO_BYTE_RESTART_LIMIT = 2;
|
|
1017
1017
|
const MODEL_STREAM_NO_PROGRESS_TIMEOUT_MS = 90_000;
|
|
1018
|
+
const EMPTY_FINAL_RESPONSE_RETRY_LIMIT = 1;
|
|
1018
1019
|
const MAIN_CHAT_INTERNAL_CONTINUATION_LIMIT = 6;
|
|
1019
1020
|
const RUN_BUDGET_EXHAUSTED_ERROR_CODE = "run_budget_exhausted";
|
|
1020
1021
|
const RUN_BUDGET_EXHAUSTED_MESSAGE =
|
|
@@ -2733,6 +2734,7 @@ export async function runAgentLoop(opts: {
|
|
|
2733
2734
|
}
|
|
2734
2735
|
|
|
2735
2736
|
let finalGuardRetries = 0;
|
|
2737
|
+
let emptyFinalResponseRetries = 0;
|
|
2736
2738
|
let iterations = 0;
|
|
2737
2739
|
|
|
2738
2740
|
// Set when an in-loop processor aborts via `abort()` / throws a `TripWire`.
|
|
@@ -3349,16 +3351,24 @@ export async function runAgentLoop(opts: {
|
|
|
3349
3351
|
// text — typically when reasoning consumes the entire output-token
|
|
3350
3352
|
// budget. Without a final text part the SSE stream still ends with a
|
|
3351
3353
|
// clean `done`, which renders as a totally empty assistant bubble.
|
|
3352
|
-
//
|
|
3353
|
-
|
|
3354
|
+
// Retry once so a transient reasoning-budget miss can still finish; if
|
|
3355
|
+
// the retry also has no visible content, surface a plain-language error.
|
|
3356
|
+
const hasEmptyFinalResponse =
|
|
3354
3357
|
!guardEmittedFallback &&
|
|
3355
3358
|
collectTextParts(assistantContentForHistory).trim().length === 0 &&
|
|
3356
|
-
streamedAssistantText.trim().length === 0
|
|
3357
|
-
) {
|
|
3359
|
+
streamedAssistantText.trim().length === 0;
|
|
3360
|
+
if (hasEmptyFinalResponse) {
|
|
3361
|
+
if (emptyFinalResponseRetries < EMPTY_FINAL_RESPONSE_RETRY_LIMIT) {
|
|
3362
|
+
emptyFinalResponseRetries += 1;
|
|
3363
|
+
appendAgentLoopContinuation(messages, "max_tokens");
|
|
3364
|
+
continue;
|
|
3365
|
+
}
|
|
3358
3366
|
send({
|
|
3359
3367
|
type: "text",
|
|
3360
3368
|
text: "The model returned an empty response. This usually means reasoning used the full output-token budget. Try again, or pick a different model from the model menu.",
|
|
3361
3369
|
});
|
|
3370
|
+
} else {
|
|
3371
|
+
emptyFinalResponseRetries = 0;
|
|
3362
3372
|
}
|
|
3363
3373
|
break;
|
|
3364
3374
|
}
|
|
@@ -3369,6 +3379,7 @@ export async function runAgentLoop(opts: {
|
|
|
3369
3379
|
// finalGuardRetries stays at 1 from a prior cycle and the guard is
|
|
3370
3380
|
// permanently disabled for the rest of a long multi-step run.
|
|
3371
3381
|
finalGuardRetries = 0;
|
|
3382
|
+
emptyFinalResponseRetries = 0;
|
|
3372
3383
|
|
|
3373
3384
|
flushUnstreamedAssistantText();
|
|
3374
3385
|
|
|
@@ -1005,8 +1005,16 @@ function configuredSessionReplayOptions(
|
|
|
1005
1005
|
config: boolean | SessionReplayOptions | undefined,
|
|
1006
1006
|
tracking: { endpoint?: string; publicKey?: string } = {},
|
|
1007
1007
|
): SessionReplayOptions | null {
|
|
1008
|
-
const
|
|
1009
|
-
const
|
|
1008
|
+
const env = (import.meta.env as Record<string, string | undefined>) ?? {};
|
|
1009
|
+
const publicKey =
|
|
1010
|
+
tracking.publicKey ||
|
|
1011
|
+
_agentNativeAnalyticsPublicKey ||
|
|
1012
|
+
env.VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY;
|
|
1013
|
+
const trackingEndpoint =
|
|
1014
|
+
tracking.endpoint ||
|
|
1015
|
+
_agentNativeAnalyticsEndpoint ||
|
|
1016
|
+
env.VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT ||
|
|
1017
|
+
(publicKey ? AGENT_NATIVE_ANALYTICS_DEFAULT_ENDPOINT : undefined);
|
|
1010
1018
|
const endpoint = trackingEndpoint
|
|
1011
1019
|
? replayEndpointFromTrackingEndpoint(trackingEndpoint)
|
|
1012
1020
|
: undefined;
|
|
@@ -1034,7 +1042,13 @@ function configuredSessionReplayOptions(
|
|
|
1034
1042
|
if (config.enabled === false) return null;
|
|
1035
1043
|
return withTrackingDefaults(config);
|
|
1036
1044
|
}
|
|
1037
|
-
|
|
1045
|
+
const autoEnabledByAnalyticsKey =
|
|
1046
|
+
!!publicKey &&
|
|
1047
|
+
(typeof window === "undefined" ||
|
|
1048
|
+
!isLocalAnalyticsHostname(window.location.hostname));
|
|
1049
|
+
return sessionReplayEnabledFromEnv() || autoEnabledByAnalyticsKey
|
|
1050
|
+
? withTrackingDefaults({})
|
|
1051
|
+
: null;
|
|
1038
1052
|
}
|
|
1039
1053
|
|
|
1040
1054
|
function replayExtraPropertiesWithDefaults(
|
|
@@ -121,6 +121,7 @@ export function useIsDark(): boolean {
|
|
|
121
121
|
*/
|
|
122
122
|
export const KitConfigContext = createContext<{
|
|
123
123
|
skeleton?: boolean;
|
|
124
|
+
flushFrame?: boolean;
|
|
124
125
|
sketch?: number;
|
|
125
126
|
theme?: "light" | "dark";
|
|
126
127
|
style?: "sketchy" | "clean";
|
|
@@ -195,6 +196,7 @@ export function Screen({
|
|
|
195
196
|
const isSkeleton = skeleton || Boolean(cfg.skeleton);
|
|
196
197
|
const wfStyle = cfg.style ?? "sketchy";
|
|
197
198
|
const wfTheme = theme ?? cfg.theme ?? "light";
|
|
199
|
+
const effectivePad = cfg.flushFrame ? 0 : pad;
|
|
198
200
|
void sketch;
|
|
199
201
|
return (
|
|
200
202
|
<div
|
|
@@ -218,7 +220,7 @@ export function Screen({
|
|
|
218
220
|
lineHeight: 1.25,
|
|
219
221
|
display: "flex",
|
|
220
222
|
flexDirection: "column",
|
|
221
|
-
padding:
|
|
223
|
+
padding: effectivePad,
|
|
222
224
|
boxSizing: "border-box",
|
|
223
225
|
overflow: "hidden",
|
|
224
226
|
...style,
|
|
@@ -414,7 +414,12 @@ function KitArtboard({
|
|
|
414
414
|
caption={data.caption}
|
|
415
415
|
render={({ theme, style }) => (
|
|
416
416
|
<KitConfigContext.Provider
|
|
417
|
-
value={{
|
|
417
|
+
value={{
|
|
418
|
+
skeleton: data.skeleton,
|
|
419
|
+
flushFrame: !showFrame,
|
|
420
|
+
theme,
|
|
421
|
+
style,
|
|
422
|
+
}}
|
|
418
423
|
>
|
|
419
424
|
{renderKitScreen(data.screen ?? [])}
|
|
420
425
|
</KitConfigContext.Provider>
|
|
@@ -13,14 +13,6 @@ const LARGE_FILE_THRESHOLD_BYTES = 30 * 1024 * 1024;
|
|
|
13
13
|
const UPLOAD_TIMEOUT_MS = 120_000;
|
|
14
14
|
const SMALL_FILE_RETRY_DELAYS_MS = [600, 1800];
|
|
15
15
|
|
|
16
|
-
function enabledFlag(value: unknown): boolean {
|
|
17
|
-
return /^(true|1|yes|on)$/i.test(String(value || "").trim());
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function stableUrlOptInEnabled(): boolean {
|
|
21
|
-
return enabledFlag(process.env.CLIPS_STABLE_URL_OPTIN);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
16
|
function builderUploadHost(): string {
|
|
25
17
|
return (
|
|
26
18
|
process.env.BUILDER_APP_HOST ||
|
|
@@ -52,12 +44,9 @@ function fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {
|
|
|
52
44
|
);
|
|
53
45
|
}
|
|
54
46
|
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
url.searchParams.set("
|
|
58
|
-
if (stableUrlOptInEnabled()) {
|
|
59
|
-
url.searchParams.set("stableUrl", "true");
|
|
60
|
-
}
|
|
47
|
+
function setStableUrlQueryParam(url: URL): void {
|
|
48
|
+
// Stable URLs let Builder compress asynchronously without changing the media URL.
|
|
49
|
+
url.searchParams.set("stableUrl", "true");
|
|
61
50
|
}
|
|
62
51
|
|
|
63
52
|
function setRecordAssetQueryParam(
|
|
@@ -121,7 +110,7 @@ async function uploadLargeFileViaSignedUrl(
|
|
|
121
110
|
assetId,
|
|
122
111
|
input.filename,
|
|
123
112
|
{
|
|
124
|
-
|
|
113
|
+
stableUrl: input.stableUrl,
|
|
125
114
|
recordAsset: input.recordAsset,
|
|
126
115
|
},
|
|
127
116
|
);
|
|
@@ -177,12 +166,12 @@ async function completeBuilderUpload(
|
|
|
177
166
|
privateKey: string,
|
|
178
167
|
assetId: string,
|
|
179
168
|
filename: string | undefined,
|
|
180
|
-
options?: {
|
|
169
|
+
options?: { stableUrl?: boolean; recordAsset?: boolean },
|
|
181
170
|
): Promise<{ url: string; id?: string }> {
|
|
182
171
|
const host = builderUploadHost();
|
|
183
172
|
const url = new URL("/api/v1/upload/complete", host);
|
|
184
|
-
if (options?.
|
|
185
|
-
|
|
173
|
+
if (options?.stableUrl) {
|
|
174
|
+
setStableUrlQueryParam(url);
|
|
186
175
|
}
|
|
187
176
|
setRecordAssetQueryParam(url, options?.recordAsset);
|
|
188
177
|
const res = await fetchWithTimeout(url.toString(), {
|
|
@@ -287,8 +276,8 @@ export const builderFileUploadProvider: FileUploadProvider = {
|
|
|
287
276
|
|
|
288
277
|
const url = new URL("/api/v1/upload", builderUploadHost());
|
|
289
278
|
if (filename) url.searchParams.set("name", filename);
|
|
290
|
-
if (input.
|
|
291
|
-
|
|
279
|
+
if (input.stableUrl) {
|
|
280
|
+
setStableUrlQueryParam(url);
|
|
292
281
|
}
|
|
293
282
|
setRecordAssetQueryParam(url, input.recordAsset);
|
|
294
283
|
|
|
@@ -429,9 +418,7 @@ export const builderFileUploadProvider: FileUploadProvider = {
|
|
|
429
418
|
assetId,
|
|
430
419
|
filename,
|
|
431
420
|
{
|
|
432
|
-
|
|
433
|
-
options?.skipCompressionWait ||
|
|
434
|
-
session.meta.skipCompressionWait === true,
|
|
421
|
+
stableUrl: options?.stableUrl || session.meta.stableUrl === true,
|
|
435
422
|
recordAsset:
|
|
436
423
|
options?.recordAsset ??
|
|
437
424
|
(session.meta.recordAsset === false ? false : undefined),
|
|
@@ -16,8 +16,8 @@ export interface FileUploadInput {
|
|
|
16
16
|
mimeType?: string;
|
|
17
17
|
/** Optional owner email for per-user scoping in fallback storage. */
|
|
18
18
|
ownerEmail?: string;
|
|
19
|
-
/** Builder.io upload hint: return
|
|
20
|
-
|
|
19
|
+
/** Builder.io upload hint: return one stable URL while compression finishes asynchronously. */
|
|
20
|
+
stableUrl?: boolean;
|
|
21
21
|
/** Builder.io upload hint: set false for internal artifacts that should not appear in the asset library. */
|
|
22
22
|
recordAsset?: boolean;
|
|
23
23
|
}
|
|
@@ -81,7 +81,7 @@ export interface FileUploadProvider {
|
|
|
81
81
|
completeSession(
|
|
82
82
|
session: ResumableUploadSession,
|
|
83
83
|
filename: string,
|
|
84
|
-
options?: {
|
|
84
|
+
options?: { stableUrl?: boolean; recordAsset?: boolean },
|
|
85
85
|
): Promise<string>;
|
|
86
86
|
};
|
|
87
87
|
}
|
|
@@ -1007,6 +1007,13 @@
|
|
|
1007
1007
|
min-height: 100%;
|
|
1008
1008
|
}
|
|
1009
1009
|
|
|
1010
|
+
.plan-html-frame[data-frame="hide"]:not([data-render-mode="design"])
|
|
1011
|
+
> .plan-html-frame-content
|
|
1012
|
+
> :first-child {
|
|
1013
|
+
margin: 0 !important;
|
|
1014
|
+
padding: 0 !important;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1010
1017
|
.plan-html-frame[data-prototype-live="true"] {
|
|
1011
1018
|
overflow: auto;
|
|
1012
1019
|
}
|
|
@@ -106,12 +106,17 @@ agent answers about browser recordings in the Analytics template.
|
|
|
106
106
|
|
|
107
107
|
## Capture Defaults
|
|
108
108
|
|
|
109
|
-
- Replay is
|
|
110
|
-
|
|
109
|
+
- Replay is on by default for signed-in hosted users when
|
|
110
|
+
`VITE_AGENT_NATIVE_ANALYTICS_PUBLIC_KEY` or `configureTracking({ key })` is
|
|
111
|
+
present. The default sample rate is 100% of eligible sessions.
|
|
112
|
+
- Replay remains off when no first-party analytics key is configured, and it is
|
|
113
|
+
not auto-enabled on localhost/local dev. Consumers can still enable replay
|
|
114
|
+
directly with
|
|
111
115
|
`configureTracking({ key, endpoint, sessionReplay: { enabled: true } })`.
|
|
116
|
+
- Apps can opt out with `configureTracking({ sessionReplay: false })`.
|
|
112
117
|
- Agent Native templates already call `configureTracking()` in their roots;
|
|
113
|
-
hosted template deployments
|
|
114
|
-
vars on the recorded site.
|
|
118
|
+
hosted template deployments only need the normal Agent Native Analytics
|
|
119
|
+
Vite/Netlify env vars on the recorded site.
|
|
115
120
|
- Inputs are masked by default. Page text is visible unless marked with
|
|
116
121
|
`.an-mask` or `data-an-mask`.
|
|
117
122
|
- Use `.an-block`, `.an-ignore`, `data-an-block`, or `data-an-ignore` for
|
|
@@ -155,6 +155,24 @@ export function formatMetricValue(
|
|
|
155
155
|
: String(raw ?? "-");
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
function isNumericLikeValue(value: unknown): boolean {
|
|
159
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
160
|
+
return (
|
|
161
|
+
typeof value === "string" &&
|
|
162
|
+
value.trim() !== "" &&
|
|
163
|
+
Number.isFinite(Number(value))
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function detectMetricValueColumn(
|
|
168
|
+
row: Record<string, unknown>,
|
|
169
|
+
configuredKey?: string,
|
|
170
|
+
): string {
|
|
171
|
+
const cols = Object.keys(row);
|
|
172
|
+
if (configuredKey && cols.includes(configuredKey)) return configuredKey;
|
|
173
|
+
return cols.find((key) => isNumericLikeValue(row[key])) || cols[0] || "";
|
|
174
|
+
}
|
|
175
|
+
|
|
158
176
|
function parsePrometheusSeriesLabel(label: string): {
|
|
159
177
|
metric: string;
|
|
160
178
|
labels: Record<string, string>;
|
|
@@ -804,7 +822,7 @@ function detectKeys(
|
|
|
804
822
|
if (yKeys.length === 0) {
|
|
805
823
|
for (const c of cols) {
|
|
806
824
|
if (c === xKey) continue;
|
|
807
|
-
if (
|
|
825
|
+
if (isNumericLikeValue(sample[c])) yKeys.push(c);
|
|
808
826
|
}
|
|
809
827
|
}
|
|
810
828
|
if (yKeys.length === 0 && cols.length > 1) {
|
|
@@ -1120,14 +1138,10 @@ function MetricRenderer({
|
|
|
1120
1138
|
panel: SqlPanel;
|
|
1121
1139
|
}) {
|
|
1122
1140
|
const row = rows[0];
|
|
1123
|
-
const
|
|
1124
|
-
const valueCol =
|
|
1125
|
-
panel.config?.yKey ||
|
|
1126
|
-
cols.find((c) => typeof row[c] === "number") ||
|
|
1127
|
-
cols[0];
|
|
1141
|
+
const valueCol = detectMetricValueColumn(row, panel.config?.yKey);
|
|
1128
1142
|
|
|
1129
1143
|
let raw: unknown;
|
|
1130
|
-
if (rows.length > 1 &&
|
|
1144
|
+
if (rows.length > 1 && isNumericLikeValue(row[valueCol])) {
|
|
1131
1145
|
raw = rows.reduce((sum, r) => sum + (Number(r[valueCol]) || 0), 0);
|
|
1132
1146
|
} else {
|
|
1133
1147
|
raw = row[valueCol];
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
appBasePath,
|
|
3
|
+
installRouteChunkRecovery,
|
|
4
|
+
} from "@agent-native/core/client";
|
|
2
5
|
import { hydrateRoot } from "react-dom/client";
|
|
3
6
|
import { HydratedRouter } from "react-router/dom";
|
|
4
7
|
|
|
8
|
+
installRouteChunkRecovery();
|
|
9
|
+
|
|
5
10
|
const basePath = appBasePath();
|
|
6
11
|
const pathname = window.location.pathname;
|
|
7
12
|
const routerBasePath =
|
|
@@ -596,7 +596,7 @@ export default defineAction({
|
|
|
596
596
|
typeof resumableSession.meta.filename === "string"
|
|
597
597
|
? resumableSession.meta.filename
|
|
598
598
|
: "",
|
|
599
|
-
{
|
|
599
|
+
{ stableUrl: true, recordAsset: false },
|
|
600
600
|
);
|
|
601
601
|
debugLog("[finalize] resumable upload completed", { id, videoUrl });
|
|
602
602
|
try {
|
|
@@ -966,7 +966,7 @@ export default defineAction({
|
|
|
966
966
|
filename: `${id}.${videoFormat}`,
|
|
967
967
|
mimeType,
|
|
968
968
|
ownerEmail,
|
|
969
|
-
|
|
969
|
+
stableUrl: true,
|
|
970
970
|
recordAsset: false,
|
|
971
971
|
});
|
|
972
972
|
} catch (err) {
|