@agent-native/core 0.141.5 → 0.141.7
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/analytics/.agents/skills/dashboard-management/SKILL.md +3 -14
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +20 -8
- package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +5 -5
- package/corpus/templates/analytics/AGENTS.md +2 -2
- package/corpus/templates/analytics/actions/compose-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/get-first-party-analytics-health.ts +15 -1
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +135 -0
- package/corpus/templates/analytics/actions/navigate.ts +1 -1
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -2
- package/corpus/templates/analytics/actions/update-dashboard.ts +0 -1
- package/corpus/templates/analytics/actions/view-screen.ts +0 -20
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +5 -5
- package/corpus/templates/analytics/app/i18n-data.ts +330 -90
- package/corpus/templates/analytics/app/pages/Agents.tsx +0 -3
- package/corpus/templates/analytics/app/pages/DataSources.tsx +66 -30
- package/corpus/templates/analytics/app/pages/Settings.tsx +22 -43
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +23 -20
- package/corpus/templates/analytics/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/analytics/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-now-repair-automatically-after-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-settings-no-longer-includes-an-unnecessary-about-section.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +1 -1
- package/corpus/templates/analytics/netlify.toml +4 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +109 -0
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery.sql +104 -0
- package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +342 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -2
- package/corpus/templates/analytics/server/lib/analytics-rollup-lock.ts +8 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +11 -29
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +55 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +1058 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +151 -46
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +15 -9
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +59 -17
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -4
- package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +61 -0
- package/corpus/templates/analytics/server/plugins/db.ts +58 -187
- package/corpus/templates/analytics/server/routes/api/analytics-rollups/backfill.post.ts +53 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +8 -6
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +16 -1
- package/corpus/templates/assets/AGENTS.md +1 -0
- package/corpus/templates/assets/actions/_helpers.ts +12 -0
- package/corpus/templates/assets/actions/generate-image.ts +9 -3
- package/corpus/templates/assets/actions/import-style-from-url.ts +115 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
- package/corpus/templates/assets/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/assets/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/assets/app/routes/settings.tsx +5 -0
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/assets/changelog/2026-08-05-brand-kits-can-import-a-website-s-hydrated-visual-language-a.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-05-generated-images-now-hand-off-embeddable-previews-to-other-w.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +58 -0
- package/corpus/templates/assets/shared/api.ts +12 -0
- package/corpus/templates/brain/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/app/routes.ts +1 -1
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +7 -7
- package/corpus/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/chat/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-08-05-clips-overlays-now-use-clean-surfaces-without-clipped-shadow.md +6 -0
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +2 -2
- package/corpus/templates/clips/desktop/src/styles.css +3 -54
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -3
- package/corpus/templates/content/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/content/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/content/e2e/global-setup.ts +1 -1
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -1
- package/corpus/templates/design/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/design/actions/get-design-system.ts +3 -1
- package/corpus/templates/design/actions/import-from-url.ts +6 -5
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +2 -2
- package/corpus/templates/design/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/design/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-08-05-missing-design-systems-now-return-a-clear-not-found-response.md +6 -0
- package/corpus/templates/design/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-de.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +1 -1
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/factory/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/factory/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/factory/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/macros/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/mail/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +3 -1
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/slides/actions/import-from-url.ts +6 -6
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +3 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -1
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +9 -3
- package/corpus/templates/slides/app/context/DeckContext.tsx +71 -20
- package/corpus/templates/slides/app/global.css +6 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +5 -5
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +9 -5
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -0
- package/corpus/templates/slides/app/pages/Index.tsx +16 -5
- package/corpus/templates/slides/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/slides/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-08-05-failed-deck-creation-and-reference-uploads-now-recover-clean.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-new-presentation-prompts-now-clearly-describe-presentation-g.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-slides-recover-completed-generation-results-after-a-sync-hic.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-st.md +6 -0
- package/corpus/templates/tasks/app/components/layout/Header.tsx +3 -1
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/tasks/app/routes/settings.$.tsx +1 -0
- package/dist/agent/engine/ai-sdk-engine.js +49 -3
- package/dist/agent/production-agent.d.ts +1 -0
- package/dist/agent/production-agent.js +8 -0
- package/dist/agent/types.d.ts +7 -0
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/agent-chat-adapter.d.ts +1 -1
- package/dist/client/agent-chat-adapter.js +30 -3
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +1 -1
- package/dist/client/agent-page/AgentWorkspaceContent.js +13 -13
- package/dist/client/chat/run-recovery.d.ts +2 -1
- package/dist/client/chat/run-recovery.js +14 -3
- package/dist/client/embed-auth.js +6 -2
- package/dist/client/error-format.d.ts +1 -0
- package/dist/client/error-format.js +16 -2
- package/dist/client/integrations/IntegrationsPanel.js +40 -6
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/TeamPage.js +92 -72
- package/dist/client/require-session.d.ts +1 -1
- package/dist/client/require-session.js +3 -3
- package/dist/client/resources/use-mcp-servers.d.ts +5 -0
- package/dist/client/resources/use-mcp-servers.js +36 -0
- package/dist/client/settings/AccountSettingsCard.js +40 -35
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.d.ts +3 -1
- package/dist/client/settings/DemoModeSection.js +4 -1
- package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
- package/dist/client/settings/SchedulingTimezoneField.d.ts +3 -1
- package/dist/client/settings/SchedulingTimezoneField.js +9 -5
- package/dist/client/settings/SettingsPanel.d.ts +4 -1
- package/dist/client/settings/SettingsPanel.js +21 -21
- package/dist/client/settings/SettingsTabsPage.d.ts +2 -2
- package/dist/client/settings/SettingsTabsPage.js +98 -45
- package/dist/client/settings/VoiceTranscriptionSection.js +6 -1
- package/dist/client/settings/useSettingsPanelController.js +47 -8
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/ingestion/website.d.ts +30 -0
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.js +5 -0
- package/dist/mcp-client/oauth-routes.js +1 -1
- package/dist/mcp-client/routes.d.ts +1 -0
- package/dist/mcp-client/routes.js +49 -0
- package/dist/navigation/index.js +16 -5
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/call-agent.js +11 -0
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +9 -7
- package/dist/server/identity-sso.js +2 -1
- package/dist/server/onboarding-html.js +57 -34
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/sign-in-journey.d.ts +5 -2
- package/dist/shared/sign-in-journey.js +10 -4
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +7 -7
- package/dist/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/dist/templates/chat/app/routes/settings.$.tsx +1 -0
- package/dist/templates/chat/app/routes/team.tsx +1 -1
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/docs/content/authentication.mdx +4 -5
- package/docs/content/template-analytics-developers.mdx +1 -1
- package/docs/content/template-calendar-developers.mdx +1 -1
- package/docs/content/template-chat-developers.mdx +2 -2
- package/docs/content/template-content-developers.mdx +1 -1
- package/docs/content/template-mail-developers.mdx +1 -1
- package/docs/content/template-plan-developers.mdx +1 -1
- package/docs/content/toolkit-command-navigation.mdx +6 -6
- package/docs/content/toolkit-org-team.mdx +1 -1
- package/docs/content/toolkit-settings.mdx +8 -8
- package/docs/content/toolkit-setup-connections.mdx +1 -1
- package/package.json +1 -1
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +7 -7
- package/src/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/src/templates/chat/app/routes/settings.$.tsx +1 -0
- package/src/templates/chat/app/routes/team.tsx +1 -1
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +0 -62
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +0 -369
- package/corpus/templates/analytics/actions/list-dashboard-templates.ts +0 -47
- package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +0 -34
- package/corpus/templates/analytics/app/routes/catalog.tsx +0 -240
- package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-stay-complete-and-atomic.md +0 -6
- package/corpus/templates/analytics/changelog/2026-08-05-historical-rollups-stay-complete-while-live-events-arrive.md +0 -6
- package/src/templates/default/actions/navigate.spec.ts +0 -53
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deferMigration,
|
|
3
3
|
ensureAdditiveColumns,
|
|
4
|
-
getDialect,
|
|
5
4
|
getDbExec,
|
|
6
|
-
isPostgres,
|
|
7
5
|
runMigrations,
|
|
8
6
|
} from "@agent-native/core/db";
|
|
9
7
|
import { isInBackgroundFunctionRuntime } from "@agent-native/core/server";
|
|
@@ -12,7 +10,7 @@ import { isInBackgroundFunctionRuntime } from "@agent-native/core/server";
|
|
|
12
10
|
// startup so the dashboard / analysis share actions know where to dispatch.
|
|
13
11
|
import "../db/index.js";
|
|
14
12
|
import * as schema from "../db/schema.js";
|
|
15
|
-
import {
|
|
13
|
+
import { isHistoricalAnalyticsRollupBackfillComplete } from "../jobs/analytics-rollup-backfill.js";
|
|
16
14
|
import { repairPersistedFirstPartyDashboardQueries } from "../lib/first-party-dashboard-repair.js";
|
|
17
15
|
|
|
18
16
|
/**
|
|
@@ -33,182 +31,6 @@ function isDrizzleTable(value: unknown): value is object {
|
|
|
33
31
|
|
|
34
32
|
const schemaTables = Object.values(schema).filter(isDrizzleTable);
|
|
35
33
|
|
|
36
|
-
const ANALYTICS_ROLLUP_BACKFILL_STATEMENTS = {
|
|
37
|
-
postgres: [
|
|
38
|
-
`
|
|
39
|
-
INSERT INTO analytics_event_daily_rollups (
|
|
40
|
-
id, tenant_key, owner_email, org_id, event_date, event_name,
|
|
41
|
-
app, template, event_count
|
|
42
|
-
)
|
|
43
|
-
SELECT
|
|
44
|
-
md5(random()::text || clock_timestamp()::text), tenant_key,
|
|
45
|
-
MIN(owner_email), MIN(org_id), event_date, event_name, app, template,
|
|
46
|
-
COUNT(*)::INTEGER
|
|
47
|
-
FROM (
|
|
48
|
-
SELECT
|
|
49
|
-
CASE
|
|
50
|
-
WHEN org_id IS NOT NULL AND org_id <> '' THEN 'org:' || org_id
|
|
51
|
-
ELSE 'user:' || owner_email
|
|
52
|
-
END AS tenant_key,
|
|
53
|
-
owner_email,
|
|
54
|
-
org_id,
|
|
55
|
-
COALESCE(NULLIF(event_date, ''), substr(timestamp, 1, 10)) AS event_date,
|
|
56
|
-
event_name,
|
|
57
|
-
COALESCE(app, '') AS app,
|
|
58
|
-
COALESCE(template, '') AS template
|
|
59
|
-
FROM analytics_events
|
|
60
|
-
) AS historical_events
|
|
61
|
-
WHERE event_date <> ''
|
|
62
|
-
GROUP BY tenant_key, event_date, event_name, app, template
|
|
63
|
-
ON CONFLICT (tenant_key, event_date, event_name, app, template)
|
|
64
|
-
DO UPDATE SET event_count = GREATEST(
|
|
65
|
-
analytics_event_daily_rollups.event_count,
|
|
66
|
-
EXCLUDED.event_count
|
|
67
|
-
)
|
|
68
|
-
`,
|
|
69
|
-
`
|
|
70
|
-
INSERT INTO analytics_user_days (
|
|
71
|
-
id, tenant_key, owner_email, org_id, event_date, user_key
|
|
72
|
-
)
|
|
73
|
-
SELECT
|
|
74
|
-
md5(random()::text || clock_timestamp()::text), tenant_key,
|
|
75
|
-
owner_email, org_id, event_date, user_key
|
|
76
|
-
FROM (
|
|
77
|
-
SELECT DISTINCT
|
|
78
|
-
CASE
|
|
79
|
-
WHEN org_id IS NOT NULL AND org_id <> '' THEN 'org:' || org_id
|
|
80
|
-
ELSE 'user:' || owner_email
|
|
81
|
-
END AS tenant_key,
|
|
82
|
-
owner_email,
|
|
83
|
-
org_id,
|
|
84
|
-
COALESCE(NULLIF(event_date, ''), substr(timestamp, 1, 10)) AS event_date,
|
|
85
|
-
user_key
|
|
86
|
-
FROM analytics_events
|
|
87
|
-
WHERE user_key IS NOT NULL AND TRIM(user_key) <> ''
|
|
88
|
-
) AS historical_user_days
|
|
89
|
-
WHERE event_date <> ''
|
|
90
|
-
ON CONFLICT (tenant_key, event_date, user_key) DO NOTHING
|
|
91
|
-
`,
|
|
92
|
-
],
|
|
93
|
-
sqlite: [
|
|
94
|
-
`
|
|
95
|
-
INSERT INTO analytics_event_daily_rollups (
|
|
96
|
-
id, tenant_key, owner_email, org_id, event_date, event_name,
|
|
97
|
-
app, template, event_count
|
|
98
|
-
)
|
|
99
|
-
SELECT
|
|
100
|
-
lower(hex(randomblob(16))), tenant_key, MIN(owner_email), MIN(org_id),
|
|
101
|
-
event_date, event_name, app, template, COUNT(*)
|
|
102
|
-
FROM (
|
|
103
|
-
SELECT
|
|
104
|
-
CASE
|
|
105
|
-
WHEN org_id IS NOT NULL AND org_id <> '' THEN 'org:' || org_id
|
|
106
|
-
ELSE 'user:' || owner_email
|
|
107
|
-
END AS tenant_key,
|
|
108
|
-
owner_email,
|
|
109
|
-
org_id,
|
|
110
|
-
COALESCE(NULLIF(event_date, ''), substr(timestamp, 1, 10)) AS event_date,
|
|
111
|
-
event_name,
|
|
112
|
-
COALESCE(app, '') AS app,
|
|
113
|
-
COALESCE(template, '') AS template
|
|
114
|
-
FROM analytics_events
|
|
115
|
-
) AS historical_events
|
|
116
|
-
WHERE event_date <> ''
|
|
117
|
-
GROUP BY tenant_key, event_date, event_name, app, template
|
|
118
|
-
ON CONFLICT (tenant_key, event_date, event_name, app, template)
|
|
119
|
-
DO UPDATE SET event_count = excluded.event_count
|
|
120
|
-
`,
|
|
121
|
-
`
|
|
122
|
-
INSERT INTO analytics_user_days (
|
|
123
|
-
id, tenant_key, owner_email, org_id, event_date, user_key
|
|
124
|
-
)
|
|
125
|
-
SELECT
|
|
126
|
-
lower(hex(randomblob(16))), tenant_key, owner_email, org_id,
|
|
127
|
-
event_date, user_key
|
|
128
|
-
FROM (
|
|
129
|
-
SELECT DISTINCT
|
|
130
|
-
CASE
|
|
131
|
-
WHEN org_id IS NOT NULL AND org_id <> '' THEN 'org:' || org_id
|
|
132
|
-
ELSE 'user:' || owner_email
|
|
133
|
-
END AS tenant_key,
|
|
134
|
-
owner_email,
|
|
135
|
-
org_id,
|
|
136
|
-
COALESCE(NULLIF(event_date, ''), substr(timestamp, 1, 10)) AS event_date,
|
|
137
|
-
user_key
|
|
138
|
-
FROM analytics_events
|
|
139
|
-
WHERE user_key IS NOT NULL AND TRIM(user_key) <> ''
|
|
140
|
-
) AS historical_user_days
|
|
141
|
-
WHERE event_date <> ''
|
|
142
|
-
ON CONFLICT (tenant_key, event_date, user_key) DO NOTHING
|
|
143
|
-
`,
|
|
144
|
-
],
|
|
145
|
-
} as const;
|
|
146
|
-
|
|
147
|
-
async function runHistoricalAnalyticsRollupBackfill() {
|
|
148
|
-
// Durable agent workers share this plugin bundle with the regular server,
|
|
149
|
-
// but they must not become a second migration runner for an expensive
|
|
150
|
-
// historical scan. The keep-warm/regular server path owns this work.
|
|
151
|
-
if (isInBackgroundFunctionRuntime()) {
|
|
152
|
-
console.info(
|
|
153
|
-
"[db] Deferring historical Analytics rollup backfill from durable background runtime",
|
|
154
|
-
);
|
|
155
|
-
return deferMigration();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const db = getDbExec();
|
|
159
|
-
|
|
160
|
-
if (isPostgres()) {
|
|
161
|
-
if (!db.transaction) {
|
|
162
|
-
throw new Error(
|
|
163
|
-
"Analytics rollup backfill requires a Postgres transaction",
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const result = await db.transaction(async (tx) => {
|
|
168
|
-
// Only one serverless instance should perform the expensive scan. A
|
|
169
|
-
// A try-lock keeps competing cold starts from holding pooled Neon
|
|
170
|
-
// connections while waiting for the winner. A lock loser defers without
|
|
171
|
-
// recording the migration so a failed winner can be retried safely.
|
|
172
|
-
// The monotonic rollup upsert below keeps a live increment from being
|
|
173
|
-
// overwritten if ingest commits during the historical snapshot. Live
|
|
174
|
-
// ingest takes this same lock before inserting its raw event.
|
|
175
|
-
const lockResult = await tx.execute({
|
|
176
|
-
sql: "SELECT pg_try_advisory_xact_lock(hashtextextended(?, 0::bigint)) AS acquired",
|
|
177
|
-
args: [FIRST_PARTY_ANALYTICS_ROLLUP_LOCK_KEY],
|
|
178
|
-
});
|
|
179
|
-
const acquired = lockResult.rows[0]?.acquired;
|
|
180
|
-
if (acquired !== true && acquired !== "t") {
|
|
181
|
-
console.info(
|
|
182
|
-
"[db] Deferring historical Analytics rollup backfill; another instance owns the advisory lock",
|
|
183
|
-
);
|
|
184
|
-
return deferMigration();
|
|
185
|
-
}
|
|
186
|
-
for (const statement of ANALYTICS_ROLLUP_BACKFILL_STATEMENTS.postgres) {
|
|
187
|
-
await tx.execute(statement);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const statements = ANALYTICS_ROLLUP_BACKFILL_STATEMENTS.sqlite;
|
|
194
|
-
if (getDialect() === "d1") {
|
|
195
|
-
if (!db.atomicBatch) {
|
|
196
|
-
throw new Error("D1 analytics rollup backfill requires an atomic batch");
|
|
197
|
-
}
|
|
198
|
-
await db.atomicBatch(statements);
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (!db.transaction) {
|
|
203
|
-
throw new Error(
|
|
204
|
-
"Analytics rollup backfill requires a database transaction",
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
await db.transaction(async (tx) => {
|
|
208
|
-
for (const statement of statements) await tx.execute(statement);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
34
|
// Convention: every new migration below MUST set a unique `name:` slug (see
|
|
213
35
|
// packages/core/src/db/migrations.ts for the full rationale). Version numbers
|
|
214
36
|
// alone are not a safe identity across parallel branches that each extend
|
|
@@ -1548,14 +1370,56 @@ const runAnalyticsMigrations = runMigrations(
|
|
|
1548
1370
|
name: "analytics-query-pressure-daily-key-idx",
|
|
1549
1371
|
sql: `CREATE UNIQUE INDEX IF NOT EXISTS analytics_query_pressure_daily_key_idx ON analytics_query_pressure_daily (tenant_key, event_date, query_class)`,
|
|
1550
1372
|
},
|
|
1551
|
-
//
|
|
1552
|
-
//
|
|
1553
|
-
//
|
|
1373
|
+
// Keep this historical migration name reserved, but record it without a
|
|
1374
|
+
// boot-time run. Scanning analytics_events here makes every concurrent
|
|
1375
|
+
// serverless migration runner hold a database connection for the full
|
|
1376
|
+
// history; v126-v131 continue to maintain the compact tables incrementally.
|
|
1377
|
+
// Any future one-shot backfill must use a new migration identity or an
|
|
1378
|
+
// explicit out-of-band job because this marker is permanently applied.
|
|
1554
1379
|
{
|
|
1555
1380
|
version: 132,
|
|
1556
1381
|
name: "analytics-rollups-historical-backfill",
|
|
1557
1382
|
sql: {},
|
|
1558
|
-
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
version: 133,
|
|
1386
|
+
name: "analytics-rollups-historical-backfill-state",
|
|
1387
|
+
sql: {
|
|
1388
|
+
postgres: `CREATE TABLE IF NOT EXISTS analytics_rollup_backfill_state (
|
|
1389
|
+
id TEXT PRIMARY KEY,
|
|
1390
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
1391
|
+
completed_at TEXT,
|
|
1392
|
+
lease_token TEXT,
|
|
1393
|
+
lease_expires_at TEXT,
|
|
1394
|
+
updated_at TEXT NOT NULL DEFAULT (now()::text)
|
|
1395
|
+
)`,
|
|
1396
|
+
sqlite: `CREATE TABLE IF NOT EXISTS analytics_rollup_backfill_state (
|
|
1397
|
+
id TEXT PRIMARY KEY,
|
|
1398
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
1399
|
+
completed_at TEXT,
|
|
1400
|
+
lease_token TEXT,
|
|
1401
|
+
lease_expires_at TEXT,
|
|
1402
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1403
|
+
)`,
|
|
1404
|
+
},
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
version: 134,
|
|
1408
|
+
name: "analytics-rollups-historical-backfill-repair",
|
|
1409
|
+
sql: {},
|
|
1410
|
+
run: async () => {
|
|
1411
|
+
if (!(await isHistoricalAnalyticsRollupBackfillComplete())) {
|
|
1412
|
+
return deferMigration();
|
|
1413
|
+
}
|
|
1414
|
+
},
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
version: 135,
|
|
1418
|
+
name: "analytics-rollups-historical-backfill-lease",
|
|
1419
|
+
sql: `
|
|
1420
|
+
ALTER TABLE analytics_rollup_backfill_state ADD COLUMN IF NOT EXISTS lease_token TEXT;
|
|
1421
|
+
ALTER TABLE analytics_rollup_backfill_state ADD COLUMN IF NOT EXISTS lease_expires_at TEXT;
|
|
1422
|
+
`,
|
|
1559
1423
|
},
|
|
1560
1424
|
],
|
|
1561
1425
|
{ table: "analytics_migrations" },
|
|
@@ -1572,10 +1436,17 @@ const runAnalyticsMigrations = runMigrations(
|
|
|
1572
1436
|
* swallowed so it can never fail boot.
|
|
1573
1437
|
*/
|
|
1574
1438
|
export default async (nitroApp: any): Promise<void> => {
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1439
|
+
const isScheduledRollupRuntime =
|
|
1440
|
+
(
|
|
1441
|
+
globalThis as typeof globalThis & {
|
|
1442
|
+
__AGENT_NATIVE_ANALYTICS_ROLLUP_BACKFILL_SCHEDULED_RUNTIME__?: boolean;
|
|
1443
|
+
}
|
|
1444
|
+
).__AGENT_NATIVE_ANALYTICS_ROLLUP_BACKFILL_SCHEDULED_RUNTIME__ === true;
|
|
1445
|
+
if (isInBackgroundFunctionRuntime() && !isScheduledRollupRuntime) {
|
|
1446
|
+
// Most durable workers execute signed internal routes against a schema
|
|
1447
|
+
// owned by the regular server. A second migration runner only adds a Neon
|
|
1448
|
+
// pool probe to every worker cold start. The scheduled rollup worker is
|
|
1449
|
+
// the exception because it can be the first post-deploy invocation.
|
|
1579
1450
|
console.info(
|
|
1580
1451
|
"[db] Skipping Analytics migrations in durable background runtime",
|
|
1581
1452
|
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { createError, defineEventHandler, getHeader } from "h3";
|
|
4
|
+
|
|
5
|
+
// guard:allow-action-twin — external cron endpoint authenticates scheduled callers before invoking the rollup job.
|
|
6
|
+
import { runAnalyticsRollupBackfillOnce } from "../../../jobs/analytics-rollup-backfill";
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
var __AGENT_NATIVE_ANALYTICS_ROLLUP_BACKFILL_SCHEDULED_RUNTIME__:
|
|
10
|
+
| boolean
|
|
11
|
+
| undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function scheduledFunctionRuntime(): boolean {
|
|
15
|
+
return (
|
|
16
|
+
globalThis.__AGENT_NATIVE_ANALYTICS_ROLLUP_BACKFILL_SCHEDULED_RUNTIME__ ===
|
|
17
|
+
true
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function cronSecret(): string | null {
|
|
22
|
+
const secret = process.env.ANALYTICS_ROLLUP_BACKFILL_CRON_SECRET?.trim();
|
|
23
|
+
return secret ? secret : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function headerMatchesSecret(
|
|
27
|
+
header: string | undefined,
|
|
28
|
+
secret: string,
|
|
29
|
+
): boolean {
|
|
30
|
+
const expected = `Bearer ${secret}`;
|
|
31
|
+
const value = header?.trim() ?? "";
|
|
32
|
+
if (value.length !== expected.length) return false;
|
|
33
|
+
return timingSafeEqual(Buffer.from(value), Buffer.from(expected));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default defineEventHandler(async (event) => {
|
|
37
|
+
const secret = cronSecret();
|
|
38
|
+
const scheduledRuntime = scheduledFunctionRuntime();
|
|
39
|
+
const authenticatedHeader =
|
|
40
|
+
secret !== null &&
|
|
41
|
+
headerMatchesSecret(getHeader(event, "authorization"), secret);
|
|
42
|
+
if (!scheduledRuntime && !authenticatedHeader) {
|
|
43
|
+
throw createError({
|
|
44
|
+
statusCode: secret ? 401 : 503,
|
|
45
|
+
statusMessage: secret
|
|
46
|
+
? "Unauthorized"
|
|
47
|
+
: "ANALYTICS_ROLLUP_BACKFILL_CRON_SECRET is required",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = await runAnalyticsRollupBackfillOnce();
|
|
52
|
+
return { ok: true, ...result };
|
|
53
|
+
});
|
|
@@ -27,8 +27,9 @@ or generated image/video assets that another app can reference by ID and URL.
|
|
|
27
27
|
Pass `mediaType: "image"` by default, or `mediaType: "video"` for video
|
|
28
28
|
libraries.
|
|
29
29
|
- Use unattended actions when the agent already knows what to do:
|
|
30
|
-
`search-assets`, `list-assets`, `
|
|
31
|
-
`generate-video`, `refresh-generation-run`, and
|
|
30
|
+
`search-assets`, `list-assets`, `import-style-from-url`, `generate-image`,
|
|
31
|
+
`generate-image-batch`, `generate-video`, `refresh-generation-run`, and
|
|
32
|
+
`export-asset`.
|
|
32
33
|
- In chat, consume composer `@` references as structured generation inputs:
|
|
33
34
|
`brand-kit` maps to `libraryId`, `preset` maps to `presetId`, and
|
|
34
35
|
`media-type` chooses image generation versus video generation. If no mention
|
|
@@ -94,10 +95,11 @@ or generated image/video assets that another app can reference by ID and URL.
|
|
|
94
95
|
when they want a chat preloaded with the session context.
|
|
95
96
|
|
|
96
97
|
For short vague prompts, enhance conservatively with library style context while
|
|
97
|
-
preserving the user's original prompt in run metadata.
|
|
98
|
-
`
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
preserving the user's original prompt in run metadata. If a public website is
|
|
99
|
+
the style source, call `import-style-from-url` first so the library keeps the
|
|
100
|
+
hydrated browser-derived design brief. Use `analyze-collection-style` when a
|
|
101
|
+
collection needs upgraded vision brand analysis from image references before
|
|
102
|
+
generation. Brand QA scoring and best-of-N selection are deferred.
|
|
101
103
|
|
|
102
104
|
## Video Workflows
|
|
103
105
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: library-management
|
|
3
|
-
description: Schema, CRUD, sharing, and cascade-delete patterns for asset libraries, collections, and assets.
|
|
3
|
+
description: Schema, CRUD, sharing, URL style imports, and cascade-delete patterns for asset libraries, collections, and assets. Use when managing a library or importing visual brand evidence from a URL.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Library management
|
|
@@ -118,6 +118,21 @@ for the exact logo. Imported assets are stored as `status: "reference"` with
|
|
|
118
118
|
`sourceUrl` provenance, so downstream generation, preset boards, and logo
|
|
119
119
|
compositing can use them like uploaded reference assets.
|
|
120
120
|
|
|
121
|
+
## Importing a rendered visual system
|
|
122
|
+
|
|
123
|
+
Use `import-style-from-url` when a public website should contribute more than
|
|
124
|
+
images to a library or collection. It uses the same layered browser extractor
|
|
125
|
+
as Design and Slides, so CSS-in-JS, Tailwind, hydration, web fonts, computed
|
|
126
|
+
colors, component styles, spacing, radii, shadows, CSS variables, and logo
|
|
127
|
+
references are captured from the live cascade. The action persists a bounded
|
|
128
|
+
`designMd` summary plus structured fields in `styleBrief`, with the source URL
|
|
129
|
+
and any browser/static-fallback warnings preserved for provenance.
|
|
130
|
+
|
|
131
|
+
Prefer this action over copying raw HTML into a style brief. If the result is
|
|
132
|
+
`partial`, the structured values are still usable but the warnings must remain
|
|
133
|
+
visible to the agent; `failed` is an error and must not be treated as an empty
|
|
134
|
+
style brief.
|
|
135
|
+
|
|
121
136
|
## When to add a collection
|
|
122
137
|
|
|
123
138
|
Collections are optional. Most users won't create them. Use them when:
|
|
@@ -84,6 +84,7 @@ Uncommon actions stay discoverable through `tool-search`.
|
|
|
84
84
|
| `duplicate-library` | Make a private copy of a Brand Kit |
|
|
85
85
|
| `list-assets` / `search-assets` | Browse or search assets in accessible kits |
|
|
86
86
|
| `import-asset-from-url` | Ingest external brand or blog imagery as a reference asset |
|
|
87
|
+
| `import-style-from-url` | Render a website and merge its design.md-style visual language into a library or collection |
|
|
87
88
|
| `set-canonical-logo` | Pin the kit's pixel-perfect logo |
|
|
88
89
|
| `list-generation-presets` | List repeatable output formats before generating |
|
|
89
90
|
| `create-generation-preset` / `update-generation-preset` | Author preset format, references, `includeLogo`, skeleton |
|
|
@@ -97,6 +97,18 @@ export function assetUrls(asset: {
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export function imageArtifactLinks(input: {
|
|
101
|
+
id: string;
|
|
102
|
+
runId: string;
|
|
103
|
+
previewUrl: string;
|
|
104
|
+
downloadUrl: string;
|
|
105
|
+
}) {
|
|
106
|
+
return [
|
|
107
|
+
`previewUrl: ${input.previewUrl} (ID: ${input.id}, Run: ${input.runId})`,
|
|
108
|
+
`downloadUrl: ${input.downloadUrl}`,
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
|
|
100
112
|
export function serializeLibrary(row: any) {
|
|
101
113
|
return {
|
|
102
114
|
id: row.id,
|
|
@@ -69,6 +69,7 @@ import {
|
|
|
69
69
|
type StyleBrief,
|
|
70
70
|
} from "../shared/api.js";
|
|
71
71
|
import {
|
|
72
|
+
imageArtifactLinks,
|
|
72
73
|
requireGenerationSessionInLibrary,
|
|
73
74
|
serializeAsset,
|
|
74
75
|
} from "./_helpers.js";
|
|
@@ -1109,9 +1110,14 @@ export default defineAction({
|
|
|
1109
1110
|
...serialized,
|
|
1110
1111
|
runId,
|
|
1111
1112
|
artifactType: "image",
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1113
|
+
// Cross-app callers embed the artifact in HTML. `url` is the Assets
|
|
1114
|
+
// detail page; previewUrl is the actual media response.
|
|
1115
|
+
Artifacts: imageArtifactLinks({
|
|
1116
|
+
id: asset.id,
|
|
1117
|
+
runId,
|
|
1118
|
+
previewUrl: serialized.previewUrl,
|
|
1119
|
+
downloadUrl: serialized.downloadUrl,
|
|
1120
|
+
}),
|
|
1115
1121
|
...creativeContextProvenance,
|
|
1116
1122
|
};
|
|
1117
1123
|
} catch (err) {
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
|
+
import {
|
|
4
|
+
extractRenderedDesignSystemFromUrl,
|
|
5
|
+
styleBriefFromRenderedDesign,
|
|
6
|
+
} from "@agent-native/creative-context/server";
|
|
7
|
+
import { eq } from "drizzle-orm";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
11
|
+
import { nowIso, parseJson, stringifyJson } from "../server/lib/json.js";
|
|
12
|
+
import type { StyleBrief } from "../shared/api.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Render a public website once and merge its computed visual language into an
|
|
16
|
+
* Assets library or collection style brief. This intentionally shares the
|
|
17
|
+
* exact browser extractor used by Design and Slides instead of maintaining a
|
|
18
|
+
* second image-only or static-HTML interpretation of the page.
|
|
19
|
+
*/
|
|
20
|
+
export default defineAction({
|
|
21
|
+
description:
|
|
22
|
+
"Render a website in a real browser and merge its design.md-style visual " +
|
|
23
|
+
"language into an asset library or collection style brief. Captures " +
|
|
24
|
+
"computed colors, typography, spacing, radii, shadows, components, CSS " +
|
|
25
|
+
"variables, and logo references. Uses a static SSRF-safe fallback only " +
|
|
26
|
+
"when browser rendering is unavailable.",
|
|
27
|
+
schema: z.object({
|
|
28
|
+
libraryId: z.string().describe("Asset library ID"),
|
|
29
|
+
collectionId: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Optional collection to update instead of the library"),
|
|
33
|
+
url: z.string().describe("Public website URL to render and analyze"),
|
|
34
|
+
}),
|
|
35
|
+
run: async ({ libraryId, collectionId, url }) => {
|
|
36
|
+
await assertAccess("asset-library", libraryId, "editor");
|
|
37
|
+
const db = getDb();
|
|
38
|
+
const [library] = await db
|
|
39
|
+
.select()
|
|
40
|
+
.from(schema.assetLibraries)
|
|
41
|
+
.where(eq(schema.assetLibraries.id, libraryId))
|
|
42
|
+
.limit(1);
|
|
43
|
+
if (!library) throw new Error("Asset library not found.");
|
|
44
|
+
|
|
45
|
+
const [collection] = collectionId
|
|
46
|
+
? await db
|
|
47
|
+
.select()
|
|
48
|
+
.from(schema.assetCollections)
|
|
49
|
+
.where(eq(schema.assetCollections.id, collectionId))
|
|
50
|
+
.limit(1)
|
|
51
|
+
: [null];
|
|
52
|
+
if (collectionId && !collection) throw new Error("Collection not found.");
|
|
53
|
+
if (collection && collection.libraryId !== libraryId) {
|
|
54
|
+
throw new Error("Collection does not belong to this asset library.");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const extraction = await extractRenderedDesignSystemFromUrl(url);
|
|
58
|
+
if (extraction.status === "failed") {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Rendered website extraction failed: ${extraction.error ?? "unknown error"}`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const previous = parseJson<StyleBrief>(
|
|
65
|
+
collection?.styleBrief ?? library.styleBrief,
|
|
66
|
+
{},
|
|
67
|
+
);
|
|
68
|
+
const styleBrief = {
|
|
69
|
+
...previous,
|
|
70
|
+
...styleBriefFromRenderedDesign(extraction),
|
|
71
|
+
} satisfies StyleBrief;
|
|
72
|
+
const updatedAt = nowIso();
|
|
73
|
+
|
|
74
|
+
if (collection) {
|
|
75
|
+
await db
|
|
76
|
+
.update(schema.assetCollections)
|
|
77
|
+
.set({ styleBrief: stringifyJson(styleBrief), updatedAt })
|
|
78
|
+
.where(eq(schema.assetCollections.id, collection.id));
|
|
79
|
+
} else {
|
|
80
|
+
const settings = parseJson<Record<string, unknown>>(library.settings, {});
|
|
81
|
+
settings.brandAnalysis = {
|
|
82
|
+
...(typeof settings.brandAnalysis === "object" &&
|
|
83
|
+
settings.brandAnalysis !== null
|
|
84
|
+
? settings.brandAnalysis
|
|
85
|
+
: {}),
|
|
86
|
+
analyzedAt: updatedAt,
|
|
87
|
+
sourceUrl: extraction.finalUrl ?? extraction.url,
|
|
88
|
+
mode: extraction.rendered ? "rendered-browser" : "static-fallback",
|
|
89
|
+
method: extraction.method,
|
|
90
|
+
status: extraction.status,
|
|
91
|
+
warnings: extraction.warnings,
|
|
92
|
+
};
|
|
93
|
+
await db
|
|
94
|
+
.update(schema.assetLibraries)
|
|
95
|
+
.set({
|
|
96
|
+
styleBrief: stringifyJson(styleBrief),
|
|
97
|
+
settings: stringifyJson(settings),
|
|
98
|
+
updatedAt,
|
|
99
|
+
})
|
|
100
|
+
.where(eq(schema.assetLibraries.id, libraryId));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
libraryId,
|
|
105
|
+
collectionId: collection?.id ?? null,
|
|
106
|
+
status: extraction.status,
|
|
107
|
+
rendered: extraction.rendered,
|
|
108
|
+
sourceUrl: extraction.finalUrl ?? extraction.url,
|
|
109
|
+
styleBrief,
|
|
110
|
+
designMd: extraction.designMd,
|
|
111
|
+
warnings: extraction.warnings,
|
|
112
|
+
diagnostics: extraction.diagnostics,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
});
|
|
@@ -109,7 +109,9 @@ function navigationFromPath(pathname: string, search = "") {
|
|
|
109
109
|
const extension = pathname.match(/^\/extensions\/([^/]+)/);
|
|
110
110
|
if (extension) return { view: "extensions", extensionId: extension[1] };
|
|
111
111
|
if (pathname === "/audit") return { view: "audit" };
|
|
112
|
-
if (pathname === "/settings"
|
|
112
|
+
if (pathname === "/settings" || pathname.startsWith("/settings/")) {
|
|
113
|
+
return { view: "settings" };
|
|
114
|
+
}
|
|
113
115
|
return { view: "create" };
|
|
114
116
|
}
|
|
115
117
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, meta } from "./settings.js";
|
|
@@ -61,10 +61,15 @@ import {
|
|
|
61
61
|
} from "@/components/ui/select";
|
|
62
62
|
import { Switch } from "@/components/ui/switch";
|
|
63
63
|
import { useAssetsPrefs } from "@/hooks/use-assets-prefs";
|
|
64
|
+
import { messagesByLocale } from "@/i18n-data";
|
|
64
65
|
import { cn } from "@/lib/utils";
|
|
65
66
|
|
|
66
67
|
import changelog from "../../CHANGELOG.md?raw";
|
|
67
68
|
|
|
69
|
+
export function meta() {
|
|
70
|
+
return [{ title: messagesByLocale["en-US"].settings.title }];
|
|
71
|
+
}
|
|
72
|
+
|
|
68
73
|
type ImageGenerationConfig = {
|
|
69
74
|
builderEnabled?: boolean;
|
|
70
75
|
builderConnected?: boolean;
|