@agent-native/core 0.90.9 → 0.90.11
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 +18 -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/durable-background.ts +5 -5
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +40 -8
- package/corpus/core/src/agent/engine/anthropic-engine.ts +25 -7
- package/corpus/core/src/agent/engine/output-tokens.ts +94 -0
- package/corpus/core/src/agent/production-agent.ts +46 -7
- package/corpus/core/src/agent/types.ts +3 -2
- 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/db/client.ts +12 -9
- package/corpus/core/src/file-upload/builder.ts +10 -23
- package/corpus/core/src/file-upload/types.ts +3 -3
- package/corpus/core/src/shared/reasoning-effort.ts +23 -0
- 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/actions/regenerate-chapters.ts +7 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +15 -5
- package/corpus/templates/clips/app/routes/download.tsx +12 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-07-07-auto-generated-chapter-requests-now-open-the-matching-agent-.md +6 -0
- 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/changelog/2026-07-07-the-clips-desktop-download-page-now-uses-the-agent-native-ap.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/durable-background.d.ts +1 -1
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +5 -3
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +24 -4
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +13 -3
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/output-tokens.d.ts +27 -0
- package/dist/agent/engine/output-tokens.d.ts.map +1 -1
- package/dist/agent/engine/output-tokens.js +70 -0
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +41 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +3 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.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/db/client.d.ts.map +1 -1
- package/dist/db/client.js +12 -7
- package/dist/db/client.js.map +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/secrets/routes.d.ts +6 -6
- package/dist/shared/reasoning-effort.d.ts +1 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +18 -0
- package/dist/shared/reasoning-effort.js.map +1 -1
- 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
|
@@ -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>
|
|
@@ -856,15 +856,18 @@ export function isBackgroundFunctionPoolContext(): boolean {
|
|
|
856
856
|
) {
|
|
857
857
|
return true;
|
|
858
858
|
}
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
//
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
859
|
+
// NOTE: we deliberately do NOT trust `__AGENT_NATIVE_BACKGROUND_RUNTIME_EXPECTED__`
|
|
860
|
+
// here. That flag is set from the dispatch MARKER (which URL the foreground
|
|
861
|
+
// targeted), not from proof the request actually LANDED on a background
|
|
862
|
+
// function. A worker dispatched toward `-background` but routed onto the ~60s
|
|
863
|
+
// synchronous function would otherwise take the 8-connection background pool
|
|
864
|
+
// while running as one of MANY warm sync-function instances — multiplying
|
|
865
|
+
// Neon connections and exhausting the pooled endpoint ("connection
|
|
866
|
+
// terminated" / statement timeouts / failed heartbeat writes → stale runs).
|
|
867
|
+
// The genuine `-background` function sets `__AGENT_NATIVE_BACKGROUND_RUNTIME__`
|
|
868
|
+
// as its first cold-start statement, so a real background worker still gets
|
|
869
|
+
// the larger pool via the check above. Mirrors the same proof-of-landing
|
|
870
|
+
// tightening applied to `shouldUseBackgroundFunctionTimeoutForWorker`.
|
|
868
871
|
const lambdaName = process.env.AWS_LAMBDA_FUNCTION_NAME;
|
|
869
872
|
if (
|
|
870
873
|
typeof lambdaName === "string" &&
|
|
@@ -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
|
}
|
|
@@ -98,6 +98,29 @@ export function reasoningEffortLabel(effort: ReasoningEffort | undefined) {
|
|
|
98
98
|
return REASONING_EFFORT_LABELS[effort ?? "auto"];
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* One tier down from each effort, stopping at "minimal" — "none"/"auto"
|
|
103
|
+
* (not really "tiers") and "minimal" itself are left unchanged. Used by the
|
|
104
|
+
* empty-final-response retry so a retried turn asks for meaningfully less
|
|
105
|
+
* reasoning instead of repeating the exact request that came back empty.
|
|
106
|
+
*/
|
|
107
|
+
const REASONING_EFFORT_STEP_DOWN: Partial<
|
|
108
|
+
Record<ReasoningEffort, ReasoningEffort>
|
|
109
|
+
> = {
|
|
110
|
+
max: "xhigh",
|
|
111
|
+
xhigh: "high",
|
|
112
|
+
high: "medium",
|
|
113
|
+
medium: "low",
|
|
114
|
+
low: "minimal",
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export function stepDownReasoningEffort(
|
|
118
|
+
effort: ReasoningEffort | undefined,
|
|
119
|
+
): ReasoningEffort | undefined {
|
|
120
|
+
if (!effort) return effort;
|
|
121
|
+
return REASONING_EFFORT_STEP_DOWN[effort] ?? effort;
|
|
122
|
+
}
|
|
123
|
+
|
|
101
124
|
function isGPTReasoningModel(model: string) {
|
|
102
125
|
return /^gpt-5/.test(model) || /^o\d/.test(model);
|
|
103
126
|
}
|
|
@@ -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) {
|
|
@@ -23,6 +23,12 @@ export default defineAction({
|
|
|
23
23
|
"Ask the agent to generate chapters for this recording based on its transcript (and the full video when Include full video is enabled). The agent identifies topic transitions and calls set-chapters.",
|
|
24
24
|
schema: z.object({
|
|
25
25
|
recordingId: z.string().describe("Recording ID"),
|
|
26
|
+
openInChat: z
|
|
27
|
+
.boolean()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe(
|
|
30
|
+
"When true, focus the queued generation request in the agent chat instead of keeping it hidden.",
|
|
31
|
+
),
|
|
26
32
|
}),
|
|
27
33
|
run: async (args) => {
|
|
28
34
|
await assertAccess("recording", args.recordingId, "editor");
|
|
@@ -57,6 +63,7 @@ export default defineAction({
|
|
|
57
63
|
segmentsJson: transcript?.segmentsJson ?? "[]",
|
|
58
64
|
transcriptText: transcript?.fullText ?? "",
|
|
59
65
|
includeFullVideoInAi,
|
|
66
|
+
openInChat: args.openInChat === true,
|
|
60
67
|
message: withFullVideoAiInstructions(
|
|
61
68
|
baseMessage,
|
|
62
69
|
args.recordingId,
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
agentNativePath,
|
|
16
16
|
callAction,
|
|
17
17
|
sendToAgentChat,
|
|
18
|
+
type AgentChatMessage,
|
|
18
19
|
} from "@agent-native/core/client";
|
|
19
20
|
import { fullVideoAiModelSelection } from "@shared/clips-ai-prefs";
|
|
20
21
|
import { useEffect, useRef } from "react";
|
|
@@ -55,6 +56,7 @@ interface AiRequest {
|
|
|
55
56
|
thresholdMs?: number;
|
|
56
57
|
message?: string;
|
|
57
58
|
includeFullVideoInAi?: boolean;
|
|
59
|
+
openInChat?: boolean;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const DISPATCHABLE_REQUESTS = new Set([
|
|
@@ -201,25 +203,33 @@ function buildRequestContext(rec: RecordingSummary, request: AiRequest) {
|
|
|
201
203
|
};
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
function
|
|
206
|
+
export function buildAiRequestChatOptions(
|
|
207
|
+
rec: RecordingSummary,
|
|
208
|
+
request: AiRequest,
|
|
209
|
+
): AgentChatMessage {
|
|
205
210
|
const includeFullVideo = request.includeFullVideoInAi === true;
|
|
206
211
|
const gemini = includeFullVideo ? fullVideoAiModelSelection() : null;
|
|
207
|
-
|
|
212
|
+
const openInChat = request.openInChat === true;
|
|
213
|
+
return {
|
|
208
214
|
message:
|
|
209
215
|
request.message ??
|
|
210
216
|
`Handle queued ${request.kind} work for recording ${rec.id}.`,
|
|
211
217
|
context: JSON.stringify(buildRequestContext(rec, request)),
|
|
212
218
|
submit: true,
|
|
213
|
-
openSidebar: false,
|
|
219
|
+
openSidebar: openInChat ? true : false,
|
|
214
220
|
newTab: true,
|
|
215
|
-
background:
|
|
221
|
+
background: !openInChat,
|
|
216
222
|
...(gemini
|
|
217
223
|
? {
|
|
218
224
|
engine: gemini.engine,
|
|
219
225
|
model: gemini.model,
|
|
220
226
|
}
|
|
221
227
|
: {}),
|
|
222
|
-
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function dispatchAiRequest(rec: RecordingSummary, request: AiRequest) {
|
|
232
|
+
sendToAgentChat(buildAiRequestChatOptions(rec, request));
|
|
223
233
|
}
|
|
224
234
|
|
|
225
235
|
function parseJsonArray(raw: string | undefined): unknown[] {
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
IconBrandApple,
|
|
5
5
|
IconBrandWindows,
|
|
6
6
|
IconExternalLink,
|
|
7
|
-
IconPlayerRecord,
|
|
8
7
|
} from "@tabler/icons-react";
|
|
9
8
|
import { useEffect, useState } from "react";
|
|
10
9
|
|
|
@@ -201,9 +200,18 @@ export default function DownloadPage() {
|
|
|
201
200
|
href={appPath("/")}
|
|
202
201
|
className="flex items-center gap-2 font-semibold"
|
|
203
202
|
>
|
|
204
|
-
<
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
<img
|
|
204
|
+
src={appPath("/agent-native-icon-light.svg")}
|
|
205
|
+
alt=""
|
|
206
|
+
aria-hidden="true"
|
|
207
|
+
className="block h-4 w-auto shrink-0 dark:hidden"
|
|
208
|
+
/>
|
|
209
|
+
<img
|
|
210
|
+
src={appPath("/agent-native-icon-dark.svg")}
|
|
211
|
+
alt=""
|
|
212
|
+
aria-hidden="true"
|
|
213
|
+
className="hidden h-4 w-auto shrink-0 dark:block"
|
|
214
|
+
/>
|
|
207
215
|
<span>Clips</span>
|
|
208
216
|
</a>
|
|
209
217
|
<a
|