@agent-native/core 0.84.56 → 0.84.57
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 +6 -0
- package/corpus/core/docs/content/locales/ar-SA/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/hi-IN/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +2 -0
- package/corpus/core/docs/content/template-analytics.mdx +2 -0
- package/corpus/core/docs/content/template-clips.mdx +22 -10
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +8 -0
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/create-session-replay-agent-link.ts +31 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +20 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +65 -3
- package/corpus/templates/analytics/changelog/2026-07-02-session-replays-can-be-copied-as-temporary-private-links-for-agents.md +6 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +78 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +313 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +198 -3
- package/corpus/templates/analytics/server/routes/[...page].get.ts +104 -1
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-context.json.get.ts +48 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-events.json.get.ts +63 -0
- package/corpus/templates/analytics/shared/session-replay-agent-access.ts +10 -0
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +14 -8
- package/corpus/templates/clips/AGENTS.md +3 -2
- package/corpus/templates/clips/actions/create-recording-agent-link.ts +90 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -46
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -3
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -1
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +100 -46
- package/corpus/templates/clips/changelog/2026-07-02-private-recordings-can-be-shared-with-agents-through-temporary-links-without-making-them-public.md +6 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +26 -13
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/agent-frame.jpg.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +2 -1
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +7 -2
- package/corpus/templates/clips/shared/agent-context.ts +5 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/docs/content/locales/ar-SA/template-analytics.mdx +2 -0
- package/docs/content/locales/ar-SA/template-clips.mdx +2 -0
- package/docs/content/locales/de-DE/template-analytics.mdx +2 -0
- package/docs/content/locales/de-DE/template-clips.mdx +2 -0
- package/docs/content/locales/es-ES/template-analytics.mdx +2 -0
- package/docs/content/locales/es-ES/template-clips.mdx +2 -0
- package/docs/content/locales/fr-FR/template-analytics.mdx +2 -0
- package/docs/content/locales/fr-FR/template-clips.mdx +2 -0
- package/docs/content/locales/hi-IN/template-analytics.mdx +2 -0
- package/docs/content/locales/hi-IN/template-clips.mdx +2 -0
- package/docs/content/locales/ja-JP/template-analytics.mdx +2 -0
- package/docs/content/locales/ja-JP/template-clips.mdx +2 -0
- package/docs/content/locales/ko-KR/template-analytics.mdx +2 -0
- package/docs/content/locales/ko-KR/template-clips.mdx +2 -0
- package/docs/content/locales/pt-BR/template-analytics.mdx +2 -0
- package/docs/content/locales/pt-BR/template-clips.mdx +2 -0
- package/docs/content/locales/zh-CN/template-analytics.mdx +2 -0
- package/docs/content/locales/zh-CN/template-clips.mdx +2 -0
- package/docs/content/locales/zh-TW/template-analytics.mdx +2 -0
- package/docs/content/locales/zh-TW/template-clips.mdx +2 -0
- package/docs/content/template-analytics.mdx +2 -0
- package/docs/content/template-clips.mdx +22 -10
- package/docs/content/tracking.mdx +2 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
getRequestUserEmail,
|
|
13
13
|
signShortLivedToken,
|
|
14
|
+
verifyShortLivedToken,
|
|
14
15
|
} from "@agent-native/core/server";
|
|
15
16
|
import { resolveAccess } from "@agent-native/core/sharing";
|
|
16
17
|
import {
|
|
@@ -32,7 +33,12 @@ import {
|
|
|
32
33
|
useState,
|
|
33
34
|
type ReactNode,
|
|
34
35
|
} from "react";
|
|
35
|
-
import
|
|
36
|
+
import {
|
|
37
|
+
data,
|
|
38
|
+
type HeadersArgs,
|
|
39
|
+
type LoaderFunctionArgs,
|
|
40
|
+
type MetaFunction,
|
|
41
|
+
} from "react-router";
|
|
36
42
|
import { useLoaderData, useNavigate, useParams } from "react-router";
|
|
37
43
|
|
|
38
44
|
import { CaptureInstallButton } from "@/components/capture-install-options";
|
|
@@ -65,7 +71,12 @@ import { parsePlaybackSpeed } from "@/lib/playback-speed";
|
|
|
65
71
|
import { isStorageSetupFailureReason } from "@/lib/storage-failures";
|
|
66
72
|
|
|
67
73
|
import { getDb, schema } from "../../server/db";
|
|
68
|
-
import {
|
|
74
|
+
import { CLIPS_AGENT_ACCESS_PARAM } from "../../server/lib/public-agent-context";
|
|
75
|
+
import {
|
|
76
|
+
agentAccessTokenResourceId,
|
|
77
|
+
buildAgentApiUrls,
|
|
78
|
+
safeJsonForHtml,
|
|
79
|
+
} from "../../shared/agent-context";
|
|
69
80
|
import {
|
|
70
81
|
isLoomEmbedBackedRecording,
|
|
71
82
|
isLoomRecordingSource,
|
|
@@ -99,6 +110,34 @@ type SharePageLoaderData = {
|
|
|
99
110
|
shareUrl: string | null;
|
|
100
111
|
};
|
|
101
112
|
|
|
113
|
+
const PRIVATE_AGENT_SHARE_HEADERS = {
|
|
114
|
+
"Cache-Control": "private, max-age=0, no-store",
|
|
115
|
+
"Referrer-Policy": "no-referrer",
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
function emptyLoaderData(url: URL): SharePageLoaderData {
|
|
119
|
+
return {
|
|
120
|
+
recording: null,
|
|
121
|
+
agentContextUrl: null,
|
|
122
|
+
origin: url.origin,
|
|
123
|
+
shareUrl: null,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function shareLoaderData(
|
|
128
|
+
payload: SharePageLoaderData,
|
|
129
|
+
privateAgentAccess = false,
|
|
130
|
+
) {
|
|
131
|
+
if (!privateAgentAccess) return payload;
|
|
132
|
+
return data(payload, {
|
|
133
|
+
headers: PRIVATE_AGENT_SHARE_HEADERS,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function headers({ loaderHeaders }: HeadersArgs) {
|
|
138
|
+
return loaderHeaders;
|
|
139
|
+
}
|
|
140
|
+
|
|
102
141
|
function failureDetail(reason: string | null | undefined): string | null {
|
|
103
142
|
const trimmed = reason?.trim();
|
|
104
143
|
if (!trimmed) return null;
|
|
@@ -132,13 +171,7 @@ function shouldShowGeneratedTitleSkeleton(
|
|
|
132
171
|
|
|
133
172
|
export async function loader({ params, url }: LoaderFunctionArgs) {
|
|
134
173
|
const id = params.shareId;
|
|
135
|
-
if (!id)
|
|
136
|
-
return {
|
|
137
|
-
recording: null,
|
|
138
|
-
agentContextUrl: null,
|
|
139
|
-
origin: url.origin,
|
|
140
|
-
shareUrl: null,
|
|
141
|
-
};
|
|
174
|
+
if (!id) return emptyLoaderData(url);
|
|
142
175
|
|
|
143
176
|
const [rec] = await getDb()
|
|
144
177
|
.select({
|
|
@@ -151,6 +184,7 @@ export async function loader({ params, url }: LoaderFunctionArgs) {
|
|
|
151
184
|
status: schema.recordings.status,
|
|
152
185
|
ownerEmail: schema.recordings.ownerEmail,
|
|
153
186
|
password: schema.recordings.password,
|
|
187
|
+
expiresAt: schema.recordings.expiresAt,
|
|
154
188
|
archivedAt: schema.recordings.archivedAt,
|
|
155
189
|
trashedAt: schema.recordings.trashedAt,
|
|
156
190
|
})
|
|
@@ -158,24 +192,25 @@ export async function loader({ params, url }: LoaderFunctionArgs) {
|
|
|
158
192
|
.where(eq(schema.recordings.id, id))
|
|
159
193
|
.limit(1);
|
|
160
194
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
195
|
+
const agentAccessToken = url.searchParams.get(CLIPS_AGENT_ACCESS_PARAM) ?? "";
|
|
196
|
+
const hasAgentAccessToken = Boolean(agentAccessToken);
|
|
197
|
+
const tokenGrantsAgentAccess = agentAccessToken
|
|
198
|
+
? verifyShortLivedToken(agentAccessToken, agentAccessTokenResourceId(id)).ok
|
|
199
|
+
: false;
|
|
200
|
+
|
|
201
|
+
if (!rec) return shareLoaderData(emptyLoaderData(url), hasAgentAccessToken);
|
|
202
|
+
|
|
203
|
+
if (rec.expiresAt) {
|
|
204
|
+
const expires = new Date(rec.expiresAt).getTime();
|
|
205
|
+
if (Number.isFinite(expires) && expires < Date.now()) {
|
|
206
|
+
return shareLoaderData(emptyLoaderData(url), hasAgentAccessToken);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
168
209
|
|
|
169
|
-
if (rec.visibility !== "public") {
|
|
210
|
+
if (rec.visibility !== "public" && !tokenGrantsAgentAccess) {
|
|
170
211
|
const userEmail = getRequestUserEmail();
|
|
171
212
|
const access = userEmail ? await resolveAccess("recording", id) : null;
|
|
172
|
-
if (!access)
|
|
173
|
-
return {
|
|
174
|
-
recording: null,
|
|
175
|
-
agentContextUrl: null,
|
|
176
|
-
origin: url.origin,
|
|
177
|
-
shareUrl: null,
|
|
178
|
-
};
|
|
213
|
+
if (!access) return emptyLoaderData(url);
|
|
179
214
|
}
|
|
180
215
|
|
|
181
216
|
const recording: SharePageMetaRecording = {
|
|
@@ -190,29 +225,37 @@ export async function loader({ params, url }: LoaderFunctionArgs) {
|
|
|
190
225
|
trashedAt: rec.trashedAt,
|
|
191
226
|
};
|
|
192
227
|
const canExposeAgentContext =
|
|
193
|
-
rec.visibility === "public"
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
228
|
+
(rec.visibility === "public" || tokenGrantsAgentAccess) &&
|
|
229
|
+
!rec.archivedAt &&
|
|
230
|
+
!rec.trashedAt;
|
|
231
|
+
const token = tokenGrantsAgentAccess
|
|
232
|
+
? agentAccessToken
|
|
233
|
+
: canExposeAgentContext &&
|
|
234
|
+
rec.password &&
|
|
235
|
+
getRequestUserEmail() === rec.ownerEmail
|
|
236
|
+
? signShortLivedToken({ resourceId: agentAccessTokenResourceId(id) })
|
|
199
237
|
: undefined;
|
|
200
238
|
const canExposeAnonymousAgentContext = canExposeAgentContext && !rec.password;
|
|
201
239
|
const canExposeOwnerAgentContext = canExposeAgentContext && Boolean(token);
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
240
|
+
return shareLoaderData(
|
|
241
|
+
{
|
|
242
|
+
recording,
|
|
243
|
+
origin: url.origin,
|
|
244
|
+
shareUrl: `${url.origin}${url.pathname}`,
|
|
245
|
+
agentContextUrl:
|
|
246
|
+
canExposeAnonymousAgentContext || canExposeOwnerAgentContext
|
|
247
|
+
? buildAgentApiUrls(id, {
|
|
248
|
+
origin: url.origin,
|
|
249
|
+
basePath:
|
|
250
|
+
process.env.VITE_APP_BASE_PATH ||
|
|
251
|
+
process.env.APP_BASE_PATH ||
|
|
252
|
+
"",
|
|
253
|
+
token,
|
|
254
|
+
}).contextUrl
|
|
255
|
+
: null,
|
|
256
|
+
},
|
|
257
|
+
hasAgentAccessToken || canExposeOwnerAgentContext,
|
|
258
|
+
);
|
|
216
259
|
}
|
|
217
260
|
|
|
218
261
|
export const meta: MetaFunction<typeof loader> = ({ loaderData }) => {
|
|
@@ -273,7 +316,7 @@ function AgentDiscovery({
|
|
|
273
316
|
{t("sharePage.agentReadableContext")}
|
|
274
317
|
</a>
|
|
275
318
|
<script
|
|
276
|
-
type="application/json"
|
|
319
|
+
type="application/agent-native+json"
|
|
277
320
|
id="clips-agent-context"
|
|
278
321
|
dangerouslySetInnerHTML={{ __html: safeJsonForHtml(payload) }}
|
|
279
322
|
/>
|
|
@@ -362,9 +405,17 @@ export default function ShareRoute() {
|
|
|
362
405
|
[],
|
|
363
406
|
);
|
|
364
407
|
const [downloading, setDownloading] = useState(false);
|
|
408
|
+
const agentAccessToken = useMemo(() => {
|
|
409
|
+
if (typeof window === "undefined") return "";
|
|
410
|
+
return (
|
|
411
|
+
new URLSearchParams(window.location.search).get(
|
|
412
|
+
CLIPS_AGENT_ACCESS_PARAM,
|
|
413
|
+
) ?? ""
|
|
414
|
+
);
|
|
415
|
+
}, []);
|
|
365
416
|
|
|
366
417
|
const dataQ = useQuery({
|
|
367
|
-
queryKey: ["public-recording", shareId, password],
|
|
418
|
+
queryKey: ["public-recording", shareId, password, agentAccessToken],
|
|
368
419
|
queryFn: async () => {
|
|
369
420
|
const url = new URL(
|
|
370
421
|
`${appBasePath()}/api/public-recording`,
|
|
@@ -372,6 +423,9 @@ export default function ShareRoute() {
|
|
|
372
423
|
);
|
|
373
424
|
url.searchParams.set("id", shareId ?? "");
|
|
374
425
|
if (password) url.searchParams.set("password", password);
|
|
426
|
+
if (agentAccessToken) {
|
|
427
|
+
url.searchParams.set(CLIPS_AGENT_ACCESS_PARAM, agentAccessToken);
|
|
428
|
+
}
|
|
375
429
|
const res = await fetch(url.toString());
|
|
376
430
|
const data = await res.json().catch(() => ({}));
|
|
377
431
|
return { ok: res.ok, status: res.status, data };
|
|
@@ -9,6 +9,7 @@ import { asc, eq } from "drizzle-orm";
|
|
|
9
9
|
import { getRequestURL, setResponseHeader, type H3Event } from "h3";
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
+
agentAccessTokenResourceId,
|
|
12
13
|
buildAgentApiUrls,
|
|
13
14
|
buildRecommendedFrames,
|
|
14
15
|
CLIP_AGENT_CONTEXT_VERSION,
|
|
@@ -53,6 +54,8 @@ export type PublicAgentAccessResult =
|
|
|
53
54
|
| { ok: false; failure: PublicAgentFailure };
|
|
54
55
|
|
|
55
56
|
const DEFAULT_MAX_AGENT_FRAME_MEDIA_BYTES = 200 * 1024 * 1024;
|
|
57
|
+
export const CLIPS_AGENT_ACCESS_PARAM = "agent_access";
|
|
58
|
+
export const CLIPS_AGENT_ACCESS_TTL_SECONDS = 2 * 60 * 60;
|
|
56
59
|
|
|
57
60
|
function sameOwnerEmail(
|
|
58
61
|
a: string | null | undefined,
|
|
@@ -207,8 +210,20 @@ export async function loadPublicAgentAccess(
|
|
|
207
210
|
const viewerIsOwner = Boolean(
|
|
208
211
|
session?.email && sameOwnerEmail(session.email, recording.ownerEmail),
|
|
209
212
|
);
|
|
213
|
+
const suppliedToken = options.token ?? "";
|
|
214
|
+
const tokenAccess = suppliedToken
|
|
215
|
+
? verifyShortLivedToken(
|
|
216
|
+
suppliedToken,
|
|
217
|
+
agentAccessTokenResourceId(recording.id),
|
|
218
|
+
)
|
|
219
|
+
: null;
|
|
220
|
+
const tokenAllowsAgentAccess = Boolean(tokenAccess?.ok);
|
|
210
221
|
|
|
211
|
-
if (
|
|
222
|
+
if (
|
|
223
|
+
recording.visibility !== "public" &&
|
|
224
|
+
!viewerIsOwner &&
|
|
225
|
+
!tokenAllowsAgentAccess
|
|
226
|
+
) {
|
|
212
227
|
return {
|
|
213
228
|
ok: false,
|
|
214
229
|
failure: { status: 404, body: { error: "Not found" } },
|
|
@@ -229,26 +244,22 @@ export async function loadPublicAgentAccess(
|
|
|
229
244
|
}
|
|
230
245
|
|
|
231
246
|
let apiToken: string | null = null;
|
|
247
|
+
if (tokenAllowsAgentAccess) {
|
|
248
|
+
apiToken = suppliedToken;
|
|
249
|
+
}
|
|
232
250
|
if (
|
|
233
251
|
recording.password &&
|
|
234
252
|
recording.visibility === "public" &&
|
|
235
253
|
viewerIsOwner
|
|
236
254
|
) {
|
|
237
|
-
apiToken = signShortLivedToken({
|
|
255
|
+
apiToken = signShortLivedToken({
|
|
256
|
+
resourceId: agentAccessTokenResourceId(recording.id),
|
|
257
|
+
});
|
|
238
258
|
}
|
|
239
259
|
|
|
240
260
|
if (recording.password && !viewerIsOwner) {
|
|
241
|
-
const suppliedToken = options.token ?? "";
|
|
242
261
|
const suppliedPassword = options.password ?? "";
|
|
243
|
-
let allowed =
|
|
244
|
-
|
|
245
|
-
if (suppliedToken) {
|
|
246
|
-
const result = verifyShortLivedToken(suppliedToken, recording.id);
|
|
247
|
-
if (result.ok) {
|
|
248
|
-
allowed = true;
|
|
249
|
-
apiToken = suppliedToken;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
262
|
+
let allowed = tokenAllowsAgentAccess;
|
|
252
263
|
|
|
253
264
|
if (
|
|
254
265
|
!allowed &&
|
|
@@ -256,7 +267,9 @@ export async function loadPublicAgentAccess(
|
|
|
256
267
|
verifySharePassword(suppliedPassword, recording.password)
|
|
257
268
|
) {
|
|
258
269
|
allowed = true;
|
|
259
|
-
apiToken = signShortLivedToken({
|
|
270
|
+
apiToken = signShortLivedToken({
|
|
271
|
+
resourceId: agentAccessTokenResourceId(recording.id),
|
|
272
|
+
});
|
|
260
273
|
}
|
|
261
274
|
|
|
262
275
|
if (!allowed) {
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
loadPublicAgentAccess,
|
|
24
24
|
parseAgentChapters,
|
|
25
25
|
queryString,
|
|
26
|
+
CLIPS_AGENT_ACCESS_PARAM,
|
|
26
27
|
} from "../../lib/public-agent-context.js";
|
|
27
28
|
|
|
28
29
|
export default defineEventHandler(async (event: H3Event) => {
|
|
@@ -32,7 +33,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
32
33
|
const id = queryString(query.id);
|
|
33
34
|
const accessResult = await loadPublicAgentAccess(event, id, {
|
|
34
35
|
password: queryString(query.password),
|
|
35
|
-
token: queryString(query.t),
|
|
36
|
+
token: queryString(query[CLIPS_AGENT_ACCESS_PARAM]) || queryString(query.t),
|
|
36
37
|
});
|
|
37
38
|
|
|
38
39
|
if (!accessResult.ok) {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "h3";
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
+
CLIPS_AGENT_ACCESS_PARAM,
|
|
16
17
|
loadPublicAgentAccess,
|
|
17
18
|
loadRecordingMediaBytes,
|
|
18
19
|
queryString,
|
|
@@ -95,7 +96,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
95
96
|
const id = queryString(query.id);
|
|
96
97
|
const accessResult = await loadPublicAgentAccess(event, id, {
|
|
97
98
|
password: queryString(query.password),
|
|
98
|
-
token: queryString(query.t),
|
|
99
|
+
token: queryString(query[CLIPS_AGENT_ACCESS_PARAM]) || queryString(query.t),
|
|
99
100
|
});
|
|
100
101
|
|
|
101
102
|
if (!accessResult.ok) {
|
|
@@ -16,6 +16,7 @@ import { buildAgentApiUrls } from "../../../shared/agent-context.js";
|
|
|
16
16
|
import { isLoomEmbedBackedRecording } from "../../../shared/loom.js";
|
|
17
17
|
import {
|
|
18
18
|
applyAgentJsonHeaders,
|
|
19
|
+
CLIPS_AGENT_ACCESS_PARAM,
|
|
19
20
|
getServerAppBasePath,
|
|
20
21
|
loadAgentTranscript,
|
|
21
22
|
loadPublicAgentAccess,
|
|
@@ -30,7 +31,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
30
31
|
const id = queryString(query.id);
|
|
31
32
|
const accessResult = await loadPublicAgentAccess(event, id, {
|
|
32
33
|
password: queryString(query.password),
|
|
33
|
-
token: queryString(query.t),
|
|
34
|
+
token: queryString(query[CLIPS_AGENT_ACCESS_PARAM]) || queryString(query.t),
|
|
34
35
|
});
|
|
35
36
|
|
|
36
37
|
if (!accessResult.ok) {
|
|
@@ -26,7 +26,10 @@ import {
|
|
|
26
26
|
type H3Event,
|
|
27
27
|
} from "h3";
|
|
28
28
|
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
agentAccessTokenResourceId,
|
|
31
|
+
buildAgentApiUrls,
|
|
32
|
+
} from "../../../shared/agent-context.js";
|
|
30
33
|
import {
|
|
31
34
|
normalizeTranscriptSegments,
|
|
32
35
|
parseTranscriptSegments,
|
|
@@ -248,7 +251,9 @@ export default defineEventHandler(async (event) => {
|
|
|
248
251
|
rec.visibility === "public" && !rec.archivedAt && !rec.trashedAt;
|
|
249
252
|
const agentToken =
|
|
250
253
|
canExposeAgentContext && rec.password
|
|
251
|
-
? signShortLivedToken({
|
|
254
|
+
? signShortLivedToken({
|
|
255
|
+
resourceId: agentAccessTokenResourceId(recordingId),
|
|
256
|
+
})
|
|
252
257
|
: undefined;
|
|
253
258
|
const agentContextUrl = canExposeAgentContext
|
|
254
259
|
? buildAgentApiUrls(recordingId, {
|
|
@@ -4,6 +4,11 @@ export const CLIP_AGENT_CONTEXT_VERSION = 1;
|
|
|
4
4
|
export const AGENT_CONTEXT_ENDPOINT = "/api/agent-context.json";
|
|
5
5
|
export const AGENT_TRANSCRIPT_ENDPOINT = "/api/agent-transcript.json";
|
|
6
6
|
export const AGENT_FRAME_ENDPOINT = "/api/agent-frame.jpg";
|
|
7
|
+
export const CLIP_AGENT_ACCESS_TOKEN_PREFIX = "clip-agent-context";
|
|
8
|
+
|
|
9
|
+
export function agentAccessTokenResourceId(recordingId: string): string {
|
|
10
|
+
return `${CLIP_AGENT_ACCESS_TOKEN_PREFIX}:${recordingId}`;
|
|
11
|
+
}
|
|
7
12
|
|
|
8
13
|
export interface AgentApiUrls {
|
|
9
14
|
contextUrl: string;
|
|
@@ -49,11 +49,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
49
49
|
error: string;
|
|
50
50
|
states?: undefined;
|
|
51
51
|
} | {
|
|
52
|
+
error?: undefined;
|
|
52
53
|
states: {
|
|
53
54
|
clientId: number;
|
|
54
55
|
state: string;
|
|
55
56
|
}[];
|
|
56
|
-
error?: undefined;
|
|
57
57
|
}>>;
|
|
58
58
|
/**
|
|
59
59
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -64,10 +64,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
64
64
|
error: string;
|
|
65
65
|
users?: undefined;
|
|
66
66
|
} | {
|
|
67
|
+
error?: undefined;
|
|
67
68
|
users: {
|
|
68
69
|
clientId: number;
|
|
69
70
|
lastSeen: number;
|
|
70
71
|
}[];
|
|
71
|
-
error?: undefined;
|
|
72
72
|
}>>;
|
|
73
73
|
//# sourceMappingURL=awareness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;kBAuCa,MAAM;eAAS,MAAM;;GAa1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;;kBAWM,MAAM;kBAAY,MAAM;;GAMvD,CAAC"}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -41,8 +41,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
41
41
|
* Body: { text: string, fieldName?: string, requestSource?: string }
|
|
42
42
|
*/
|
|
43
43
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
44
|
-
ok?: undefined;
|
|
45
44
|
text?: undefined;
|
|
45
|
+
ok?: undefined;
|
|
46
46
|
error: string;
|
|
47
47
|
} | {
|
|
48
48
|
error?: undefined;
|
|
@@ -3,18 +3,18 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
3
3
|
url?: string;
|
|
4
4
|
filename?: string;
|
|
5
5
|
}, {
|
|
6
|
+
id?: undefined;
|
|
6
7
|
error: string;
|
|
7
8
|
configured?: undefined;
|
|
8
9
|
connectPath?: undefined;
|
|
9
10
|
url?: undefined;
|
|
10
|
-
id?: undefined;
|
|
11
11
|
provider?: undefined;
|
|
12
12
|
} | {
|
|
13
|
+
id?: undefined;
|
|
13
14
|
error: string;
|
|
14
15
|
configured: boolean;
|
|
15
16
|
connectPath: string;
|
|
16
17
|
url?: undefined;
|
|
17
|
-
id?: undefined;
|
|
18
18
|
provider?: undefined;
|
|
19
19
|
} | {
|
|
20
20
|
error?: undefined;
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
+
error?: undefined;
|
|
14
15
|
count: number;
|
|
15
16
|
updated?: undefined;
|
|
16
|
-
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
+
error?: undefined;
|
|
19
20
|
count?: undefined;
|
|
20
21
|
updated: number;
|
|
21
|
-
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,9 +26,9 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
+
error?: undefined;
|
|
29
30
|
count?: undefined;
|
|
30
31
|
updated?: undefined;
|
|
31
|
-
error?: undefined;
|
|
32
32
|
ok: boolean;
|
|
33
33
|
}>>;
|
|
34
34
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -56,13 +56,13 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
56
56
|
ok?: undefined;
|
|
57
57
|
summary?: undefined;
|
|
58
58
|
spans?: undefined;
|
|
59
|
-
error: any;
|
|
60
59
|
id?: undefined;
|
|
60
|
+
error: any;
|
|
61
61
|
} | {
|
|
62
62
|
error?: undefined;
|
|
63
63
|
summary?: undefined;
|
|
64
64
|
spans?: undefined;
|
|
65
|
-
ok: boolean;
|
|
66
65
|
id?: undefined;
|
|
66
|
+
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -49,8 +49,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
49
49
|
}>;
|
|
50
50
|
/** DELETE /_agent-native/resources/:id — delete a resource */
|
|
51
51
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
52
|
-
ok?: undefined;
|
|
53
52
|
error: string;
|
|
53
|
+
ok?: undefined;
|
|
54
54
|
} | {
|
|
55
55
|
error?: undefined;
|
|
56
56
|
ok: boolean;
|
|
@@ -147,6 +147,8 @@ pnpm dev
|
|
|
147
147
|
|
|
148
148
|
**سطح موصل واسع.** تأتي أحداث BigQuery وGA4 وتحليلات المنتج وCRM والدعم والمجتمع وGitHub/Jira وSEO وأحداث `/track` للطرف الأول من خلال actions التي يمكن للوكيل الاتصال بها.
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### العمل مع الوكيل
|
|
151
153
|
|
|
152
154
|
يعرف الوكيل دائمًا ما تنظر إليه. يتم إدخال حالة الشاشة الحالية في كل رسالة ككتلة `<current-screen>` - فهي تحتوي على العرض النشط، ولوحة المعلومات المفتوحة أو التحليل، وأي عوامل تصفية محددة.
|
|
@@ -131,6 +131,8 @@ API، لذا فإن النماذج التي تقبل النص أو الصور ا
|
|
|
131
131
|
| `/api/agent-transcript.json?id=<recordingId>` | أجزاء النص ذات الطابع الزمني مع `startMs`، `endMs`، والطوابع الزمنية القابلة للقراءة، والنص، وتسميات المصدر الاختيارية |
|
|
132
132
|
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` | إطار JPEG مستخرج من الفيديو بطابع زمني للفيديو الأصلي |
|
|
133
133
|
|
|
134
|
+
Temporary private agent links are also supported: the Share dialog can mint a two-hour `agent_access` URL for any recording the viewer can access. Agents use that token with the share page and JSON APIs, and the clip does not become public.
|
|
135
|
+
|
|
134
136
|
تتبع نقاط النهاية نفس القواعد العامة/كلمة المرور/انتهاء الصلاحية مثل صفحة المشاركة.
|
|
135
137
|
تتطلب المقاطع المحمية بكلمة مرور كلمة المرور مرة واحدة؛ تعود الاستجابات الناجحة
|
|
136
138
|
روابط رمزية قصيرة العمر بحيث لا يحتاج وكلاء المراحل النهائية إلى النص العادي
|
|
@@ -147,6 +147,8 @@ CLI gibt den lokalen Entwickler URL aus. Melden Sie sich bei Google an und öffn
|
|
|
147
147
|
|
|
148
148
|
**Breite Konnektoroberfläche.** BigQuery, GA4, Produktanalyse, CRM, Support, Community, GitHub/Jira, SEO und Erstanbieter-`/track`-Ereignisse kommen alle über actions, das der Agent anrufen kann.
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### Zusammenarbeit mit dem Agenten
|
|
151
153
|
|
|
152
154
|
Der Agent weiß immer, was Sie sehen. Der aktuelle Bildschirmstatus wird als `<current-screen>`-Block in jede Nachricht eingefügt – er enthält die aktive Ansicht, das geöffnete Dashboard oder die geöffnete Analyse und alle ausgewählten Filter.
|
|
@@ -131,6 +131,8 @@ Agent.
|
|
|
131
131
|
| `/api/agent-transcript.json?id=<recordingId>` | Transkriptsegmente mit Zeitstempel mit `startMs`, `endMs`, lesbaren Zeitstempeln, Text und optionalen Quellenbezeichnungen |
|
|
132
132
|
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` | Ein JPEG-Frame, der mit einem Originalvideo-Zeitstempel aus dem Video extrahiert wurde |
|
|
133
133
|
|
|
134
|
+
Temporary private agent links are also supported: the Share dialog can mint a two-hour `agent_access` URL for any recording the viewer can access. Agents use that token with the share page and JSON APIs, and the clip does not become public.
|
|
135
|
+
|
|
134
136
|
Die Endpunkte folgen denselben öffentlichen/Passwort-/Ablaufregeln wie die Freigabeseite.
|
|
135
137
|
Passwortgeschützte Clips erfordern das einmalige Passwort; Erfolgreiche Antworten werden zurückgegeben
|
|
136
138
|
kurzlebige tokenisierte Links, sodass nachgeschaltete Agenten den Klartext nicht benötigen
|
|
@@ -147,6 +147,8 @@ El CLI imprime el desarrollador local URL. Inicia sesión con Google y luego abr
|
|
|
147
147
|
|
|
148
148
|
**Amplia superficie de conector.** BigQuery, GA4, análisis de productos, CRM, soporte, comunidad, GitHub/Jira, SEO y eventos propios `/track` llegan a través de actions al que el agente puede llamar.
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### Trabajar con el agente
|
|
151
153
|
|
|
152
154
|
El agente siempre sabe lo que estás mirando. El estado actual de la pantalla se inyecta en cada mensaje como un bloque `<current-screen>`: contiene la vista activa, el panel o análisis abierto y los filtros seleccionados.
|
|
@@ -131,6 +131,8 @@ agente.
|
|
|
131
131
|
| `/api/agent-transcript.json?id=<recordingId>` | Segmentos de transcripción con marca de tiempo con `startMs`, `endMs`, marcas de tiempo legibles, texto y etiquetas de origen opcionales |
|
|
132
132
|
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` | Un fotograma JPEG extraído del vídeo en una marca de tiempo del vídeo original |
|
|
133
133
|
|
|
134
|
+
Temporary private agent links are also supported: the Share dialog can mint a two-hour `agent_access` URL for any recording the viewer can access. Agents use that token with the share page and JSON APIs, and the clip does not become public.
|
|
135
|
+
|
|
134
136
|
Los puntos finales siguen las mismas reglas de público/contraseña/caducidad que la página para compartir.
|
|
135
137
|
Los clips protegidos con contraseña requieren la contraseña una vez; regresan respuestas exitosas
|
|
136
138
|
Enlaces tokenizados de corta duración para que los agentes posteriores no necesiten el texto sin formato
|
|
@@ -147,6 +147,8 @@ Le CLI imprime le développement local URL. Connectez-vous avec Google, puis ouv
|
|
|
147
147
|
|
|
148
148
|
**Large surface de connecteur.** Les événements BigQuery, GA4, analyses de produits, CRM, support, communauté, GitHub/Jira, SEO et `/track` propriétaires passent tous par actions que l'agent peut appeler.
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### Travailler avec l'agent
|
|
151
153
|
|
|
152
154
|
L'agent sait toujours ce que vous regardez. L'état actuel de l'écran est injecté dans chaque message sous forme de bloc `<current-screen>` : il contient la vue active, le tableau de bord ou l'analyse ouvert et tous les filtres sélectionnés.
|
|
@@ -131,6 +131,8 @@ agent.
|
|
|
131
131
|
| `/api/agent-transcript.json?id=<recordingId>` | Segments de transcription horodatés avec `startMs`, `endMs`, horodatages lisibles, texte et étiquettes de source facultatives |
|
|
132
132
|
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` | Une image JPEG extraite de la vidéo avec un horodatage de la vidéo d'origine |
|
|
133
133
|
|
|
134
|
+
Temporary private agent links are also supported: the Share dialog can mint a two-hour `agent_access` URL for any recording the viewer can access. Agents use that token with the share page and JSON APIs, and the clip does not become public.
|
|
135
|
+
|
|
134
136
|
Les points de terminaison suivent les mêmes règles de public/mot de passe/expiration que la page de partage.
|
|
135
137
|
Les clips protégés par mot de passe nécessitent le mot de passe une seule fois ; les réponses positives reviennent
|
|
136
138
|
Liens tokenisés de courte durée afin que les agents en aval n'aient pas besoin du texte brut
|
|
@@ -147,6 +147,8 @@ CLI स्थानीय डेव URL प्रिंट करता है
|
|
|
147
147
|
|
|
148
148
|
**व्यापक कनेक्टर सतह।** BigQuery, GA4, उत्पाद विश्लेषण, CRM, समर्थन, समुदाय, GitHub/Jira, SEO, और प्रथम-पक्ष `/track` इवेंट सभी actions के माध्यम से आते हैं जिन्हें एजेंट कॉल कर सकता है।
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### एजेंट के साथ काम करना
|
|
151
153
|
|
|
152
154
|
एजेंट को हमेशा पता होता है कि आप क्या देख रहे हैं। वर्तमान स्क्रीन स्थिति को प्रत्येक संदेश में `<current-screen>` ब्लॉक के रूप में इंजेक्ट किया जाता है - इसमें सक्रिय दृश्य, खुला डैशबोर्ड या विश्लेषण और कोई भी चयनित फ़िल्टर शामिल होता है।
|
|
@@ -131,6 +131,8 @@ APIs, इसलिए मॉडल जो केवल पाठ या स्
|
|
|
131
131
|
| `/api/agent-transcript.json?id=<recordingId>` | `startMs`, `endMs`, पठनीय टाइमस्टैम्प, टेक्स्ट और वैकल्पिक स्रोत लेबल के साथ टाइमस्टैम्प्ड ट्रांसक्रिप्ट सेगमेंट |
|
|
132
132
|
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>` | मूल-वीडियो टाइमस्टैम्प पर वीडियो से निकाला गया एक JPEG फ्रेम |
|
|
133
133
|
|
|
134
|
+
Temporary private agent links are also supported: the Share dialog can mint a two-hour `agent_access` URL for any recording the viewer can access. Agents use that token with the share page and JSON APIs, and the clip does not become public.
|
|
135
|
+
|
|
134
136
|
एंडपॉइंट शेयर पेज के समान सार्वजनिक/पासवर्ड/समाप्ति नियमों का पालन करते हैं।
|
|
135
137
|
पासवर्ड-सुरक्षित क्लिप को एक बार पासवर्ड की आवश्यकता होती है; सफल प्रत्युत्तर वापस आते हैं
|
|
136
138
|
अल्पकालिक टोकनयुक्त लिंक ताकि डाउनस्ट्रीम एजेंटों को प्लेनटेक्स्ट की आवश्यकता न हो
|
|
@@ -147,6 +147,8 @@ CLI はローカル開発 URL を出力します。 Google でログインし、
|
|
|
147
147
|
|
|
148
148
|
**幅広いコネクタ サーフェス。** BigQuery、GA4、製品分析、CRM、サポート、コミュニティ、GitHub/Jira、SEO、ファーストパーティ `/track` イベントはすべて、エージェントが呼び出すことができる actions 経由で行われます。
|
|
149
149
|
|
|
150
|
+
**Session replay agent handoff.** Session recordings stay private, but the session detail page can mint a temporary **Copy for agent** link. The two-hour `agent_access` URL lets an external agent read replay summaries, timelines, and bounded event details without exposing blob/provider URLs or making the recording public.
|
|
151
|
+
|
|
150
152
|
### エージェントとの連携
|
|
151
153
|
|
|
152
154
|
エージェントは、あなたが何を見ているのかを常に知っています。現在の画面状態は、`<current-screen>` ブロックとしてすべてのメッセージに挿入されます。これには、アクティブなビュー、開いているダッシュボードまたは分析、選択したフィルターが含まれます。
|