@agent-native/core 0.77.6 → 0.77.8
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 +2 -2
- package/corpus/core/CHANGELOG.md +29 -0
- package/corpus/core/package.json +3 -3
- package/corpus/core/src/agent/production-agent.ts +18 -0
- package/corpus/core/src/agent/thread-data-builder.ts +21 -2
- package/corpus/core/src/cli/create.ts +35 -1
- package/corpus/core/src/cli/skills.ts +8 -0
- package/corpus/core/src/client/AgentPanel.tsx +57 -25
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -1
- package/corpus/core/src/client/analytics.ts +24 -2
- package/corpus/core/src/client/use-agent-engine-configured.ts +29 -15
- package/corpus/core/src/client/use-chat-threads.ts +104 -55
- package/corpus/core/src/db/ddl-guard.ts +190 -0
- package/corpus/core/src/secrets/storage.ts +36 -2
- package/corpus/core/src/server/analytics.ts +27 -3
- package/corpus/core/src/settings/store.ts +40 -6
- package/corpus/core/src/sharing/access.ts +35 -13
- package/corpus/core/src/sharing/actions/share-resource.ts +32 -9
- package/corpus/core/src/sharing/actions/unshare-resource.ts +25 -2
- package/corpus/core/src/sharing/registry.ts +9 -0
- package/corpus/core/src/vite/client.ts +3 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +25 -14
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +2 -2
- package/corpus/templates/analytics/app/lib/data-source-status.ts +47 -6
- package/corpus/templates/analytics/app/lib/data-sources.ts +14 -3
- package/corpus/templates/analytics/app/pages/DataSources.tsx +24 -5
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +15 -43
- package/corpus/templates/analytics/changelog/2026-06-25-fixed-hubspot-data-source-status-so-private-app-tokens-legac.md +6 -0
- package/corpus/templates/analytics/netlify.toml +1 -0
- package/corpus/templates/analytics/server/lib/credential-keys.ts +3 -1
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +12 -3
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +5 -2
- package/corpus/templates/assets/changelog/2026-06-25-create-now-returns-from-agent-settings-to-the-asset-chat-eve.md +6 -0
- package/corpus/templates/assets/netlify.toml +1 -0
- package/corpus/templates/brain/netlify.toml +1 -0
- package/corpus/templates/calendar/app/i18n-data.ts +12 -0
- package/corpus/templates/calendar/app/lib/clipboard.ts +58 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +15 -9
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +6 -2
- package/corpus/templates/calendar/changelog/2026-06-25-booking-link-copy-buttons-no-longer-fail-when-clipboard-perm.md +6 -0
- package/corpus/templates/calendar/netlify.toml +1 -0
- package/corpus/templates/chat/netlify.toml +1 -0
- package/corpus/templates/clips/AGENTS.md +9 -7
- package/corpus/templates/clips/actions/add-vocabulary-term.ts +2 -2
- package/corpus/templates/clips/actions/archive-recording.ts +5 -2
- package/corpus/templates/clips/actions/clear-edits.ts +5 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -2
- package/corpus/templates/clips/actions/delete-folder.ts +7 -4
- package/corpus/templates/clips/actions/delete-recording-permanent.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +5 -2
- package/corpus/templates/clips/actions/import-loom-recording.ts +2 -1
- package/corpus/templates/clips/actions/list-notifications.ts +9 -5
- package/corpus/templates/clips/actions/list-organization-state.ts +2 -1
- package/corpus/templates/clips/actions/list-recordings.ts +4 -1
- package/corpus/templates/clips/actions/move-recording.ts +5 -1
- package/corpus/templates/clips/actions/rename-folder.ts +6 -3
- package/corpus/templates/clips/actions/request-transcript.ts +5 -2
- package/corpus/templates/clips/actions/restore-recording.ts +5 -2
- package/corpus/templates/clips/actions/save-browser-diagnostics.ts +21 -8
- package/corpus/templates/clips/actions/set-chapters.ts +5 -2
- package/corpus/templates/clips/actions/set-thumbnail.ts +5 -2
- package/corpus/templates/clips/actions/split-recording.ts +5 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +6 -2
- package/corpus/templates/clips/actions/trash-recording.ts +5 -2
- package/corpus/templates/clips/actions/undo-edit.ts +5 -2
- package/corpus/templates/clips/actions/view-screen.ts +2 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +24 -7
- package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +5 -1
- package/corpus/templates/clips/changelog/2026-06-25-chrome-extension-recordings-now-upload-large-capture-bursts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-console-diagnostics-keep-more-useful-non-secret-details-when.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-fixed-owner-recognition-so-clips-created-from-desktop-and-we.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +3 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +85 -9
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +55 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +79 -3
- package/corpus/templates/clips/chrome-extension/src/options.ts +10 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +6 -0
- package/corpus/templates/clips/chrome-extension/src/permission.ts +8 -1
- package/corpus/templates/clips/chrome-extension/src/popup.ts +65 -39
- package/corpus/templates/clips/chrome-extension/src/sentry.ts +206 -0
- package/corpus/templates/clips/chrome-extension/vite.config.ts +47 -0
- package/corpus/templates/clips/netlify.toml +1 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/lib/google-calendar-oauth.ts +35 -23
- package/corpus/templates/clips/server/lib/public-agent-context.ts +8 -1
- package/corpus/templates/clips/server/lib/recordings.ts +18 -2
- package/corpus/templates/clips/server/lib/slack-oauth.ts +9 -6
- package/corpus/templates/clips/server/plugins/onboarding-calendar.ts +6 -2
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +2 -2
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +5 -2
- package/corpus/templates/clips/shared/browser-diagnostics.ts +14 -4
- package/corpus/templates/content/netlify.toml +1 -0
- package/corpus/templates/design/netlify.toml +1 -0
- package/corpus/templates/dispatch/netlify.toml +1 -0
- package/corpus/templates/forms/netlify.toml +1 -0
- package/corpus/templates/macros/netlify.toml +1 -0
- package/corpus/templates/mail/app/components/email/EmailList.tsx +7 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +4 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +10 -2
- package/corpus/templates/mail/app/hooks/use-compose-state.ts +15 -5
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +47 -9
- package/corpus/templates/mail/changelog/2026-06-25-account-avatars-stay-stable-while-mail-refreshes-google-acco.md +6 -0
- package/corpus/templates/mail/changelog/2026-06-25-mail-background-draft-saves-and-thread-prefetches-no-longer.md +6 -0
- package/corpus/templates/mail/netlify.toml +1 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +8 -0
- package/corpus/templates/plan/netlify.toml +1 -0
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/videos/netlify.toml +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +18 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +23 -2
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +28 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +8 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +8 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +29 -15
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +4 -4
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +22 -2
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +23 -13
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +4 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +49 -4
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/ddl-guard.d.ts +88 -0
- package/dist/db/ddl-guard.d.ts.map +1 -0
- package/dist/db/ddl-guard.js +180 -0
- package/dist/db/ddl-guard.js.map +1 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +26 -2
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/analytics.d.ts +4 -0
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +19 -3
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +32 -6
- package/dist/settings/store.js.map +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +26 -12
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +20 -9
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +13 -2
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +9 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +3 -3
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type BrowserDiagnosticConsoleLevel,
|
|
25
25
|
} from "../shared/browser-diagnostics.js";
|
|
26
26
|
|
|
27
|
-
const REDACTION_VERSION =
|
|
27
|
+
const REDACTION_VERSION = 2;
|
|
28
28
|
|
|
29
29
|
const consoleLevelSchema = z.enum(["debug", "log", "info", "warn", "error"]);
|
|
30
30
|
|
|
@@ -53,12 +53,19 @@ function truncate(value: string, maxLength: number): string {
|
|
|
53
53
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function redactString(
|
|
57
|
-
|
|
56
|
+
function redactString(
|
|
57
|
+
value: string,
|
|
58
|
+
options?: { redactQueryValues?: boolean },
|
|
59
|
+
): string {
|
|
60
|
+
return redactBrowserDiagnosticString(value, options);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function redactUrlString(value: string): string {
|
|
64
|
+
return redactBrowserDiagnosticString(value, { redactQueryValues: true });
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
function sanitizeUrl(raw: string): string {
|
|
61
|
-
const redacted =
|
|
68
|
+
const redacted = redactUrlString(raw);
|
|
62
69
|
try {
|
|
63
70
|
const parsed = new URL(redacted, "https://clips.local");
|
|
64
71
|
parsed.username = "";
|
|
@@ -93,14 +100,17 @@ function sanitizeConsoleLog(entry: z.infer<typeof consoleLogSchema>): {
|
|
|
93
100
|
stack?: string;
|
|
94
101
|
} {
|
|
95
102
|
const stack = entry.stack
|
|
96
|
-
? truncate(
|
|
103
|
+
? truncate(
|
|
104
|
+
redactString(entry.stack, { redactQueryValues: true }),
|
|
105
|
+
MAX_BROWSER_DIAGNOSTIC_MESSAGE_LENGTH,
|
|
106
|
+
)
|
|
97
107
|
: "";
|
|
98
108
|
return {
|
|
99
109
|
timestampMs: Math.round(entry.timestampMs),
|
|
100
110
|
elapsedMs: Math.round(entry.elapsedMs),
|
|
101
111
|
level: entry.level,
|
|
102
112
|
message: truncate(
|
|
103
|
-
redactString(entry.message),
|
|
113
|
+
redactString(entry.message, { redactQueryValues: true }),
|
|
104
114
|
MAX_BROWSER_DIAGNOSTIC_MESSAGE_LENGTH,
|
|
105
115
|
),
|
|
106
116
|
...(stack ? { stack } : {}),
|
|
@@ -109,10 +119,13 @@ function sanitizeConsoleLog(entry: z.infer<typeof consoleLogSchema>): {
|
|
|
109
119
|
|
|
110
120
|
function sanitizeNetworkRequest(entry: z.infer<typeof networkRequestSchema>) {
|
|
111
121
|
const statusText = entry.statusText
|
|
112
|
-
? truncate(redactString(entry.statusText), 120)
|
|
122
|
+
? truncate(redactString(entry.statusText, { redactQueryValues: true }), 120)
|
|
113
123
|
: "";
|
|
114
124
|
const error = entry.error
|
|
115
|
-
? truncate(
|
|
125
|
+
? truncate(
|
|
126
|
+
redactString(entry.error, { redactQueryValues: true }),
|
|
127
|
+
MAX_BROWSER_DIAGNOSTIC_MESSAGE_LENGTH,
|
|
128
|
+
)
|
|
116
129
|
: "";
|
|
117
130
|
return {
|
|
118
131
|
timestampMs: Math.round(entry.timestampMs),
|
|
@@ -15,7 +15,10 @@ import { and, eq } from "drizzle-orm";
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
17
|
import { getDb, schema } from "../server/db/index.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
getCurrentOwnerEmail,
|
|
20
|
+
ownerEmailMatches,
|
|
21
|
+
} from "../server/lib/recordings.js";
|
|
19
22
|
|
|
20
23
|
const ChapterSchema = z.object({
|
|
21
24
|
startMs: z.coerce.number().int().min(0),
|
|
@@ -61,7 +64,7 @@ export default defineAction({
|
|
|
61
64
|
.where(
|
|
62
65
|
and(
|
|
63
66
|
eq(schema.recordings.id, args.recordingId),
|
|
64
|
-
|
|
67
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
65
68
|
),
|
|
66
69
|
);
|
|
67
70
|
if (!existing) {
|
|
@@ -26,7 +26,10 @@ import { z } from "zod";
|
|
|
26
26
|
|
|
27
27
|
import { parseEdits, serializeEdits } from "../app/lib/timestamp-mapping.js";
|
|
28
28
|
import { getDb, schema } from "../server/db/index.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
getCurrentOwnerEmail,
|
|
31
|
+
ownerEmailMatches,
|
|
32
|
+
} from "../server/lib/recordings.js";
|
|
30
33
|
import { assertNativeRecordingMedia } from "./lib/native-media.js";
|
|
31
34
|
|
|
32
35
|
function decodeDataUrl(dataUrl: string): { bytes: Uint8Array; mime: string } {
|
|
@@ -88,7 +91,7 @@ export default defineAction({
|
|
|
88
91
|
.where(
|
|
89
92
|
and(
|
|
90
93
|
eq(schema.recordings.id, args.recordingId),
|
|
91
|
-
|
|
94
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
92
95
|
),
|
|
93
96
|
);
|
|
94
97
|
if (!existing) {
|
|
@@ -20,7 +20,10 @@ import {
|
|
|
20
20
|
serializeEdits,
|
|
21
21
|
} from "../app/lib/timestamp-mapping.js";
|
|
22
22
|
import { getDb, schema } from "../server/db/index.js";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
getCurrentOwnerEmail,
|
|
25
|
+
ownerEmailMatches,
|
|
26
|
+
} from "../server/lib/recordings.js";
|
|
24
27
|
import { assertNativeRecordingMedia } from "./lib/native-media.js";
|
|
25
28
|
|
|
26
29
|
export default defineAction({
|
|
@@ -44,7 +47,7 @@ export default defineAction({
|
|
|
44
47
|
.where(
|
|
45
48
|
and(
|
|
46
49
|
eq(schema.recordings.id, args.recordingId),
|
|
47
|
-
|
|
50
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
48
51
|
),
|
|
49
52
|
);
|
|
50
53
|
if (!existing) {
|
|
@@ -34,7 +34,11 @@ import { z } from "zod";
|
|
|
34
34
|
|
|
35
35
|
import { parseEdits, serializeEdits } from "../app/lib/timestamp-mapping.js";
|
|
36
36
|
import { getDb, schema } from "../server/db/index.js";
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
getCurrentOwnerEmail,
|
|
39
|
+
nanoid,
|
|
40
|
+
ownerEmailMatches,
|
|
41
|
+
} from "../server/lib/recordings.js";
|
|
38
42
|
import { assertNativeRecordingMedia } from "./lib/native-media.js";
|
|
39
43
|
|
|
40
44
|
export default defineAction({
|
|
@@ -95,7 +99,7 @@ export default defineAction({
|
|
|
95
99
|
.where(
|
|
96
100
|
and(
|
|
97
101
|
inArray(schema.recordings.id, ids),
|
|
98
|
-
|
|
102
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
99
103
|
),
|
|
100
104
|
);
|
|
101
105
|
if (sources.length !== ids.length) {
|
|
@@ -11,7 +11,10 @@ import { and, eq } from "drizzle-orm";
|
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
13
|
import { getDb, schema } from "../server/db/index.js";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
getCurrentOwnerEmail,
|
|
16
|
+
ownerEmailMatches,
|
|
17
|
+
} from "../server/lib/recordings.js";
|
|
15
18
|
|
|
16
19
|
export default defineAction({
|
|
17
20
|
description:
|
|
@@ -29,7 +32,7 @@ export default defineAction({
|
|
|
29
32
|
.where(
|
|
30
33
|
and(
|
|
31
34
|
eq(schema.recordings.id, args.id),
|
|
32
|
-
|
|
35
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
33
36
|
),
|
|
34
37
|
);
|
|
35
38
|
if (!existing) throw new Error(`Recording not found: ${args.id}`);
|
|
@@ -19,7 +19,10 @@ import {
|
|
|
19
19
|
serializeEdits,
|
|
20
20
|
} from "../app/lib/timestamp-mapping.js";
|
|
21
21
|
import { getDb, schema } from "../server/db/index.js";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
getCurrentOwnerEmail,
|
|
24
|
+
ownerEmailMatches,
|
|
25
|
+
} from "../server/lib/recordings.js";
|
|
23
26
|
import { assertNativeRecordingMedia } from "./lib/native-media.js";
|
|
24
27
|
|
|
25
28
|
export default defineAction({
|
|
@@ -38,7 +41,7 @@ export default defineAction({
|
|
|
38
41
|
.where(
|
|
39
42
|
and(
|
|
40
43
|
eq(schema.recordings.id, args.recordingId),
|
|
41
|
-
|
|
44
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
42
45
|
),
|
|
43
46
|
);
|
|
44
47
|
if (!existing) {
|
|
@@ -23,6 +23,7 @@ import { z } from "zod";
|
|
|
23
23
|
import { getDb, schema } from "../server/db/index.js";
|
|
24
24
|
import {
|
|
25
25
|
getActiveOrganizationId,
|
|
26
|
+
ownerEmailMatches,
|
|
26
27
|
parseSpaceIds,
|
|
27
28
|
} from "../server/lib/recordings.js";
|
|
28
29
|
import { parseBrowserDiagnosticsRow } from "../shared/browser-diagnostics.js";
|
|
@@ -168,7 +169,7 @@ async function fetchFoldersForSpace(spaceId: string | null) {
|
|
|
168
169
|
.from(schema.folders)
|
|
169
170
|
.where(
|
|
170
171
|
and(
|
|
171
|
-
|
|
172
|
+
ownerEmailMatches(schema.folders.ownerEmail, ownerEmail),
|
|
172
173
|
spaceId
|
|
173
174
|
? eq(schema.folders.spaceId, spaceId)
|
|
174
175
|
: isNull(schema.folders.spaceId),
|
|
@@ -117,13 +117,29 @@ export function RecordingCard({
|
|
|
117
117
|
return (local || "?").slice(0, 2).toUpperCase();
|
|
118
118
|
}, [recording.ownerEmail]);
|
|
119
119
|
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
const recordingPath = `/r/${recording.id}`;
|
|
121
|
+
|
|
122
|
+
const handleOpen = useCallback(
|
|
123
|
+
(event: React.MouseEvent<HTMLElement>) => {
|
|
124
|
+
const shouldOpenNewTab =
|
|
125
|
+
event.button === 1 ||
|
|
126
|
+
(event.button === 0 && (event.metaKey || event.ctrlKey));
|
|
127
|
+
|
|
128
|
+
if (shouldOpenNewTab) {
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
event.stopPropagation();
|
|
131
|
+
window.open(recordingPath, "_blank", "noopener,noreferrer");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (selectionMode) {
|
|
136
|
+
onToggleSelect?.(recording.id);
|
|
137
|
+
} else {
|
|
138
|
+
navigate(recordingPath);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
[navigate, onToggleSelect, recording.id, recordingPath, selectionMode],
|
|
142
|
+
);
|
|
127
143
|
|
|
128
144
|
const handleCheckbox = useCallback(
|
|
129
145
|
(e: React.MouseEvent) => {
|
|
@@ -145,6 +161,7 @@ export function RecordingCard({
|
|
|
145
161
|
<div
|
|
146
162
|
role="article"
|
|
147
163
|
onClick={handleOpen}
|
|
164
|
+
onAuxClick={handleOpen}
|
|
148
165
|
onMouseEnter={() => setHovered(true)}
|
|
149
166
|
onMouseLeave={() => setHovered(false)}
|
|
150
167
|
className={cn(
|
|
@@ -26,8 +26,12 @@ function redactString(value: string): string {
|
|
|
26
26
|
return redactBrowserDiagnosticString(value);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function redactUrlString(value: string): string {
|
|
30
|
+
return redactBrowserDiagnosticString(value, { redactQueryValues: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
function sanitizeUrl(raw: string): string {
|
|
30
|
-
const redacted =
|
|
34
|
+
const redacted = redactUrlString(raw);
|
|
31
35
|
try {
|
|
32
36
|
const parsed = new URL(redacted, window.location.href);
|
|
33
37
|
parsed.username = "";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Agent-Native Clips",
|
|
4
4
|
"short_name": "Clips",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.3",
|
|
6
6
|
"description": "Start Clips recordings from Chrome with optional redacted console and network diagnostics.",
|
|
7
7
|
"minimum_chrome_version": "116",
|
|
8
8
|
"action": {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { captureExtensionError, initExtensionSentry } from "./sentry";
|
|
2
|
+
|
|
3
|
+
initExtensionSentry("background");
|
|
4
|
+
|
|
1
5
|
const DEFAULT_CLIPS_BASE_URL = "https://clips.agent-native.com";
|
|
2
6
|
const DEBUGGER_PROTOCOL_VERSION = "1.3";
|
|
3
7
|
const MAX_CONSOLE_LOGS = 400;
|
|
@@ -149,6 +153,15 @@ type OffscreenStatusMessage = {
|
|
|
149
153
|
error?: string;
|
|
150
154
|
};
|
|
151
155
|
|
|
156
|
+
type ExtensionErrorMessage = {
|
|
157
|
+
type: "CLIPS_EXTENSION_ERROR";
|
|
158
|
+
surface?: string;
|
|
159
|
+
name?: string;
|
|
160
|
+
message?: string;
|
|
161
|
+
stack?: string;
|
|
162
|
+
context?: Record<string, unknown>;
|
|
163
|
+
};
|
|
164
|
+
|
|
152
165
|
type PendingNetworkRequest = {
|
|
153
166
|
requestId: string;
|
|
154
167
|
timestampMs: number;
|
|
@@ -516,19 +529,24 @@ function truncate(value: string, maxLength: number): string {
|
|
|
516
529
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
517
530
|
}
|
|
518
531
|
|
|
519
|
-
function redactString(
|
|
520
|
-
|
|
532
|
+
function redactString(
|
|
533
|
+
value: string,
|
|
534
|
+
options: { redactQueryValues?: boolean } = {},
|
|
535
|
+
): string {
|
|
536
|
+
const redacted = value
|
|
521
537
|
.replace(AUTHORIZATION_SCHEME_RE, "$1$2<redacted>")
|
|
522
538
|
.replace(/\b(bearer|basic)\s+[a-z0-9._~+/-]+=*/gi, "$1 <redacted>")
|
|
523
539
|
.replace(DOUBLE_QUOTED_SECRET_VALUE_RE, '$1$2$1$3"<redacted>"')
|
|
524
540
|
.replace(SINGLE_QUOTED_SECRET_VALUE_RE, "$1$2$1$3'<redacted>'")
|
|
525
|
-
.replace(UNQUOTED_SECRET_VALUE_RE, "$1$2$1$3<redacted>")
|
|
526
|
-
|
|
541
|
+
.replace(UNQUOTED_SECRET_VALUE_RE, "$1$2$1$3<redacted>");
|
|
542
|
+
return options.redactQueryValues
|
|
543
|
+
? redacted.replace(/([?&][^=\s&?#]+)=([^&\s#]+)/g, "$1=<redacted>")
|
|
544
|
+
: redacted;
|
|
527
545
|
}
|
|
528
546
|
|
|
529
547
|
function sanitizeUrl(raw: string | null | undefined): string | null {
|
|
530
548
|
if (!raw) return null;
|
|
531
|
-
const redacted = redactString(raw);
|
|
549
|
+
const redacted = redactString(raw, { redactQueryValues: true });
|
|
532
550
|
try {
|
|
533
551
|
const parsed = new URL(redacted);
|
|
534
552
|
parsed.username = "";
|
|
@@ -1016,6 +1034,17 @@ async function armRecording(args: {
|
|
|
1016
1034
|
visibility: "public",
|
|
1017
1035
|
});
|
|
1018
1036
|
} catch (err) {
|
|
1037
|
+
captureExtensionError(err, {
|
|
1038
|
+
tags: {
|
|
1039
|
+
surface: "background",
|
|
1040
|
+
recordingStep: "create-recording",
|
|
1041
|
+
},
|
|
1042
|
+
extra: {
|
|
1043
|
+
captureSurface: settings.captureSurface,
|
|
1044
|
+
includeCamera: settings.includeCamera,
|
|
1045
|
+
includeMicrophone: settings.includeMicrophone,
|
|
1046
|
+
},
|
|
1047
|
+
});
|
|
1019
1048
|
await abortArming();
|
|
1020
1049
|
throw err;
|
|
1021
1050
|
}
|
|
@@ -1070,6 +1099,18 @@ async function armRecording(args: {
|
|
|
1070
1099
|
});
|
|
1071
1100
|
} catch (err) {
|
|
1072
1101
|
console.error("[clips-bg] arm: BEGIN failed", err);
|
|
1102
|
+
captureExtensionError(err, {
|
|
1103
|
+
tags: {
|
|
1104
|
+
surface: "background",
|
|
1105
|
+
recordingStep: "offscreen-begin",
|
|
1106
|
+
},
|
|
1107
|
+
extra: {
|
|
1108
|
+
recordingId: created.id,
|
|
1109
|
+
captureSurface: settings.captureSurface,
|
|
1110
|
+
includeCamera: settings.includeCamera,
|
|
1111
|
+
includeMicrophone: settings.includeMicrophone,
|
|
1112
|
+
},
|
|
1113
|
+
});
|
|
1073
1114
|
await cancelRecording();
|
|
1074
1115
|
throw err;
|
|
1075
1116
|
}
|
|
@@ -1553,9 +1594,15 @@ function pushConsole(
|
|
|
1553
1594
|
const timestampMs = Number.isFinite(entry.timestampMs)
|
|
1554
1595
|
? (entry.timestampMs as number)
|
|
1555
1596
|
: nowMs();
|
|
1556
|
-
const message = truncate(
|
|
1597
|
+
const message = truncate(
|
|
1598
|
+
redactString(entry.message, { redactQueryValues: true }),
|
|
1599
|
+
MAX_MESSAGE_LENGTH,
|
|
1600
|
+
);
|
|
1557
1601
|
const stack = entry.stack
|
|
1558
|
-
? truncate(
|
|
1602
|
+
? truncate(
|
|
1603
|
+
redactString(entry.stack, { redactQueryValues: true }),
|
|
1604
|
+
MAX_MESSAGE_LENGTH,
|
|
1605
|
+
)
|
|
1559
1606
|
: "";
|
|
1560
1607
|
session.consoleLogs.push({
|
|
1561
1608
|
timestampMs,
|
|
@@ -1762,7 +1809,10 @@ function handleResponseReceived(
|
|
|
1762
1809
|
pending.ok = response.status >= 200 && response.status < 400;
|
|
1763
1810
|
}
|
|
1764
1811
|
if (typeof response.statusText === "string") {
|
|
1765
|
-
pending.statusText = truncate(
|
|
1812
|
+
pending.statusText = truncate(
|
|
1813
|
+
redactString(response.statusText, { redactQueryValues: true }),
|
|
1814
|
+
120,
|
|
1815
|
+
);
|
|
1766
1816
|
}
|
|
1767
1817
|
}
|
|
1768
1818
|
|
|
@@ -1792,7 +1842,12 @@ function finalizeNetworkRequest(
|
|
|
1792
1842
|
...(typeof pending.ok === "boolean" ? { ok: pending.ok } : {}),
|
|
1793
1843
|
durationMs: Math.round(durationMs),
|
|
1794
1844
|
...(error
|
|
1795
|
-
? {
|
|
1845
|
+
? {
|
|
1846
|
+
error: truncate(
|
|
1847
|
+
redactString(error, { redactQueryValues: true }),
|
|
1848
|
+
MAX_MESSAGE_LENGTH,
|
|
1849
|
+
),
|
|
1850
|
+
}
|
|
1796
1851
|
: {}),
|
|
1797
1852
|
});
|
|
1798
1853
|
}
|
|
@@ -1923,6 +1978,12 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
1923
1978
|
(message as { type?: unknown })?.type,
|
|
1924
1979
|
err,
|
|
1925
1980
|
);
|
|
1981
|
+
captureExtensionError(err, {
|
|
1982
|
+
tags: {
|
|
1983
|
+
surface: "background",
|
|
1984
|
+
messageType: String((message as { type?: unknown })?.type ?? ""),
|
|
1985
|
+
},
|
|
1986
|
+
});
|
|
1926
1987
|
response = {
|
|
1927
1988
|
ok: false,
|
|
1928
1989
|
error: err instanceof Error ? err.message : "Could not use Clips.",
|
|
@@ -1940,6 +2001,21 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
1940
2001
|
async function dispatchRuntimeMessage(message: unknown): Promise<unknown> {
|
|
1941
2002
|
const type = (message as { type?: unknown }).type;
|
|
1942
2003
|
|
|
2004
|
+
if (type === "CLIPS_EXTENSION_ERROR") {
|
|
2005
|
+
const report = message as ExtensionErrorMessage;
|
|
2006
|
+
const error = new Error(report.message || "Chrome extension error");
|
|
2007
|
+
error.name = report.name || "ExtensionError";
|
|
2008
|
+
if (report.stack) error.stack = report.stack;
|
|
2009
|
+
captureExtensionError(error, {
|
|
2010
|
+
tags: {
|
|
2011
|
+
surface: report.surface || "content-script",
|
|
2012
|
+
mechanism: "content-script-report",
|
|
2013
|
+
},
|
|
2014
|
+
extra: report.context,
|
|
2015
|
+
});
|
|
2016
|
+
return { ok: true };
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1943
2019
|
// Status updates streamed from the offscreen recorder.
|
|
1944
2020
|
if (type === "CLIPS_NATIVE_STATUS") {
|
|
1945
2021
|
const status = message as OffscreenStatusMessage;
|
|
@@ -18,6 +18,61 @@
|
|
|
18
18
|
const ALL_PARTS: OverlayPart[] = ["bubble", "countdown", "toolbar", "saving"];
|
|
19
19
|
const flags = window as unknown as { __clipsOverlayHostReady?: boolean };
|
|
20
20
|
|
|
21
|
+
function errorPayload(error: unknown): {
|
|
22
|
+
name: string;
|
|
23
|
+
message: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
} {
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
return {
|
|
28
|
+
name: error.name || "Error",
|
|
29
|
+
message: error.message || "Unknown content-script error",
|
|
30
|
+
stack: error.stack,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
name: "Error",
|
|
35
|
+
message: String(error ?? "Unknown content-script error"),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function reportContentScriptError(
|
|
40
|
+
error: unknown,
|
|
41
|
+
context: Record<string, unknown> = {},
|
|
42
|
+
): void {
|
|
43
|
+
try {
|
|
44
|
+
chrome.runtime.sendMessage(
|
|
45
|
+
{
|
|
46
|
+
type: "CLIPS_EXTENSION_ERROR",
|
|
47
|
+
surface: "content-script",
|
|
48
|
+
...errorPayload(error),
|
|
49
|
+
context: {
|
|
50
|
+
...context,
|
|
51
|
+
pageUrl: location.href,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
() => void chrome.runtime.lastError,
|
|
55
|
+
);
|
|
56
|
+
} catch {
|
|
57
|
+
/* background unavailable */
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
window.addEventListener("error", (event) => {
|
|
62
|
+
reportContentScriptError(event.error || event.message, {
|
|
63
|
+
mechanism: "global-error",
|
|
64
|
+
filename: event.filename,
|
|
65
|
+
lineno: event.lineno,
|
|
66
|
+
colno: event.colno,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
71
|
+
reportContentScriptError(event.reason, {
|
|
72
|
+
mechanism: "unhandled-rejection",
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
21
76
|
// ----- Draggable, resizable camera bubble ---------------------------------
|
|
22
77
|
// Size + position persist in storage so the bubble stays where the user put it
|
|
23
78
|
// across pages and recordings (like the desktop app). The iframe can't move or
|