@agent-native/core 0.164.3 → 0.164.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/corpus/README.md +1 -1
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +36 -47
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
- package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
- package/corpus/templates/calendar/app/i18n-data.ts +120 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -0
- package/corpus/templates/calendar/server/handlers/google-auth.ts +119 -3
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +1 -1
- package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -78
- package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +6 -0
- package/corpus/templates/clips/desktop/README.md +19 -4
- package/corpus/templates/clips/desktop/src/app.tsx +78 -16
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
- package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
- package/corpus/templates/clips/server/lib/slack-unfurls.ts +7 -13
- package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
- package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
- package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
- package/corpus/templates/clips/shared/share-meta.ts +67 -3
- package/corpus/templates/content/actions/list-content-databases.ts +95 -1
- package/corpus/templates/content/changelog/2026-08-11-content-mutations-delegated-from-verified-slack-dms-now-use-.md +6 -0
- package/corpus/templates/content/shared/api.ts +11 -0
- package/corpus/templates/factory/AGENTS.md +1 -1
- package/corpus/templates/factory/actions/list-factory-automations.ts +4 -0
- package/corpus/templates/factory/actions/start-builder-for-item.ts +19 -17
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
- package/corpus/templates/factory/app/i18n/en-US.ts +4 -0
- package/corpus/templates/factory/app/routes/factory.tsx +209 -46
- package/corpus/templates/factory/server/connectors/slack.ts +44 -2
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -7
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
- package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
- package/corpus/templates/mail/actions/view-screen.ts +1 -1
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
- package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
- package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
- package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
- package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
- package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
- package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
- package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
- package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
- package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
- package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
- package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
- package/corpus/templates/slides/server/db/schema.ts +8 -0
- package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
- package/corpus/templates/slides/server/lib/emails.ts +26 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
- package/corpus/templates/slides/server/plugins/db.ts +50 -0
- package/corpus/templates/slides/shared/deck-access.ts +31 -0
- package/dist/a2a/artifact-response.d.ts +50 -0
- package/dist/a2a/artifact-response.js +266 -39
- package/dist/a2a/index.d.ts +2 -0
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/task-store.d.ts +1 -0
- package/dist/a2a/task-store.js +1 -1
- package/dist/agent/observational-memory/store.d.ts +1 -0
- package/dist/agent/observational-memory/store.js +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/tool-approval-store.d.ts +1 -0
- package/dist/agent/tool-approval-store.js +1 -1
- package/dist/application-state/store.d.ts +1 -0
- package/dist/application-state/store.js +1 -1
- package/dist/browser-sessions/store.d.ts +1 -0
- package/dist/browser-sessions/store.js +1 -1
- package/dist/checkpoints/store.d.ts +1 -0
- package/dist/checkpoints/store.js +1 -1
- package/dist/cli/code-agent-schedules.d.ts +11 -0
- package/dist/cli/code-agent-schedules.js +44 -5
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AssistantChat.d.ts +5 -1
- package/dist/client/AssistantChat.js +40 -6
- package/dist/client/EnvironmentBadge.d.ts +7 -13
- package/dist/client/EnvironmentBadge.js +43 -92
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/agent-chat-adapter.js +76 -50
- package/dist/client/app-providers.js +4 -4
- package/dist/client/chat/message-components.d.ts +4 -0
- package/dist/client/chat/message-components.js +28 -1
- package/dist/client/chat/run-recovery.js +26 -0
- package/dist/client/chat-first/apps-rail.d.ts +1 -0
- package/dist/client/chat-first/apps-rail.js +28 -2
- package/dist/client/sse-event-processor.js +13 -8
- package/dist/client/use-active-agent-chat-run.d.ts +2 -0
- package/dist/client/use-active-agent-chat-run.js +22 -0
- package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +1 -1
- package/dist/collab/awareness-store.d.ts +1 -0
- package/dist/collab/awareness-store.js +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts +1 -0
- package/dist/collab/storage.js +1 -1
- package/dist/db/client.js +3 -3
- package/dist/db/ddl-guard.js +8 -0
- package/dist/db/migration-runtime.d.ts +23 -0
- package/dist/db/migration-runtime.js +41 -0
- package/dist/db/migrations.d.ts +1 -2
- package/dist/db/migrations.js +2 -24
- package/dist/email-catalog/log.d.ts +1 -0
- package/dist/email-catalog/log.js +1 -1
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.js +1 -0
- package/dist/guards/release-schema-complete.d.ts +22 -0
- package/dist/guards/release-schema-complete.js +144 -0
- package/dist/integrations/a2a-continuations-store.d.ts +1 -0
- package/dist/integrations/a2a-continuations-store.js +1 -1
- package/dist/integrations/adapters/slack.js +58 -7
- package/dist/integrations/awaiting-input-store.d.ts +1 -0
- package/dist/integrations/awaiting-input-store.js +1 -1
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.js +1 -1
- package/dist/integrations/controls-store.d.ts +1 -0
- package/dist/integrations/controls-store.js +1 -1
- package/dist/integrations/identity-links-store.d.ts +1 -0
- package/dist/integrations/identity-links-store.js +1 -1
- package/dist/integrations/installations-store.d.ts +1 -0
- package/dist/integrations/installations-store.js +1 -1
- package/dist/integrations/remote-commands-store.d.ts +1 -0
- package/dist/integrations/remote-commands-store.js +1 -1
- package/dist/integrations/remote-devices-store.d.ts +1 -0
- package/dist/integrations/remote-devices-store.js +1 -1
- package/dist/integrations/remote-push-store.d.ts +1 -0
- package/dist/integrations/remote-push-store.js +1 -1
- package/dist/integrations/remote-run-events-store.d.ts +1 -0
- package/dist/integrations/remote-run-events-store.js +1 -1
- package/dist/integrations/scope-store.d.ts +1 -0
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/thread-mapping-store.d.ts +1 -0
- package/dist/integrations/thread-mapping-store.js +1 -1
- package/dist/integrations/usage-budget-store.d.ts +1 -0
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/jobs/background-automation-runner.js +111 -9
- package/dist/jobs/run-history.d.ts +1 -0
- package/dist/jobs/run-history.js +1 -1
- package/dist/jobs/scheduler-health.d.ts +1 -0
- package/dist/jobs/scheduler-health.js +1 -1
- package/dist/mcp/approval-store.d.ts +1 -0
- package/dist/mcp/approval-store.js +1 -1
- package/dist/mcp/connect-store.d.ts +1 -0
- package/dist/mcp/connect-store.js +1 -1
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.js +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/notifications/store.d.ts +1 -0
- package/dist/notifications/store.js +1 -1
- package/dist/oauth-tokens/store.d.ts +1 -0
- package/dist/oauth-tokens/store.js +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/store.d.ts +1 -0
- package/dist/progress/store.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
- package/dist/provider-api/corpus-jobs-store.js +1 -1
- package/dist/provider-api/custom-registry.d.ts +1 -0
- package/dist/provider-api/custom-registry.js +1 -1
- package/dist/provider-api/quota-governor.d.ts +1 -0
- package/dist/provider-api/quota-governor.js +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts +1 -0
- package/dist/provider-api/staged-datasets-store.js +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/resources/store.d.ts +1 -0
- package/dist/resources/store.js +1 -1
- package/dist/scripts/dev/index.js +15 -1
- package/dist/search/index.js +3 -0
- package/dist/secrets/storage.d.ts +1 -0
- package/dist/secrets/storage.js +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +2 -1
- package/dist/server/agent-chat/action-filters-a2a.js +10 -2
- package/dist/server/agent-chat-plugin.js +71 -20
- package/dist/server/agent-teams-run-queue.d.ts +1 -0
- package/dist/server/agent-teams-run-queue.js +1 -1
- package/dist/server/auth-marketing.js +3 -1
- package/dist/server/auth.d.ts +18 -1
- package/dist/server/auth.js +370 -154
- package/dist/server/embed-session.d.ts +1 -0
- package/dist/server/embed-session.js +1 -1
- package/dist/server/google-auth-plugin.js +3 -1
- package/dist/server/google-oauth.d.ts +10 -0
- package/dist/server/google-oauth.js +25 -1
- package/dist/server/identity-sso-store.d.ts +1 -0
- package/dist/server/identity-sso-store.js +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/onboarding-html.js +200 -31
- package/dist/server/poll.d.ts +2 -0
- package/dist/server/poll.js +19 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +5 -0
- package/dist/server/release-schema.d.ts +46 -0
- package/dist/server/release-schema.js +307 -0
- package/dist/settings/store.d.ts +1 -0
- package/dist/settings/store.js +1 -1
- package/dist/shared/environment-lanes.d.ts +28 -0
- package/dist/shared/environment-lanes.js +61 -0
- package/dist/sharing/actions/share-resource.js +22 -2
- package/dist/styles/agent-native.css +17 -15
- package/dist/triggers/routes.d.ts +11 -0
- package/dist/triggers/routes.js +10 -0
- package/dist/usage/alerts-store.d.ts +1 -0
- package/dist/usage/alerts-store.js +1 -1
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +1 -1
- package/docs/content/drop-in-agent.mdx +4 -4
- package/docs/content/faq.mdx +15 -15
- package/docs/content/getting-started.mdx +173 -41
- package/docs/content/key-concepts.mdx +10 -10
- package/docs/content/using-your-agent.mdx +2 -2
- package/docs/content/what-is-agent-native.mdx +79 -228
- package/package.json +2 -2
|
@@ -6,6 +6,7 @@ import { eq } from "drizzle-orm";
|
|
|
6
6
|
import {
|
|
7
7
|
clipsShareDescription,
|
|
8
8
|
displayRecordingTitle,
|
|
9
|
+
resolveClipsSocialImageUrl,
|
|
9
10
|
} from "../../shared/share-meta.js";
|
|
10
11
|
import { getDb, schema } from "../db/index.js";
|
|
11
12
|
|
|
@@ -191,15 +192,6 @@ function appPath(path: string, basePath: string): string {
|
|
|
191
192
|
return base ? `/${base}${path}` : path;
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
function absoluteUrl(value: string | null | undefined, origin: string): string {
|
|
195
|
-
if (!value) return AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE;
|
|
196
|
-
try {
|
|
197
|
-
return new URL(value, origin).toString();
|
|
198
|
-
} catch {
|
|
199
|
-
return AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
195
|
function isExpired(value: string | null): boolean {
|
|
204
196
|
if (!value) return false;
|
|
205
197
|
const expires = new Date(value).getTime();
|
|
@@ -255,10 +247,12 @@ export function buildSlackVideoBlock(options: {
|
|
|
255
247
|
const description = duration
|
|
256
248
|
? `${duration} · ${shareDescription}`
|
|
257
249
|
: shareDescription;
|
|
258
|
-
const thumbnailUrl =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
250
|
+
const thumbnailUrl =
|
|
251
|
+
resolveClipsSocialImageUrl({
|
|
252
|
+
recording,
|
|
253
|
+
origin,
|
|
254
|
+
basePath,
|
|
255
|
+
}) ?? AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE;
|
|
262
256
|
|
|
263
257
|
return {
|
|
264
258
|
type: "video",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "../../../_agent-native/google/auth-url.get.js";
|
|
@@ -4,10 +4,14 @@ import {
|
|
|
4
4
|
isElectron,
|
|
5
5
|
resolveGoogleSignInCredentials,
|
|
6
6
|
resolveOAuthRedirectUri,
|
|
7
|
+
registerDesktopExchange,
|
|
8
|
+
prepareDesktopOAuthBrowserBinding,
|
|
7
9
|
safeReturnPath,
|
|
8
10
|
} from "@agent-native/core/server";
|
|
9
11
|
import {
|
|
10
12
|
defineEventHandler,
|
|
13
|
+
getHeader,
|
|
14
|
+
getMethod,
|
|
11
15
|
getQuery,
|
|
12
16
|
setResponseStatus,
|
|
13
17
|
type H3Event,
|
|
@@ -54,11 +58,39 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
54
58
|
isElectron(event) || q.desktop === "1" || q.desktop === "true";
|
|
55
59
|
const flowId =
|
|
56
60
|
desktop && typeof q.flow_id === "string" ? q.flow_id : undefined;
|
|
61
|
+
if (getMethod(event) === "POST" && (!desktop || !flowId)) {
|
|
62
|
+
setResponseStatus(event, 400);
|
|
63
|
+
return { error: "Invalid desktop exchange challenge." };
|
|
64
|
+
}
|
|
65
|
+
const calendarConnect =
|
|
66
|
+
q.calendar === "1" || q.calendar === "true" || q.product === "calendar";
|
|
67
|
+
let desktopVerifierHash: string | undefined;
|
|
68
|
+
let desktopBrowserBindingHash: string | undefined;
|
|
69
|
+
if (flowId && !calendarConnect) {
|
|
70
|
+
if (getMethod(event) !== "POST" || q.redirect !== undefined) {
|
|
71
|
+
setResponseStatus(event, 400);
|
|
72
|
+
return { error: "Invalid desktop exchange challenge." };
|
|
73
|
+
}
|
|
74
|
+
const verifier = getHeader(event, "x-agent-native-desktop-verifier");
|
|
75
|
+
if (!verifier || q.verifier !== undefined) {
|
|
76
|
+
setResponseStatus(event, 400);
|
|
77
|
+
return { error: "Invalid desktop exchange challenge." };
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
desktopBrowserBindingHash = prepareDesktopOAuthBrowserBinding(event);
|
|
81
|
+
desktopVerifierHash = await registerDesktopExchange(
|
|
82
|
+
flowId,
|
|
83
|
+
verifier,
|
|
84
|
+
desktopBrowserBindingHash,
|
|
85
|
+
);
|
|
86
|
+
} catch {
|
|
87
|
+
setResponseStatus(event, 400);
|
|
88
|
+
return { error: "Invalid desktop exchange challenge." };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
57
91
|
const requestedReturn =
|
|
58
92
|
typeof q.return === "string" ? safeReturnPath(q.return) : "/";
|
|
59
93
|
const returnUrl = requestedReturn !== "/" ? requestedReturn : undefined;
|
|
60
|
-
const calendarConnect =
|
|
61
|
-
q.calendar === "1" || q.calendar === "true" || q.product === "calendar";
|
|
62
94
|
const credentials = calendarConnect
|
|
63
95
|
? ((await resolveGoogleOAuthCredentialCandidates())[0] ?? null)
|
|
64
96
|
: resolveGoogleSignInCredentials();
|
|
@@ -84,10 +116,16 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
84
116
|
redirectUri,
|
|
85
117
|
owner,
|
|
86
118
|
desktop,
|
|
119
|
+
desktopWebview: desktop && q.webview === "1" && !calendarConnect,
|
|
87
120
|
addAccount: calendarConnect,
|
|
88
121
|
app: CLIPS_GOOGLE_OAUTH_APP_ID,
|
|
89
|
-
returnUrl
|
|
122
|
+
returnUrl:
|
|
123
|
+
desktop && q.webview === "1" && !calendarConnect
|
|
124
|
+
? "/?desktop_auth=complete"
|
|
125
|
+
: returnUrl,
|
|
90
126
|
flowId: calendarConnect ? undefined : flowId,
|
|
127
|
+
desktopVerifierHash,
|
|
128
|
+
desktopBrowserBindingHash,
|
|
91
129
|
});
|
|
92
130
|
|
|
93
131
|
const params = new URLSearchParams({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./auth-url.get.js";
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
oauthErrorPage,
|
|
7
7
|
resolveGoogleSignInCredentials,
|
|
8
8
|
resolveOAuthOwner,
|
|
9
|
+
matchesDesktopOAuthBrowserBinding,
|
|
9
10
|
setDesktopExchange,
|
|
10
11
|
type OAuthStatePayload,
|
|
11
12
|
} from "@agent-native/core/server";
|
|
@@ -31,6 +32,17 @@ async function handleGoogleSignInCallback(
|
|
|
31
32
|
) {
|
|
32
33
|
const desktop = state.desktop;
|
|
33
34
|
const flowId = state.flowId;
|
|
35
|
+
if (
|
|
36
|
+
flowId &&
|
|
37
|
+
(!state.desktopVerifierHash ||
|
|
38
|
+
!state.desktopBrowserBindingHash ||
|
|
39
|
+
!matchesDesktopOAuthBrowserBinding(
|
|
40
|
+
event,
|
|
41
|
+
state.desktopBrowserBindingHash,
|
|
42
|
+
))
|
|
43
|
+
) {
|
|
44
|
+
return oauthErrorPage("Desktop OAuth browser binding is invalid.");
|
|
45
|
+
}
|
|
34
46
|
|
|
35
47
|
try {
|
|
36
48
|
const query = getQuery(event);
|
|
@@ -107,12 +119,21 @@ async function handleGoogleSignInCallback(
|
|
|
107
119
|
});
|
|
108
120
|
|
|
109
121
|
if (flowId && sessionToken) {
|
|
110
|
-
|
|
122
|
+
if (!state.desktopVerifierHash) {
|
|
123
|
+
throw new Error("Missing desktop exchange challenge.");
|
|
124
|
+
}
|
|
125
|
+
await setDesktopExchange(
|
|
126
|
+
flowId,
|
|
127
|
+
sessionToken,
|
|
128
|
+
email,
|
|
129
|
+
state.desktopVerifierHash,
|
|
130
|
+
);
|
|
111
131
|
}
|
|
112
132
|
|
|
113
133
|
return oauthCallbackResponse(event, email, {
|
|
114
134
|
sessionToken,
|
|
115
135
|
desktop,
|
|
136
|
+
desktopWebview: state.desktopWebview,
|
|
116
137
|
returnUrl: state.returnUrl,
|
|
117
138
|
flowId,
|
|
118
139
|
appName: "Clips",
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import { defineEventHandler, setResponseHeaders } from "h3";
|
|
1
|
+
import { defineEventHandler, getQuery, setResponseHeaders } from "h3";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Tauri updater manifest endpoint for the Clips desktop app.
|
|
5
5
|
*
|
|
6
6
|
* The installed app only needs this endpoint to be valid JSON when no signed
|
|
7
|
-
* updater bundle is available. If the
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* updater bundle is available. If the channel's GitHub pointer release exists,
|
|
8
|
+
* we proxy its signed manifest. If it does not, return a deliberately old
|
|
9
|
+
* no-update manifest so the desktop UI stays quiet instead of surfacing a
|
|
10
10
|
* release-channel setup error to end users.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
type ClipsUpdateChannel = "production" | "nightly";
|
|
14
|
+
|
|
15
|
+
const GITHUB_MANIFEST_URL: Record<ClipsUpdateChannel, string> = {
|
|
16
|
+
production:
|
|
17
|
+
"https://github.com/BuilderIO/agent-native/releases/download/clips-latest/clips-latest.json",
|
|
18
|
+
nightly:
|
|
19
|
+
"https://github.com/BuilderIO/agent-native/releases/download/clips-nightly-latest/clips-nightly-latest.json",
|
|
20
|
+
};
|
|
15
21
|
const CACHE_TTL_MS = 5 * 60_000;
|
|
16
22
|
|
|
17
23
|
// Tauri throws a red-banner error if the requesting client's target triple is
|
|
@@ -48,8 +54,8 @@ export const INERT_MANIFEST = {
|
|
|
48
54
|
},
|
|
49
55
|
};
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
const cache = new Map<ClipsUpdateChannel, { data: unknown; ts: number }>();
|
|
58
|
+
const inFlight = new Map<ClipsUpdateChannel, Promise<unknown>>();
|
|
53
59
|
|
|
54
60
|
function isManifestLike(value: unknown): value is Record<string, unknown> {
|
|
55
61
|
if (!value || typeof value !== "object") return false;
|
|
@@ -72,8 +78,10 @@ export function hasAllRequiredPlatforms(value: unknown): boolean {
|
|
|
72
78
|
return REQUIRED_PLATFORM_KEYS.every((k) => k in platforms);
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
async function fetchSignedManifest(
|
|
76
|
-
|
|
81
|
+
async function fetchSignedManifest(
|
|
82
|
+
channel: ClipsUpdateChannel,
|
|
83
|
+
): Promise<unknown> {
|
|
84
|
+
const res = await fetch(GITHUB_MANIFEST_URL[channel], {
|
|
77
85
|
headers: {
|
|
78
86
|
accept: "application/json",
|
|
79
87
|
"user-agent": "clips-updater-manifest",
|
|
@@ -94,38 +102,49 @@ async function fetchSignedManifest(): Promise<unknown> {
|
|
|
94
102
|
return json;
|
|
95
103
|
}
|
|
96
104
|
|
|
97
|
-
|
|
105
|
+
function normalizeChannel(value: unknown): ClipsUpdateChannel {
|
|
106
|
+
return value === "nightly" ? "nightly" : "production";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function getManifest(
|
|
110
|
+
channel: ClipsUpdateChannel = "production",
|
|
111
|
+
): Promise<unknown> {
|
|
98
112
|
const now = Date.now();
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
113
|
+
const cached = cache.get(channel);
|
|
114
|
+
if (cached && now - cached.ts < CACHE_TTL_MS) return cached.data;
|
|
115
|
+
const pending = inFlight.get(channel);
|
|
116
|
+
if (pending) return pending;
|
|
117
|
+
const request = (async () => {
|
|
102
118
|
try {
|
|
103
|
-
const data = await fetchSignedManifest();
|
|
104
|
-
cache
|
|
119
|
+
const data = await fetchSignedManifest(channel);
|
|
120
|
+
cache.set(channel, { data, ts: Date.now() });
|
|
105
121
|
return data;
|
|
106
122
|
} catch {
|
|
107
123
|
// A validation or network failure may serve the last good manifest (or
|
|
108
124
|
// inert fallback), but it must not make that fallback fresh again.
|
|
109
125
|
// Otherwise an incomplete release manifest can indefinitely extend the
|
|
110
126
|
// stale cache window on every failed refresh.
|
|
111
|
-
return cache?.data ?? INERT_MANIFEST;
|
|
127
|
+
return cache.get(channel)?.data ?? INERT_MANIFEST;
|
|
112
128
|
} finally {
|
|
113
|
-
inFlight
|
|
129
|
+
inFlight.delete(channel);
|
|
114
130
|
}
|
|
115
131
|
})();
|
|
116
|
-
|
|
132
|
+
inFlight.set(channel, request);
|
|
133
|
+
return request;
|
|
117
134
|
}
|
|
118
135
|
|
|
119
136
|
export const __clipsUpdaterTest = {
|
|
120
137
|
getManifest,
|
|
121
138
|
reset() {
|
|
122
|
-
cache
|
|
123
|
-
inFlight
|
|
139
|
+
cache.clear();
|
|
140
|
+
inFlight.clear();
|
|
124
141
|
},
|
|
125
142
|
};
|
|
126
143
|
|
|
127
144
|
export default defineEventHandler(async (event) => {
|
|
128
|
-
const
|
|
145
|
+
const query = getQuery(event);
|
|
146
|
+
const channel = normalizeChannel(query.channel);
|
|
147
|
+
const manifest = await getManifest(channel);
|
|
129
148
|
setResponseHeaders(event, {
|
|
130
149
|
"content-type": "application/json; charset=utf-8",
|
|
131
150
|
"cache-control": "public, max-age=60",
|
|
@@ -8,15 +8,25 @@ import {
|
|
|
8
8
|
type SocialMetaDescriptor,
|
|
9
9
|
} from "@agent-native/core/shared";
|
|
10
10
|
|
|
11
|
+
import { buildAgentApiUrls } from "./agent-context";
|
|
12
|
+
|
|
11
13
|
export const CLIPS_DEFAULT_TITLE = "Untitled recording";
|
|
12
14
|
|
|
13
15
|
export type ClipsShareMetaRecording = {
|
|
16
|
+
id?: string | null;
|
|
14
17
|
title?: string | null;
|
|
15
18
|
description?: string | null;
|
|
16
19
|
thumbnailUrl?: string | null;
|
|
17
20
|
animatedThumbnailUrl?: string | null;
|
|
21
|
+
visibility?: string | null;
|
|
22
|
+
status?: string | null;
|
|
23
|
+
hasPassword?: boolean;
|
|
24
|
+
archivedAt?: string | null;
|
|
25
|
+
trashedAt?: string | null;
|
|
18
26
|
};
|
|
19
27
|
|
|
28
|
+
const SOCIAL_FRAME_AT_MS = 350;
|
|
29
|
+
|
|
20
30
|
export type PreferredThumbnailVariant = "still" | "animated";
|
|
21
31
|
|
|
22
32
|
export function preferredThumbnailVariant(
|
|
@@ -81,16 +91,70 @@ function absoluteUrl(value: string, origin: string | null): string {
|
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
|
|
94
|
+
function appPath(path: string, basePath: string): string {
|
|
95
|
+
const normalizedBasePath = basePath.trim().replace(/\/+$/, "");
|
|
96
|
+
return normalizedBasePath ? `${normalizedBasePath}${path}` : path;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function canUseGeneratedSocialFrame(
|
|
100
|
+
recording: ClipsShareMetaRecording | null,
|
|
101
|
+
): recording is ClipsShareMetaRecording & {
|
|
102
|
+
id: string;
|
|
103
|
+
visibility: "public";
|
|
104
|
+
status: "ready";
|
|
105
|
+
} {
|
|
106
|
+
return Boolean(
|
|
107
|
+
recording?.id &&
|
|
108
|
+
recording.visibility === "public" &&
|
|
109
|
+
recording.status === "ready" &&
|
|
110
|
+
!recording.hasPassword &&
|
|
111
|
+
!recording.archivedAt &&
|
|
112
|
+
!recording.trashedAt,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function resolveClipsSocialImageUrl(options: {
|
|
117
|
+
recording: ClipsShareMetaRecording | null;
|
|
118
|
+
origin?: string | null;
|
|
119
|
+
basePath?: string;
|
|
120
|
+
}): string | undefined {
|
|
121
|
+
const { recording, origin = null, basePath = "" } = options;
|
|
122
|
+
if (recording?.hasPassword) return undefined;
|
|
123
|
+
|
|
124
|
+
const storedImage = preferredSocialImage(recording);
|
|
125
|
+
|
|
126
|
+
if (storedImage) {
|
|
127
|
+
if (recording?.id && recording.visibility === "public") {
|
|
128
|
+
return absoluteUrl(
|
|
129
|
+
appPath(`/api/thumbnail/${encodeURIComponent(recording.id)}`, basePath),
|
|
130
|
+
origin,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return absoluteUrl(storedImage, origin);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!origin || !canUseGeneratedSocialFrame(recording)) return undefined;
|
|
137
|
+
|
|
138
|
+
return buildAgentApiUrls(recording.id, {
|
|
139
|
+
origin,
|
|
140
|
+
basePath,
|
|
141
|
+
}).frameUrl(SOCIAL_FRAME_AT_MS);
|
|
142
|
+
}
|
|
143
|
+
|
|
84
144
|
export function buildClipsShareMeta(options: {
|
|
85
145
|
recording: ClipsShareMetaRecording | null;
|
|
86
146
|
origin?: string | null;
|
|
147
|
+
basePath?: string;
|
|
87
148
|
shareUrl?: string | null;
|
|
88
149
|
}): SocialMetaDescriptor[] {
|
|
89
|
-
const { recording, origin = null, shareUrl = null } = options;
|
|
150
|
+
const { recording, origin = null, basePath = "", shareUrl = null } = options;
|
|
90
151
|
const title = clipsSharePageTitle(recording?.title);
|
|
91
152
|
const description = clipsShareDescription(recording);
|
|
92
|
-
const
|
|
93
|
-
|
|
153
|
+
const absoluteImage = resolveClipsSocialImageUrl({
|
|
154
|
+
recording,
|
|
155
|
+
origin,
|
|
156
|
+
basePath,
|
|
157
|
+
});
|
|
94
158
|
const alt = hasGeneratedTitle(recording?.title)
|
|
95
159
|
? recording!.title!.trim()
|
|
96
160
|
: AGENT_NATIVE_SOCIAL_IMAGE_ALT;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { getRequestUserEmail } from "@agent-native/core/server/request-context";
|
|
2
3
|
import { accessFilter } from "@agent-native/core/sharing";
|
|
3
4
|
import {
|
|
4
5
|
and,
|
|
5
6
|
asc,
|
|
6
7
|
eq,
|
|
7
8
|
inArray,
|
|
9
|
+
isNotNull,
|
|
8
10
|
isNull,
|
|
9
11
|
notInArray,
|
|
10
12
|
or,
|
|
@@ -15,6 +17,11 @@ import { z } from "zod";
|
|
|
15
17
|
import { getDb, schema } from "../server/db/index.js";
|
|
16
18
|
import { documentDiscoveryFilter } from "../server/lib/documents.js";
|
|
17
19
|
import type { ListContentDatabasesResponse } from "../shared/api.js";
|
|
20
|
+
import {
|
|
21
|
+
listContentOrganizationMemberships,
|
|
22
|
+
normalizeContentSpaceEmail,
|
|
23
|
+
resolveContentSpaceAccess,
|
|
24
|
+
} from "./_content-space-access.js";
|
|
18
25
|
import { documentDiscoveryPagination } from "./_document-discovery-query.js";
|
|
19
26
|
|
|
20
27
|
const DEFAULT_CONTENT_DATABASE_DISCOVERY_LIMIT = 50;
|
|
@@ -27,7 +34,7 @@ export class ContentDatabaseResolutionError extends Error {}
|
|
|
27
34
|
|
|
28
35
|
export default defineAction({
|
|
29
36
|
description:
|
|
30
|
-
"Discover one bounded page of ordinary Content databases the user can access from their live title and user-authored description. Returns stable database, document, and space IDs with explicit pagination; follow nextOffset until hasMore is false. Use exact filters before reading a selected database's schema.",
|
|
37
|
+
"Discover one bounded page of ordinary Content databases the user can access from their live title and user-authored description. Returns stable database, document, and space IDs with explicit pagination; follow nextOffset until hasMore is false. Use exact filters before reading a selected database's schema. Set includeSystemCollections to classify Files, Favorites, Workspaces, and other system chrome separately from ordinary databases.",
|
|
31
38
|
schema: z.object({
|
|
32
39
|
spaceId: z
|
|
33
40
|
.string()
|
|
@@ -39,6 +46,12 @@ export default defineAction({
|
|
|
39
46
|
.min(1)
|
|
40
47
|
.optional()
|
|
41
48
|
.describe("Exact Content database ID to resolve."),
|
|
49
|
+
includeSystemCollections: z
|
|
50
|
+
.boolean()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe(
|
|
53
|
+
"Return system-role databases in systemCollections instead of treating them as ordinary databases.",
|
|
54
|
+
),
|
|
42
55
|
documentId: z
|
|
43
56
|
.string()
|
|
44
57
|
.min(1)
|
|
@@ -80,7 +93,21 @@ export default defineAction({
|
|
|
80
93
|
readOnly: true,
|
|
81
94
|
publicAgent: { expose: true, readOnly: true, requiresAuth: true },
|
|
82
95
|
run: async (args): Promise<ListContentDatabasesResponse> => {
|
|
96
|
+
if (args.includeSystemCollections && !args.spaceId) {
|
|
97
|
+
throw new ContentDatabaseResolutionError(
|
|
98
|
+
"An exact spaceId is required to inventory system collections.",
|
|
99
|
+
);
|
|
100
|
+
}
|
|
83
101
|
const db = getDb();
|
|
102
|
+
const requestUserEmail = getRequestUserEmail();
|
|
103
|
+
if (!requestUserEmail) throw new Error("no authenticated user");
|
|
104
|
+
const normalizedUserEmail = normalizeContentSpaceEmail(requestUserEmail);
|
|
105
|
+
const authorizedOrganizationIds = (
|
|
106
|
+
await listContentOrganizationMemberships(normalizedUserEmail)
|
|
107
|
+
).map((membership) => membership.orgId);
|
|
108
|
+
if (args.spaceId) {
|
|
109
|
+
await resolveContentSpaceAccess(args.spaceId, "viewer", { db });
|
|
110
|
+
}
|
|
84
111
|
const query = args.query?.trim();
|
|
85
112
|
const pattern = query ? `%${escapeLike(query.toLowerCase())}%` : null;
|
|
86
113
|
const exactTitle = args.title?.toLowerCase();
|
|
@@ -160,6 +187,19 @@ export default defineAction({
|
|
|
160
187
|
isNull(schema.documents.hideFromSearch),
|
|
161
188
|
),
|
|
162
189
|
isNull(schema.contentDatabases.deletedAt),
|
|
190
|
+
isNull(schema.contentSpaces.archivedAt),
|
|
191
|
+
or(
|
|
192
|
+
isNull(schema.contentDatabases.spaceId),
|
|
193
|
+
and(
|
|
194
|
+
isNotNull(schema.contentSpaces.id),
|
|
195
|
+
or(
|
|
196
|
+
sql`LOWER(${schema.contentSpaces.ownerEmail}) = ${normalizedUserEmail}`,
|
|
197
|
+
authorizedOrganizationIds.length > 0
|
|
198
|
+
? inArray(schema.contentSpaces.orgId, authorizedOrganizationIds)
|
|
199
|
+
: undefined,
|
|
200
|
+
),
|
|
201
|
+
),
|
|
202
|
+
),
|
|
163
203
|
isNull(schema.contentDatabases.systemRole),
|
|
164
204
|
args.spaceId
|
|
165
205
|
? eq(schema.contentDatabases.spaceId, args.spaceId)
|
|
@@ -206,6 +246,10 @@ export default defineAction({
|
|
|
206
246
|
schema.documents,
|
|
207
247
|
eq(schema.contentDatabases.documentId, schema.documents.id),
|
|
208
248
|
)
|
|
249
|
+
.leftJoin(
|
|
250
|
+
schema.contentSpaces,
|
|
251
|
+
eq(schema.contentDatabases.spaceId, schema.contentSpaces.id),
|
|
252
|
+
)
|
|
209
253
|
.where(where)
|
|
210
254
|
.orderBy(
|
|
211
255
|
asc(schema.documents.position),
|
|
@@ -252,10 +296,51 @@ export default defineAction({
|
|
|
252
296
|
schema.documents,
|
|
253
297
|
eq(schema.contentDatabases.documentId, schema.documents.id),
|
|
254
298
|
)
|
|
299
|
+
.leftJoin(
|
|
300
|
+
schema.contentSpaces,
|
|
301
|
+
eq(schema.contentDatabases.spaceId, schema.contentSpaces.id),
|
|
302
|
+
)
|
|
255
303
|
.where(where)
|
|
256
304
|
)[0]?.count ?? 0,
|
|
257
305
|
);
|
|
258
306
|
|
|
307
|
+
const systemCollections = args.includeSystemCollections
|
|
308
|
+
? await db
|
|
309
|
+
.select({
|
|
310
|
+
databaseId: schema.contentDatabases.id,
|
|
311
|
+
documentId: schema.contentDatabases.documentId,
|
|
312
|
+
title: schema.documents.title,
|
|
313
|
+
spaceId: schema.contentDatabases.spaceId,
|
|
314
|
+
spaceName: schema.contentSpaces.name,
|
|
315
|
+
spaceKind: schema.contentSpaces.kind,
|
|
316
|
+
systemRole: schema.contentDatabases.systemRole,
|
|
317
|
+
})
|
|
318
|
+
.from(schema.contentDatabases)
|
|
319
|
+
.innerJoin(
|
|
320
|
+
schema.documents,
|
|
321
|
+
eq(schema.contentDatabases.documentId, schema.documents.id),
|
|
322
|
+
)
|
|
323
|
+
.leftJoin(
|
|
324
|
+
schema.contentSpaces,
|
|
325
|
+
eq(schema.contentDatabases.spaceId, schema.contentSpaces.id),
|
|
326
|
+
)
|
|
327
|
+
.where(
|
|
328
|
+
and(
|
|
329
|
+
accessFilter(schema.documents, schema.documentShares),
|
|
330
|
+
isNull(schema.documents.trashedAt),
|
|
331
|
+
isNull(schema.contentDatabases.deletedAt),
|
|
332
|
+
isNull(schema.contentSpaces.archivedAt),
|
|
333
|
+
isNotNull(schema.contentSpaces.id),
|
|
334
|
+
isNotNull(schema.contentDatabases.systemRole),
|
|
335
|
+
eq(schema.contentDatabases.spaceId, args.spaceId!),
|
|
336
|
+
),
|
|
337
|
+
)
|
|
338
|
+
.orderBy(
|
|
339
|
+
asc(schema.documents.position),
|
|
340
|
+
asc(schema.contentDatabases.id),
|
|
341
|
+
)
|
|
342
|
+
: undefined;
|
|
343
|
+
|
|
259
344
|
return {
|
|
260
345
|
databases,
|
|
261
346
|
pagination: documentDiscoveryPagination({
|
|
@@ -264,6 +349,15 @@ export default defineAction({
|
|
|
264
349
|
totalItems,
|
|
265
350
|
returnedItems: databases.length,
|
|
266
351
|
}),
|
|
352
|
+
...(systemCollections
|
|
353
|
+
? {
|
|
354
|
+
systemCollections: systemCollections.map((collection) => ({
|
|
355
|
+
...collection,
|
|
356
|
+
title: collection.title ?? "Untitled database",
|
|
357
|
+
systemRole: collection.systemRole!,
|
|
358
|
+
})),
|
|
359
|
+
}
|
|
360
|
+
: {}),
|
|
267
361
|
};
|
|
268
362
|
},
|
|
269
363
|
});
|
|
@@ -1082,6 +1082,16 @@ export interface ContentDatabaseSummary {
|
|
|
1082
1082
|
description: string;
|
|
1083
1083
|
}
|
|
1084
1084
|
|
|
1085
|
+
export interface ContentSystemCollectionSummary {
|
|
1086
|
+
databaseId: string;
|
|
1087
|
+
documentId: string;
|
|
1088
|
+
title: string;
|
|
1089
|
+
spaceId: string | null;
|
|
1090
|
+
spaceName: string | null;
|
|
1091
|
+
spaceKind: string | null;
|
|
1092
|
+
systemRole: string;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1085
1095
|
export interface ContentDatabaseDescriptionResponse {
|
|
1086
1096
|
database: ContentDatabase;
|
|
1087
1097
|
contextPath: ContentContextPathEntry[];
|
|
@@ -1091,6 +1101,7 @@ export interface ContentDatabaseDescriptionResponse {
|
|
|
1091
1101
|
export interface ListContentDatabasesResponse {
|
|
1092
1102
|
databases: ContentDatabaseSummary[];
|
|
1093
1103
|
pagination: DocumentDiscoveryPagination;
|
|
1104
|
+
systemCollections?: ContentSystemCollectionSummary[];
|
|
1094
1105
|
}
|
|
1095
1106
|
|
|
1096
1107
|
export interface TrashedContentDatabaseSummary {
|
|
@@ -63,7 +63,7 @@ decisions, feedback, agent runs, and provider audit records.
|
|
|
63
63
|
| `evaluate-triage-item` | Append a decision. |
|
|
64
64
|
| `record-triage-feedback` | Capture human correction for learning. |
|
|
65
65
|
| `approve-factory-item` | Explicitly authorize one bounded run. |
|
|
66
|
-
| `start-builder-for-item` | Govern clear-bug dispatch through Slack or Builder API. |
|
|
66
|
+
| `start-builder-for-item` | Govern clear-bug dispatch through Slack or Builder API, or record a skip reason. |
|
|
67
67
|
| `govern-agent-native-pull-request` | Apply PR evidence and ownership gates. |
|
|
68
68
|
| `list-factory-automations` / `save-factory-automation` / `run-factory-automation` | Inspect or edit org-owned automations. |
|
|
69
69
|
| `list-factory-audit` | Inspect automation runs, evidence, decisions, and provider actions. |
|
|
@@ -41,6 +41,10 @@ export default defineAction({
|
|
|
41
41
|
timezone: meta.timezone ?? null,
|
|
42
42
|
condition: meta.condition ?? null,
|
|
43
43
|
createdBy: meta.createdBy ?? null,
|
|
44
|
+
updatedAt:
|
|
45
|
+
Number.isFinite(resource.updatedAt) && resource.updatedAt > 0
|
|
46
|
+
? new Date(resource.updatedAt).toISOString()
|
|
47
|
+
: null,
|
|
44
48
|
canUpdate,
|
|
45
49
|
runs: await listAutomationRuns({
|
|
46
50
|
owners: [resource.owner],
|