@agent-native/core 0.145.7 → 0.145.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 +1 -1
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-08-07-settings-skeleton-placeholders.md +6 -0
- package/corpus/templates/analytics/netlify.toml +1 -1
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/scripts/migrate-production.ts +24 -0
- package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +9 -0
- package/corpus/templates/analytics/server/plugins/db.ts +14 -3
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/chat/AGENTS.md +3 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +21 -3
- package/corpus/templates/crm/app/components/crm/settings/ConnectionSettings.tsx +23 -5
- package/corpus/templates/crm/app/components/crm/settings/FieldsSettings.tsx +24 -5
- package/corpus/templates/crm/app/components/crm/settings/ListsSettings.tsx +23 -3
- package/corpus/templates/crm/changelog/2026-08-07-settings-loading-skeletons.md +6 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +5 -1
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +5 -1
- package/dist/client/components/ApiKeySettings.js +2 -5
- package/dist/client/org/TeamPage.js +4 -2
- package/dist/client/settings/AccountSettingsCard.js +2 -1
- package/dist/client/settings/AgentsSection.js +2 -1
- package/dist/client/settings/SecretsSection.js +3 -2
- package/dist/client/settings/SettingsPanel.js +6 -12
- package/dist/client/settings/SettingsSkeleton.d.ts +12 -0
- package/dist/client/settings/SettingsSkeleton.js +12 -0
- package/dist/client/settings/VoiceTranscriptionSection.js +5 -4
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.js +1 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +13 -7
- package/dist/db/client.js +124 -7
- package/dist/db/ddl-guard.js +3 -1
- package/dist/db/ensure-additive-columns.d.ts +2 -0
- package/dist/db/ensure-additive-columns.js +5 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +2 -2
- package/dist/db/migrations.d.ts +11 -54
- package/dist/db/migrations.js +70 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/index.d.ts +1 -0
- package/dist/jobs/index.js +1 -0
- package/dist/jobs/run-history.d.ts +4 -0
- package/dist/jobs/run-history.js +44 -0
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.js +6 -4
- package/dist/server/auth-plugin.js +5 -0
- package/dist/server/better-auth-instance.js +0 -61
- package/dist/server/better-auth-migrations.d.ts +8 -0
- package/dist/server/better-auth-migrations.js +179 -0
- package/dist/server/edge.d.ts +2 -0
- package/dist/server/edge.js +2 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +2 -0
- package/dist/server/release-migrations.d.ts +8 -0
- package/dist/server/release-migrations.js +24 -0
- package/dist/server/sweep-runtime.d.ts +1 -1
- package/dist/server/sweep-runtime.js +15 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
- package/dist/templates/chat/AGENTS.md +3 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +5 -1
- package/dist/templates/default/AGENTS.md +3 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -1
- package/dist/templates/workspace-core/AGENTS.md +3 -0
- package/dist/templates/workspace-root/AGENTS.md +3 -0
- package/package.json +1 -1
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
- package/src/templates/chat/AGENTS.md +3 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +5 -1
- package/src/templates/default/AGENTS.md +3 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -1
- package/src/templates/workspace-core/AGENTS.md +3 -0
- package/src/templates/workspace-root/AGENTS.md +3 -0
package/corpus/README.md
CHANGED
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
SelectTrigger,
|
|
59
59
|
SelectValue,
|
|
60
60
|
} from "@/components/ui/select";
|
|
61
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
61
62
|
import { Switch } from "@/components/ui/switch";
|
|
62
63
|
import { Textarea } from "@/components/ui/textarea";
|
|
63
64
|
import { cn } from "@/lib/utils";
|
|
@@ -503,9 +504,9 @@ export function AlertRulesSettingsCard() {
|
|
|
503
504
|
{isLoading ? (
|
|
504
505
|
<div className="space-y-2">
|
|
505
506
|
{[0, 1, 2].map((item) => (
|
|
506
|
-
<
|
|
507
|
+
<Skeleton
|
|
507
508
|
key={item}
|
|
508
|
-
className="h-14 rounded-md border border-border bg-muted/30"
|
|
509
|
+
className="h-14 w-full rounded-md border border-border bg-muted/30"
|
|
509
510
|
/>
|
|
510
511
|
))}
|
|
511
512
|
</div>
|
|
@@ -4,7 +4,7 @@ ignore = "node ./scripts/netlify-ignore-build.mjs analytics"
|
|
|
4
4
|
# core explicitly here so a cached Netlify install cannot bundle an older agent
|
|
5
5
|
# loop into Analytics' server functions (including A2A/MCP final-response
|
|
6
6
|
# guards).
|
|
7
|
-
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter analytics build"
|
|
7
|
+
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && pnpm --filter @agent-native/core build && NITRO_PRESET=netlify pnpm --filter analytics build && if [ \"${CONTEXT:-}\" = \"production\" ]; then pnpm --filter analytics migrate:production; fi"
|
|
8
8
|
publish = "templates/analytics/dist"
|
|
9
9
|
functions = "templates/analytics/.netlify/functions-internal"
|
|
10
10
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { closeDbExec, withMigrationRuntime } from "@agent-native/core/db";
|
|
2
|
+
import { runFrameworkReleaseMigrations } from "@agent-native/core/server";
|
|
3
|
+
|
|
4
|
+
import { runAnalyticsMigrations } from "../server/plugins/db.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Release-time schema entrypoint for Analytics.
|
|
8
|
+
*
|
|
9
|
+
* This script is the production owner of schema changes. It runs against the
|
|
10
|
+
* direct migration endpoint selected by core, while request functions skip
|
|
11
|
+
* all migration and ensure-table work automatically.
|
|
12
|
+
*/
|
|
13
|
+
async function main(): Promise<void> {
|
|
14
|
+
await withMigrationRuntime(async () => {
|
|
15
|
+
await runFrameworkReleaseMigrations(null);
|
|
16
|
+
await runAnalyticsMigrations(null);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await main();
|
|
22
|
+
} finally {
|
|
23
|
+
await closeDbExec();
|
|
24
|
+
}
|
|
@@ -243,6 +243,15 @@ async function runTransactionalBackfill(
|
|
|
243
243
|
|
|
244
244
|
return db.transaction(async (tx) => {
|
|
245
245
|
if (isPostgres()) {
|
|
246
|
+
// This scans all of analytics_events (41 GB in production) in one
|
|
247
|
+
// GROUP BY, and the lease budgets 15 minutes for it. A role-level
|
|
248
|
+
// statement_timeout — the thing that stops a runaway dashboard query
|
|
249
|
+
// from holding every pooler connection — would otherwise kill this
|
|
250
|
+
// legitimate job partway through. SET LOCAL is scoped to this
|
|
251
|
+
// transaction and reverts on commit or rollback.
|
|
252
|
+
await tx.execute(
|
|
253
|
+
`SET LOCAL statement_timeout = '${BACKFILL_LEASE_MINUTES}min'`,
|
|
254
|
+
);
|
|
246
255
|
const lockResult = await tx.execute({
|
|
247
256
|
sql: "SELECT pg_try_advisory_xact_lock(hashtextextended(?, 0::bigint)) AS acquired",
|
|
248
257
|
args: [FIRST_PARTY_ANALYTICS_ROLLUP_LOCK_KEY],
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ensureAdditiveColumns,
|
|
3
3
|
getDbExec,
|
|
4
4
|
runMigrations,
|
|
5
|
+
withMigrationRuntime,
|
|
5
6
|
} from "@agent-native/core/db";
|
|
6
7
|
import { isInBackgroundFunctionRuntime } from "@agent-native/core/server";
|
|
7
8
|
|
|
@@ -33,7 +34,7 @@ const schemaTables = Object.values(schema).filter(isDrizzleTable);
|
|
|
33
34
|
// packages/core/src/db/migrations.ts for the full rationale). Version numbers
|
|
34
35
|
// alone are not a safe identity across parallel branches that each extend
|
|
35
36
|
// this list independently — see the v75-v83 incident documented on v75 below.
|
|
36
|
-
const runAnalyticsMigrations = runMigrations(
|
|
37
|
+
export const runAnalyticsMigrations = runMigrations(
|
|
37
38
|
[
|
|
38
39
|
{
|
|
39
40
|
version: 1,
|
|
@@ -1536,9 +1537,19 @@ export default async (nitroApp: any): Promise<void> => {
|
|
|
1536
1537
|
}
|
|
1537
1538
|
// The schema must exist before the first query. Measured cost on this
|
|
1538
1539
|
// database (180 tables): ~5.5s for the version check alone, which is why the
|
|
1539
|
-
// serverless runtime never runs it on cold starts.
|
|
1540
|
+
// serverless runtime never runs it on cold starts. The scheduled worker is
|
|
1541
|
+
// the one serverless exception and claims migration duty explicitly.
|
|
1540
1542
|
// guard:allow-boot-data-work — schema must exist before the first query
|
|
1541
|
-
|
|
1543
|
+
if (isScheduledRollupRuntime) {
|
|
1544
|
+
// guard:allow-boot-data-work — scheduled worker owns the release migration
|
|
1545
|
+
await withMigrationRuntime(async () => {
|
|
1546
|
+
// guard:allow-boot-data-work — scheduled worker owns the release migration
|
|
1547
|
+
await runAnalyticsMigrations(nitroApp);
|
|
1548
|
+
});
|
|
1549
|
+
} else {
|
|
1550
|
+
// guard:allow-boot-data-work — long-lived local runtime owns the migration
|
|
1551
|
+
await runAnalyticsMigrations(nitroApp);
|
|
1552
|
+
}
|
|
1542
1553
|
try {
|
|
1543
1554
|
const summary = await ensureAdditiveColumns({
|
|
1544
1555
|
db: getDbExec(),
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -23,6 +23,9 @@ workflow needs durable UI around the conversation.
|
|
|
23
23
|
- Keep the first viewport sparse and task-focused. Use progressive disclosure
|
|
24
24
|
and domain-specific navigation, and never use sparkle, wand, magic, or robot
|
|
25
25
|
icons as AI affordances.
|
|
26
|
+
- Page and section data loads use layout-matching `Skeleton` geometry, never a
|
|
27
|
+
generic "Loading..." label. Reserve `Spinner` for brief mutations, uploads,
|
|
28
|
+
and progress actions.
|
|
26
29
|
- Use a sans-first SaaS hierarchy with one restrained visual cue; reserve serif
|
|
27
30
|
type for content previews. Give the AgentSidebar a subtle surface/divider
|
|
28
31
|
boundary, and stack original/generated review vertically by default.
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
SelectTrigger,
|
|
40
40
|
SelectValue,
|
|
41
41
|
} from "@/components/ui/select";
|
|
42
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
42
43
|
import { Switch } from "@/components/ui/switch";
|
|
43
44
|
import { Textarea } from "@/components/ui/textarea";
|
|
44
45
|
|
|
@@ -131,9 +132,26 @@ export function IntelligenceSettings() {
|
|
|
131
132
|
</div>
|
|
132
133
|
|
|
133
134
|
{trackersQuery.isLoading ? (
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
<div
|
|
136
|
+
className="mt-8 space-y-2"
|
|
137
|
+
role="status"
|
|
138
|
+
aria-busy="true"
|
|
139
|
+
aria-label={t("intelligence.loading")}
|
|
140
|
+
>
|
|
141
|
+
{[0, 1, 2].map((item) => (
|
|
142
|
+
<div
|
|
143
|
+
key={item}
|
|
144
|
+
className="flex items-center gap-4 rounded-lg border border-border/70 bg-card px-4 py-3.5"
|
|
145
|
+
>
|
|
146
|
+
<Skeleton className="size-4" />
|
|
147
|
+
<div className="flex-1 space-y-2">
|
|
148
|
+
<Skeleton className="h-4 w-40" />
|
|
149
|
+
<Skeleton className="h-3 w-56" />
|
|
150
|
+
</div>
|
|
151
|
+
<Skeleton className="size-5 rounded-full" />
|
|
152
|
+
</div>
|
|
153
|
+
))}
|
|
154
|
+
</div>
|
|
137
155
|
) : trackers.length ? (
|
|
138
156
|
<div className="mt-8 divide-y divide-border/70 rounded-lg border border-border/70 bg-card">
|
|
139
157
|
{trackers.map((tracker) => {
|
|
@@ -5,6 +5,7 @@ import { Link } from "react-router";
|
|
|
5
5
|
|
|
6
6
|
import { Badge } from "@/components/ui/badge";
|
|
7
7
|
import { Button } from "@/components/ui/button";
|
|
8
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
8
9
|
|
|
9
10
|
import {
|
|
10
11
|
connectionModeInfo,
|
|
@@ -88,13 +89,30 @@ export function ConnectionSettings() {
|
|
|
88
89
|
<ConnectionRow key={connection.id} connection={connection} />
|
|
89
90
|
))}
|
|
90
91
|
</div>
|
|
92
|
+
) : connectionsQuery.isLoading ? (
|
|
93
|
+
<div
|
|
94
|
+
className="mt-6 space-y-2"
|
|
95
|
+
role="status"
|
|
96
|
+
aria-busy="true"
|
|
97
|
+
aria-label={t("connection.loading")}
|
|
98
|
+
>
|
|
99
|
+
{[0, 1, 2].map((item) => (
|
|
100
|
+
<div
|
|
101
|
+
key={item}
|
|
102
|
+
className="flex items-center gap-4 rounded-lg border border-border/70 bg-card px-4 py-3.5"
|
|
103
|
+
>
|
|
104
|
+
<Skeleton className="size-4" />
|
|
105
|
+
<div className="flex-1 space-y-2">
|
|
106
|
+
<Skeleton className="h-4 w-40" />
|
|
107
|
+
<Skeleton className="h-3 w-56" />
|
|
108
|
+
</div>
|
|
109
|
+
<Skeleton className="h-6 w-20 rounded-full" />
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
91
113
|
) : (
|
|
92
114
|
<div className="mt-6 rounded-lg border border-dashed border-border px-4 py-10 text-center">
|
|
93
|
-
<p className="text-sm font-medium">
|
|
94
|
-
{connectionsQuery.isLoading
|
|
95
|
-
? t("connection.loading")
|
|
96
|
-
: t("connection.emptyTitle")}
|
|
97
|
-
</p>
|
|
115
|
+
<p className="text-sm font-medium">{t("connection.emptyTitle")}</p>
|
|
98
116
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
99
117
|
{t("connection.emptyDescription")}
|
|
100
118
|
</p>
|
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
SelectTrigger,
|
|
50
50
|
SelectValue,
|
|
51
51
|
} from "@/components/ui/select";
|
|
52
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
52
53
|
import { Switch } from "@/components/ui/switch";
|
|
53
54
|
import {
|
|
54
55
|
Table,
|
|
@@ -311,13 +312,31 @@ export function FieldsSettings() {
|
|
|
311
312
|
</TableBody>
|
|
312
313
|
</Table>
|
|
313
314
|
</div>
|
|
315
|
+
) : activeTarget &&
|
|
316
|
+
(connectionsQuery.isLoading ||
|
|
317
|
+
listsQuery.isLoading ||
|
|
318
|
+
attributesQuery.isLoading) ? (
|
|
319
|
+
<div
|
|
320
|
+
className="mt-4 space-y-2"
|
|
321
|
+
role="status"
|
|
322
|
+
aria-busy="true"
|
|
323
|
+
aria-label={t("fields.loading")}
|
|
324
|
+
>
|
|
325
|
+
{[0, 1, 2, 3].map((item) => (
|
|
326
|
+
<div
|
|
327
|
+
key={item}
|
|
328
|
+
className="grid grid-cols-4 gap-4 rounded-lg border border-border/70 bg-card px-4 py-3.5"
|
|
329
|
+
>
|
|
330
|
+
<Skeleton className="h-4 w-36" />
|
|
331
|
+
<Skeleton className="h-4 w-28" />
|
|
332
|
+
<Skeleton className="h-4 w-24" />
|
|
333
|
+
<Skeleton className="h-4 w-32" />
|
|
334
|
+
</div>
|
|
335
|
+
))}
|
|
336
|
+
</div>
|
|
314
337
|
) : (
|
|
315
338
|
<div className="mt-4 rounded-lg border border-dashed border-border px-4 py-10 text-center">
|
|
316
|
-
<p className="text-sm font-medium">
|
|
317
|
-
{attributesQuery.isLoading
|
|
318
|
-
? t("fields.loading")
|
|
319
|
-
: t("fields.emptyTitle")}
|
|
320
|
-
</p>
|
|
339
|
+
<p className="text-sm font-medium">{t("fields.emptyTitle")}</p>
|
|
321
340
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
322
341
|
{t("fields.emptyDescription")}
|
|
323
342
|
</p>
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
SelectTrigger,
|
|
46
46
|
SelectValue,
|
|
47
47
|
} from "@/components/ui/select";
|
|
48
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
48
49
|
import { Textarea } from "@/components/ui/textarea";
|
|
49
50
|
|
|
50
51
|
interface CrmListRow {
|
|
@@ -195,11 +196,30 @@ export function ListsSettings() {
|
|
|
195
196
|
</section>
|
|
196
197
|
))}
|
|
197
198
|
</div>
|
|
199
|
+
) : listsQuery.isLoading ? (
|
|
200
|
+
<div
|
|
201
|
+
className="mt-6 space-y-2"
|
|
202
|
+
role="status"
|
|
203
|
+
aria-busy="true"
|
|
204
|
+
aria-label={t("lists.loading")}
|
|
205
|
+
>
|
|
206
|
+
{[0, 1, 2].map((item) => (
|
|
207
|
+
<div
|
|
208
|
+
key={item}
|
|
209
|
+
className="flex items-center gap-4 rounded-lg border border-border/70 bg-card px-4 py-3.5"
|
|
210
|
+
>
|
|
211
|
+
<Skeleton className="size-4" />
|
|
212
|
+
<div className="flex-1 space-y-2">
|
|
213
|
+
<Skeleton className="h-4 w-40" />
|
|
214
|
+
<Skeleton className="h-3 w-56" />
|
|
215
|
+
</div>
|
|
216
|
+
<Skeleton className="size-8 rounded-md" />
|
|
217
|
+
</div>
|
|
218
|
+
))}
|
|
219
|
+
</div>
|
|
198
220
|
) : (
|
|
199
221
|
<div className="mt-6 rounded-lg border border-dashed border-border px-4 py-10 text-center">
|
|
200
|
-
<p className="text-sm font-medium">
|
|
201
|
-
{listsQuery.isLoading ? t("lists.loading") : t("lists.emptyTitle")}
|
|
202
|
-
</p>
|
|
222
|
+
<p className="text-sm font-medium">{t("lists.emptyTitle")}</p>
|
|
203
223
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
204
224
|
{t("lists.emptyDescription")}
|
|
205
225
|
</p>
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -199,7 +199,11 @@ as an operator would use it repeatedly:
|
|
|
199
199
|
- Use full `Card` composition when the content has a title, description, content, or actions. Do not dump complex cards into a single `CardContent`.
|
|
200
200
|
- Use `ToggleGroup` for small option sets, `Switch` for binary settings, `Checkbox` for multi-select, `RadioGroup` for one-of-many, and `Slider`/inputs for numeric values.
|
|
201
201
|
- For forms, prefer the app's existing shadcn form pattern. If newer `Field`, `FieldGroup`, or `InputGroup` primitives are installed or appropriate to add, use them instead of raw layout divs.
|
|
202
|
-
-
|
|
202
|
+
- Page and section data loading uses layout-matching `Skeleton` geometry. Do
|
|
203
|
+
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
|
+
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
|
+
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
+
should have one clear next action.
|
|
203
207
|
|
|
204
208
|
## Anti-Patterns
|
|
205
209
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Skeleton } from "@agent-native/toolkit/design-system";
|
|
2
3
|
import { useState, useEffect, useCallback } from "react";
|
|
3
4
|
import { agentNativePath } from "../api-path.js";
|
|
4
5
|
/**
|
|
@@ -77,7 +78,7 @@ export function ApiKeySettings({ settingsPath: _settingsPath = "/settings", }) {
|
|
|
77
78
|
};
|
|
78
79
|
const pendingCount = Object.values(values).filter((v) => v.trim() !== "").length;
|
|
79
80
|
if (loading) {
|
|
80
|
-
return (
|
|
81
|
+
return (_jsxs("div", { style: styles.container, role: "status", "aria-busy": "true", "aria-label": "Loading API key status", children: [_jsx(Skeleton, { className: "h-3 w-40" }), _jsx(Skeleton, { className: "mt-3 h-8 w-full" })] }));
|
|
81
82
|
}
|
|
82
83
|
if (error) {
|
|
83
84
|
return (_jsxs("div", { style: styles.container, children: [_jsx("p", { style: styles.errorText, children: error }), _jsx("button", { onClick: fetchStatus, style: styles.retryButton, children: "Retry" })] }));
|
|
@@ -110,10 +111,6 @@ const styles = {
|
|
|
110
111
|
opacity: 0.6,
|
|
111
112
|
margin: "0 0 16px 0",
|
|
112
113
|
},
|
|
113
|
-
loadingText: {
|
|
114
|
-
fontSize: "13px",
|
|
115
|
-
opacity: 0.5,
|
|
116
|
-
},
|
|
117
114
|
errorText: {
|
|
118
115
|
fontSize: "13px",
|
|
119
116
|
color: "#ef4444",
|