@agent-native/core 0.146.8 → 0.148.0
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 +115 -68
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/analytics/DEVELOPING.md +50 -3
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
- package/corpus/templates/analytics/app/i18n/index.ts +14 -29
- package/corpus/templates/analytics/app/i18n-data.ts +10 -10
- package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
- package/corpus/templates/analytics/app/routes/status.$slug.tsx +4 -2
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +253 -24
- package/corpus/templates/analytics/server/db/schema.ts +23 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
- package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
- package/corpus/templates/analytics/server/plugins/db.ts +42 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/assets/app/i18n/index.ts +14 -29
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/brain/app/i18n/index.ts +14 -29
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/chat/app/i18n/index.ts +14 -29
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
- package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +16 -4
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +14 -5
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/clips/package.json +1 -0
- package/corpus/templates/clips/react-router.config.ts +7 -0
- package/corpus/templates/clips/server/plugins/auth.ts +6 -1
- package/corpus/templates/clips/shared/prerendered-public-paths.ts +21 -0
- package/corpus/templates/clips/shared/share-meta.ts +8 -3
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/content/app/i18n/index.ts +14 -29
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/crm/app/i18n/index.ts +14 -29
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/design/actions/import-code.ts +2 -43
- package/corpus/templates/design/app/i18n/index.ts +14 -29
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/dispatch/app/chat-first-pages.ts +747 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +182 -1
- package/corpus/templates/dispatch/app/routes/settings.tsx +62 -1
- package/corpus/templates/dispatch/changelog/2026-08-08-chat-first-navigation-keeps-conversations-central-while-open.md +6 -0
- package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/factory/AGENTS.md +40 -49
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
- package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
- package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
- package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
- package/corpus/templates/factory/app/routes/factory.tsx +203 -118
- package/corpus/templates/factory/changelog/2026-08-08-scheduler-health-moves-to-settings.md +6 -0
- package/corpus/templates/factory/server/db/schema.ts +37 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
- package/corpus/templates/factory/server/triage/audit.ts +79 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/forms/app/i18n/index.ts +14 -29
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/macros/app/i18n/index.ts +14 -29
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/mail/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
- package/corpus/templates/plan/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/app/lib/plan-document-title.ts +3 -1
- package/corpus/templates/plan/app/root.tsx +1 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/slides/actions/import-code.ts +2 -43
- package/corpus/templates/slides/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
- package/corpus/templates/tasks/app/i18n/index.ts +14 -29
- package/dist/agent/engine/ai-sdk-engine.js +2 -1
- package/dist/agent/engine/builder-engine.d.ts +11 -1
- package/dist/agent/engine/builder-engine.js +11 -4
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
- package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
- package/dist/agent/engine/provider-endpoint-validation.js +26 -0
- package/dist/agent/engine/provider-env-vars.d.ts +1 -1
- package/dist/agent/engine/provider-env-vars.js +1 -1
- package/dist/agent/engine/registry.d.ts +8 -6
- package/dist/agent/engine/registry.js +37 -24
- package/dist/agent/tool-search.d.ts +1 -0
- package/dist/agent/tool-search.js +17 -1
- package/dist/automations/service.js +4 -10
- package/dist/brand-kit/brand-signals.d.ts +13 -0
- package/dist/brand-kit/brand-signals.js +15 -0
- package/dist/brand-kit/index.d.ts +2 -2
- package/dist/brand-kit/index.js +1 -1
- package/dist/chat-threads/store.d.ts +2 -0
- package/dist/chat-threads/store.js +1 -1
- package/dist/cli/agent-plugin.d.ts +5 -2
- package/dist/cli/agent-plugin.js +17 -9
- package/dist/cli/code-agent-executor.js +25 -5
- package/dist/cli/code-agent-mcp-config.d.ts +21 -0
- package/dist/cli/code-agent-mcp-config.js +103 -0
- package/dist/cli/plan-blocks.d.ts +3 -18
- package/dist/cli/plan-blocks.js +2 -95
- package/dist/cli/plan-publish-store.d.ts +2 -61
- package/dist/cli/plan-publish-store.js +2 -127
- package/dist/cli/skills-content/connection.d.ts +1 -1
- package/dist/cli/skills-content/connection.js +1 -52
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +1 -553
- package/dist/client/NewWorkspaceAppFlow.js +4 -1
- package/dist/client/agent-chat/index.d.ts +4 -1
- package/dist/client/agent-chat/index.js +4 -1
- package/dist/client/agent-engine-key.d.ts +14 -4
- package/dist/client/agent-engine-key.js +51 -5
- package/dist/client/agent-page/AgentTabsPage.d.ts +1 -0
- package/dist/client/agent-page/AgentTabsPage.js +4 -3
- package/dist/client/agent-provider-catalog.d.ts +20 -0
- package/dist/client/agent-provider-catalog.js +100 -0
- package/dist/client/app-providers.d.ts +3 -1
- package/dist/client/app-providers.js +50 -5
- package/dist/client/blocks/index.d.ts +1 -0
- package/dist/client/blocks/index.js +1 -0
- package/dist/client/chat/run-recovery.js +4 -48
- package/dist/client/chat/runtime.js +63 -0
- package/dist/client/chat-first/agents-pane.d.ts +2 -0
- package/dist/client/chat-first/agents-pane.js +6 -0
- package/dist/client/chat-first/app-pane.d.ts +2 -0
- package/dist/client/chat-first/app-pane.js +6 -0
- package/dist/client/chat-first/apps-rail.d.ts +2 -0
- package/dist/client/chat-first/apps-rail.js +103 -0
- package/dist/client/chat-first/browser-pane.d.ts +2 -0
- package/dist/client/chat-first/browser-pane.js +64 -0
- package/dist/client/chat-first/chat-history.d.ts +12 -0
- package/dist/client/chat-first/chat-history.js +10 -0
- package/dist/client/chat-first/copy.d.ts +2 -0
- package/dist/client/chat-first/copy.js +117 -0
- package/dist/client/chat-first/index.d.ts +13 -0
- package/dist/client/chat-first/index.js +12 -0
- package/dist/client/chat-first/primary-nav.d.ts +8 -0
- package/dist/client/chat-first/primary-nav.js +6 -0
- package/dist/client/chat-first/session-watch-pane.d.ts +2 -0
- package/dist/client/chat-first/session-watch-pane.js +9 -0
- package/dist/client/chat-first/surface-panel.d.ts +9 -0
- package/dist/client/chat-first/surface-panel.js +9 -0
- package/dist/client/chat-first/surface-tabs.d.ts +9 -0
- package/dist/client/chat-first/surface-tabs.js +74 -0
- package/dist/client/chat-first/types.d.ts +74 -0
- package/dist/client/chat-first/types.js +1 -0
- package/dist/client/chat-first-agent-activity.d.ts +11 -0
- package/dist/client/chat-first-agent-activity.js +51 -0
- package/dist/client/chat-first-surface-panel-toggle.d.ts +5 -0
- package/dist/client/chat-first-surface-panel-toggle.js +6 -0
- package/dist/client/chat-first.d.ts +208 -0
- package/dist/client/chat-first.js +817 -0
- package/dist/client/extensions/ExtensionViewer.js +8 -1
- package/dist/client/i18n.d.ts +14 -0
- package/dist/client/i18n.js +18 -0
- package/dist/client/resources/McpIntegrationDialog.js +3 -2
- package/dist/client/resources/McpServerDetail.js +6 -11
- package/dist/client/resources/index.d.ts +1 -0
- package/dist/client/resources/index.js +1 -0
- package/dist/client/resources/use-mcp-servers.d.ts +20 -0
- package/dist/client/resources/use-mcp-servers.js +82 -46
- package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
- package/dist/client/settings/ProviderSetupForm.js +145 -0
- package/dist/client/settings/SettingsPanel.js +52 -49
- package/dist/client/settings/index.d.ts +3 -0
- package/dist/client/settings/index.js +3 -0
- package/dist/coding-tools/run-code.d.ts +5 -0
- package/dist/coding-tools/run-code.js +196 -36
- package/dist/coding-tools/tool-orchestration.d.ts +10 -0
- package/dist/coding-tools/tool-orchestration.js +107 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/jobs/background-automation-runner.js +19 -2
- package/dist/jobs/frontmatter.d.ts +9 -0
- package/dist/jobs/frontmatter.js +16 -0
- package/dist/jobs/scheduler-health.d.ts +20 -0
- package/dist/jobs/scheduler-health.js +86 -1
- package/dist/jobs/scheduler.js +46 -9
- package/dist/jobs/tools.d.ts +1 -1
- package/dist/jobs/tools.js +2 -7
- package/dist/localization/default-messages.d.ts +20 -0
- package/dist/localization/default-messages.js +25 -5
- package/dist/mcp-client/routes.d.ts +3 -0
- package/dist/mcp-client/routes.js +14 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/onboarding/app-profile.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
- package/dist/server/agent-chat/run-code-tools.js +3 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-engine-api-key-route.js +43 -12
- package/dist/server/agents-bundle.d.ts +2 -0
- package/dist/server/agents-bundle.js +32 -2
- package/dist/server/auth.js +21 -5
- package/dist/server/credential-provider.d.ts +8 -2
- package/dist/server/credential-provider.js +14 -9
- package/dist/server/design-token-utils.d.ts +18 -0
- package/dist/server/design-token-utils.js +31 -0
- package/dist/server/onboarding-html.js +22 -2
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/chat-first-app-creation.d.ts +19 -0
- package/dist/shared/chat-first-app-creation.js +75 -0
- package/dist/shared/document-title.d.ts +7 -0
- package/dist/shared/document-title.js +29 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +2 -0
- package/dist/styles/chat-history-list.css +16 -0
- package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/dist/templates/chat/app/i18n/index.ts +14 -29
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/dist/templates/default/app/i18n/index.ts +14 -29
- package/dist/templates/default/react-router.config.ts +18 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -0
- package/dist/triggers/dispatcher.js +1 -8
- package/docs/content/environment-variables.mdx +39 -38
- package/package.json +5 -4
- package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/src/templates/chat/app/i18n/index.ts +14 -29
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/src/templates/default/app/i18n/index.ts +14 -29
- package/src/templates/default/react-router.config.ts +18 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +9 -0
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -6
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
- package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -0
- package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
|
@@ -25,6 +25,122 @@ const MAX_CACHE = 120;
|
|
|
25
25
|
// Token cache, scoped by caller credential context.
|
|
26
26
|
const tokenCache = new Map<string, { token: string; expiresAt: number }>();
|
|
27
27
|
|
|
28
|
+
const GOOGLE_REQUEST_MAX_ATTEMPTS = 4;
|
|
29
|
+
const GOOGLE_REQUEST_TIMEOUT_MS = 30_000;
|
|
30
|
+
const GOOGLE_REQUEST_RETRY_DELAY_MS = 100;
|
|
31
|
+
|
|
32
|
+
function isRetryableGoogleStatus(status: number): boolean {
|
|
33
|
+
return status === 408 || status === 429 || status >= 500;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function errorCode(error: unknown): string | null {
|
|
37
|
+
if (!error || typeof error !== "object") return null;
|
|
38
|
+
const code = (error as { code?: unknown }).code;
|
|
39
|
+
return typeof code === "string" ? code : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function errorCause(error: unknown): unknown {
|
|
43
|
+
if (!error || typeof error !== "object") return undefined;
|
|
44
|
+
return (error as { cause?: unknown }).cause;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function createGoogleError(message: string, cause: unknown): Error {
|
|
48
|
+
const error = new Error(message);
|
|
49
|
+
Object.defineProperty(error, "cause", {
|
|
50
|
+
configurable: true,
|
|
51
|
+
value: cause,
|
|
52
|
+
});
|
|
53
|
+
return error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function describeGoogleError(error: unknown): string {
|
|
57
|
+
if (error instanceof Error) {
|
|
58
|
+
const code = errorCode(error) ?? errorCode(errorCause(error));
|
|
59
|
+
return `${error.name}: ${error.message}${code ? ` (code ${code})` : ""}`;
|
|
60
|
+
}
|
|
61
|
+
return String(error);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isRetryableGoogleError(error: unknown, timedOut: boolean): boolean {
|
|
65
|
+
if (timedOut) return true;
|
|
66
|
+
const code = errorCode(error) ?? errorCode(errorCause(error));
|
|
67
|
+
if (
|
|
68
|
+
code &&
|
|
69
|
+
["ECONNRESET", "EAI_AGAIN", "ETIMEDOUT", "UND_ERR"].includes(code)
|
|
70
|
+
) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
const message = describeGoogleError(error).toLowerCase();
|
|
74
|
+
return (
|
|
75
|
+
error instanceof TypeError || /fetch failed|network|socket/.test(message)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function retryDelayMs(attempt: number): number {
|
|
80
|
+
return GOOGLE_REQUEST_RETRY_DELAY_MS * 2 ** (attempt - 1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function waitForGoogleRetry(attempt: number): Promise<void> {
|
|
84
|
+
await new Promise<void>((resolve) => {
|
|
85
|
+
setTimeout(resolve, retryDelayMs(attempt));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Keep transient Google network failures from killing long-running jobs while
|
|
91
|
+
* preserving a hard bound on attempts and request duration.
|
|
92
|
+
*/
|
|
93
|
+
export async function fetchGoogleWithRetry(
|
|
94
|
+
url: string,
|
|
95
|
+
init: RequestInit,
|
|
96
|
+
operation: string,
|
|
97
|
+
): Promise<Response> {
|
|
98
|
+
let lastError: unknown;
|
|
99
|
+
|
|
100
|
+
for (let attempt = 1; attempt <= GOOGLE_REQUEST_MAX_ATTEMPTS; attempt += 1) {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
let timedOut = false;
|
|
103
|
+
const timeout = setTimeout(() => {
|
|
104
|
+
timedOut = true;
|
|
105
|
+
controller.abort();
|
|
106
|
+
}, GOOGLE_REQUEST_TIMEOUT_MS);
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const response = await fetch(url, {
|
|
110
|
+
...init,
|
|
111
|
+
signal: controller.signal,
|
|
112
|
+
});
|
|
113
|
+
if (
|
|
114
|
+
isRetryableGoogleStatus(response.status) &&
|
|
115
|
+
attempt < GOOGLE_REQUEST_MAX_ATTEMPTS
|
|
116
|
+
) {
|
|
117
|
+
await waitForGoogleRetry(attempt);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
return response;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
lastError = error;
|
|
123
|
+
if (
|
|
124
|
+
attempt >= GOOGLE_REQUEST_MAX_ATTEMPTS ||
|
|
125
|
+
!isRetryableGoogleError(error, timedOut)
|
|
126
|
+
) {
|
|
127
|
+
throw createGoogleError(
|
|
128
|
+
`Google ${operation} failed after ${attempt} attempt(s): ${describeGoogleError(error)}`,
|
|
129
|
+
error,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
await waitForGoogleRetry(attempt);
|
|
133
|
+
} finally {
|
|
134
|
+
clearTimeout(timeout);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
throw createGoogleError(
|
|
139
|
+
`Google ${operation} failed after ${GOOGLE_REQUEST_MAX_ATTEMPTS} attempt(s): ${describeGoogleError(lastError)}`,
|
|
140
|
+
lastError,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
28
144
|
async function getServiceAccountCredentials() {
|
|
29
145
|
const ctx = requireRequestCredentialContext(
|
|
30
146
|
"GOOGLE_APPLICATION_CREDENTIALS_JSON",
|
|
@@ -101,14 +217,18 @@ export async function getAccessToken(): Promise<string> {
|
|
|
101
217
|
const jwt = await signRs256Jwt(jwtPayload, creds.private_key);
|
|
102
218
|
|
|
103
219
|
const tokenUri = creds.token_uri || "https://oauth2.googleapis.com/token";
|
|
104
|
-
const res = await
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
220
|
+
const res = await fetchGoogleWithRetry(
|
|
221
|
+
tokenUri,
|
|
222
|
+
{
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
225
|
+
body: new URLSearchParams({
|
|
226
|
+
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
227
|
+
assertion: jwt,
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
"OAuth token exchange",
|
|
231
|
+
);
|
|
112
232
|
|
|
113
233
|
if (!res.ok) {
|
|
114
234
|
const text = await res.text();
|
|
@@ -146,12 +266,16 @@ async function apiGet<T>(url: string, cacheKey?: string): Promise<T> {
|
|
|
146
266
|
}
|
|
147
267
|
|
|
148
268
|
const token = await getAccessToken();
|
|
149
|
-
const res = await
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
269
|
+
const res = await fetchGoogleWithRetry(
|
|
270
|
+
url,
|
|
271
|
+
{
|
|
272
|
+
headers: {
|
|
273
|
+
Authorization: `Bearer ${token}`,
|
|
274
|
+
"Content-Type": "application/json",
|
|
275
|
+
},
|
|
153
276
|
},
|
|
154
|
-
|
|
277
|
+
"Cloud API GET",
|
|
278
|
+
);
|
|
155
279
|
|
|
156
280
|
if (!res.ok) {
|
|
157
281
|
const text = await res.text();
|
|
@@ -178,14 +302,18 @@ async function apiPost<T>(
|
|
|
178
302
|
}
|
|
179
303
|
|
|
180
304
|
const token = await getAccessToken();
|
|
181
|
-
const res = await
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
305
|
+
const res = await fetchGoogleWithRetry(
|
|
306
|
+
url,
|
|
307
|
+
{
|
|
308
|
+
method: "POST",
|
|
309
|
+
headers: {
|
|
310
|
+
Authorization: `Bearer ${token}`,
|
|
311
|
+
"Content-Type": "application/json",
|
|
312
|
+
},
|
|
313
|
+
body: JSON.stringify(body),
|
|
186
314
|
},
|
|
187
|
-
|
|
188
|
-
|
|
315
|
+
"Cloud API POST",
|
|
316
|
+
);
|
|
189
317
|
|
|
190
318
|
if (!res.ok) {
|
|
191
319
|
const text = await res.text();
|
|
@@ -1534,6 +1534,48 @@ export const runAnalyticsMigrations = runMigrations(
|
|
|
1534
1534
|
ON analytics_bigquery_backfill_jobs (status, next_run_at, lease_expires_at, updated_at)`,
|
|
1535
1535
|
},
|
|
1536
1536
|
},
|
|
1537
|
+
{
|
|
1538
|
+
version: 140,
|
|
1539
|
+
name: "analytics-events-backfill-filtered-cursor-indexes",
|
|
1540
|
+
sql: {
|
|
1541
|
+
postgres: `CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_org_received_id_non_http_idx ON analytics_events (org_id, received_at, id) WHERE event_name IS DISTINCT FROM 'http.response'; CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_owner_received_id_non_http_idx ON analytics_events (owner_email, received_at, id) WHERE org_id IS NULL AND event_name IS DISTINCT FROM 'http.response'`,
|
|
1542
|
+
sqlite: `CREATE INDEX IF NOT EXISTS analytics_events_org_received_id_non_http_idx ON analytics_events (org_id, received_at, id) WHERE event_name IS NOT 'http.response'; CREATE INDEX IF NOT EXISTS analytics_events_owner_received_id_non_http_idx ON analytics_events (owner_email, received_at, id) WHERE org_id IS NULL AND event_name IS NOT 'http.response'`,
|
|
1543
|
+
},
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
version: 141,
|
|
1547
|
+
name: "analytics-event-volume-usage",
|
|
1548
|
+
sql: {
|
|
1549
|
+
postgres: `CREATE TABLE IF NOT EXISTS analytics_event_volume_usage (
|
|
1550
|
+
id TEXT PRIMARY KEY,
|
|
1551
|
+
tenant_key TEXT NOT NULL,
|
|
1552
|
+
owner_email TEXT NOT NULL,
|
|
1553
|
+
org_id TEXT,
|
|
1554
|
+
window_start TEXT NOT NULL,
|
|
1555
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
1556
|
+
event_limit INTEGER NOT NULL,
|
|
1557
|
+
updated_at TEXT NOT NULL DEFAULT (now()::text)
|
|
1558
|
+
);
|
|
1559
|
+
CREATE UNIQUE INDEX IF NOT EXISTS analytics_event_volume_usage_tenant_window_idx
|
|
1560
|
+
ON analytics_event_volume_usage (tenant_key, window_start);
|
|
1561
|
+
CREATE INDEX IF NOT EXISTS analytics_event_volume_usage_updated_at_idx
|
|
1562
|
+
ON analytics_event_volume_usage (updated_at)`,
|
|
1563
|
+
sqlite: `CREATE TABLE IF NOT EXISTS analytics_event_volume_usage (
|
|
1564
|
+
id TEXT PRIMARY KEY,
|
|
1565
|
+
tenant_key TEXT NOT NULL,
|
|
1566
|
+
owner_email TEXT NOT NULL,
|
|
1567
|
+
org_id TEXT,
|
|
1568
|
+
window_start TEXT NOT NULL,
|
|
1569
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
1570
|
+
event_limit INTEGER NOT NULL,
|
|
1571
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1572
|
+
);
|
|
1573
|
+
CREATE UNIQUE INDEX IF NOT EXISTS analytics_event_volume_usage_tenant_window_idx
|
|
1574
|
+
ON analytics_event_volume_usage (tenant_key, window_start);
|
|
1575
|
+
CREATE INDEX IF NOT EXISTS analytics_event_volume_usage_updated_at_idx
|
|
1576
|
+
ON analytics_event_volume_usage (updated_at)`,
|
|
1577
|
+
},
|
|
1578
|
+
},
|
|
1537
1579
|
],
|
|
1538
1580
|
{ table: "analytics_migrations" },
|
|
1539
1581
|
);
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
name: frontend-design
|
|
3
3
|
description: >-
|
|
4
4
|
Sets the visual direction for a new or redesigned surface, with production
|
|
5
|
-
quality that avoids generic AI aesthetics. Use when building
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
quality that avoids generic AI aesthetics. Use when building, redesigning, or
|
|
6
|
+
cleaning up any user-facing UI, including screenshot-driven feedback, copy or
|
|
7
|
+
density reduction, settings, control placement, or a design pass ("make this
|
|
8
|
+
look good"). Do not load it only for purely mechanical wiring or formatting.
|
|
9
9
|
scope: dev
|
|
10
10
|
license: Complete terms in LICENSE.txt
|
|
11
11
|
source: https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md
|
|
12
12
|
local-changes: >-
|
|
13
|
-
Description
|
|
14
|
-
|
|
13
|
+
Description deliberately widened on 2026-08-09 because the previous narrow
|
|
14
|
+
trigger excluded routine UI edits, including screenshot-driven cleanup, copy
|
|
15
|
+
and density changes, settings, and control placement. An upstream sync must
|
|
16
|
+
not re-narrow it. Verification remains deliberately rescoped; an upstream
|
|
17
|
+
sync must not restore screenshot-everything or broad browser-automation steps.
|
|
15
18
|
metadata:
|
|
16
19
|
internal: true
|
|
17
20
|
---
|
|
@@ -26,10 +29,12 @@ The user may ask for a component, page, full app, dashboard, marketing surface,
|
|
|
26
29
|
|
|
27
30
|
Before coding, decide:
|
|
28
31
|
|
|
29
|
-
- **Purpose**: What workflow does this surface make easier? What
|
|
32
|
+
- **Purpose**: What workflow does this surface make easier? What does the user
|
|
33
|
+
need to understand, decide, or do next?
|
|
30
34
|
- **Audience**: Who will use it repeatedly, and what should feel fast, calm, playful, premium, editorial, technical, or utilitarian?
|
|
31
35
|
- **Tone**: Choose a concrete aesthetic direction: refined minimal, dense operations console, editorial, playful, industrial, warm handmade, high-contrast data tool, etc.
|
|
32
|
-
- **Information hierarchy**: What must be visible
|
|
36
|
+
- **Information hierarchy**: What must be visible to orient and act, and what
|
|
37
|
+
can wait until context or intent makes it relevant?
|
|
33
38
|
- **Differentiation**: What makes this feel designed for this exact domain?
|
|
34
39
|
|
|
35
40
|
Then implement working code that is cohesive, accessible, responsive, and polished in small details: typography, spacing, copy, motion, empty states, loading states, focus states, and error states.
|
|
@@ -50,46 +55,80 @@ before selecting its accent family. Shared behavior and semantic token names
|
|
|
50
55
|
should stay consistent; palette, density, composition, type contrast, and
|
|
51
56
|
shape language should not be identical by default.
|
|
52
57
|
|
|
53
|
-
## Minimalism And Progressive Disclosure
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- **
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- **
|
|
92
|
-
|
|
58
|
+
## High-Signal Minimalism And Progressive Disclosure
|
|
59
|
+
|
|
60
|
+
Minimalism means fewer competing kinds of UI, not less useful information. Keep
|
|
61
|
+
surfaces dense and scannable: reduce redundant prose, decorative containers,
|
|
62
|
+
borders, badges, accent colors, and persistent controls before removing content
|
|
63
|
+
that helps the user orient, compare, decide, or recover. The reference class is
|
|
64
|
+
calm productivity software such as ChatGPT/Codex, Linear, and Vercel, not empty
|
|
65
|
+
whitespace.
|
|
66
|
+
|
|
67
|
+
### Product UX Philosophy
|
|
68
|
+
|
|
69
|
+
Apply these principles as binding decision rules:
|
|
70
|
+
|
|
71
|
+
- **Purpose over presence**: Every visible element must support orientation,
|
|
72
|
+
state comprehension, a decision, an action, or recovery. Before adding one,
|
|
73
|
+
name which; if it supports none or duplicates another element, remove or
|
|
74
|
+
defer it.
|
|
75
|
+
- **Clarity over cleverness**: Use plain language, familiar patterns, explicit
|
|
76
|
+
hierarchy, and visible state. Do not make decoration or invented terminology
|
|
77
|
+
carry meaning. Preserve the labels, hit targets, focus states, and recovery
|
|
78
|
+
paths required for accessible use.
|
|
79
|
+
- **Simple first, powerful on demand**: Keep the current task and state in the
|
|
80
|
+
default presentation. Put advanced, rare, diagnostic, and secondary work
|
|
81
|
+
behind contextual disclosure, menus, or Settings. Do not turn a discoverability
|
|
82
|
+
concern into permanent chrome, and do not hide information needed for the
|
|
83
|
+
current decision.
|
|
84
|
+
- **Hierarchy over chrome**: Use typography, spacing, alignment, and restrained
|
|
85
|
+
emphasis to organize information. Treat prose, controls, borders, cards,
|
|
86
|
+
badges, and accent colors as a competition budget: reduce competing kinds of
|
|
87
|
+
elements before reducing useful information. When a surface has one clear
|
|
88
|
+
next decision, give it dominant emphasis and move secondary actions out of
|
|
89
|
+
the default path. Do not wrap every section in a card or add borders for
|
|
90
|
+
grouping alone; use spacing, alignment, typography, or dividers first. A
|
|
91
|
+
container must communicate grouping, state, or interaction.
|
|
92
|
+
- **Coherence over novelty**: Reuse the product's primitives, interaction
|
|
93
|
+
patterns, and language. When given a screenshot or reference product, match
|
|
94
|
+
its underlying hierarchy, density, and behavior; do not copy decoration or
|
|
95
|
+
introduce a second visual language without a product reason.
|
|
96
|
+
- **Quiet continuity**: Feedback must be immediate, contextual, and honest.
|
|
97
|
+
Preserve the user's place and layout, make loading, empty, and error states
|
|
98
|
+
understandable, and use motion only to explain a change.
|
|
99
|
+
- **Respect repeated use**: Optimize for the hundredth use, not the first
|
|
100
|
+
impression. If a control repeats an explanation, occupies persistent space
|
|
101
|
+
for an occasional task, or turns routine work into ceremony, remove it or
|
|
102
|
+
move it to the contextual surface that owns it.
|
|
103
|
+
|
|
104
|
+
### Progressive Disclosure And Information Timing
|
|
105
|
+
|
|
106
|
+
Expose information and controls according to relevance, frequency, and
|
|
107
|
+
consequence. Before coding, inventory the content and actions and assign them to
|
|
108
|
+
the smallest useful visibility layer:
|
|
109
|
+
|
|
110
|
+
1. **Orient and act**: location, current state, and context needed for the next
|
|
111
|
+
meaningful choice.
|
|
112
|
+
2. **Support active work**: details and controls for the selected item or
|
|
113
|
+
current workflow.
|
|
114
|
+
3. **Available on demand**: advanced settings, diagnostics, credentials,
|
|
115
|
+
metadata, destructive actions, documentation, and rare tools.
|
|
116
|
+
|
|
117
|
+
Use a disclosure pattern that matches the task. Keep independent concerns easy
|
|
118
|
+
to scan inside an expanded area instead of dumping every form, explanation,
|
|
119
|
+
and secondary action into the first reveal. A collapsed row must retain its
|
|
120
|
+
label and essential state; remove explanatory subtext unless it changes the
|
|
121
|
+
next decision. For configuration with a known current state, show that state
|
|
122
|
+
first and expose editing contextually instead of defaulting to a full form.
|
|
123
|
+
|
|
124
|
+
Before shipping, verify collapsed, expanded, loading, empty, error, and
|
|
125
|
+
narrow-width states. The default state fails review when its first viewport
|
|
126
|
+
contains multiple unrelated forms, repeated explanatory copy, documentation
|
|
127
|
+
links, or controls for unrelated tasks. It also fails when useful information
|
|
128
|
+
has been replaced with empty whitespace or extra clicks solely to look minimal.
|
|
129
|
+
The default state passes when users can identify their location, current state,
|
|
130
|
+
current task, and relevant next choice without reading documentation, while
|
|
131
|
+
the useful information remains dense and scannable.
|
|
93
132
|
|
|
94
133
|
## Aesthetic Guidelines
|
|
95
134
|
|
|
@@ -166,26 +205,28 @@ passed this requirement yet.
|
|
|
166
205
|
|
|
167
206
|
### Product Surface Review
|
|
168
207
|
|
|
169
|
-
Before shipping a new app or a substantial redesign, review the
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
208
|
+
Before shipping a new app or a substantial redesign, review the surface as an
|
|
209
|
+
operator would use it repeatedly:
|
|
210
|
+
|
|
211
|
+
- Can users identify where they are, what state they are in, and what
|
|
212
|
+
meaningful choices or next steps are available?
|
|
213
|
+
- Remove competing or redundant elements, then place optional inputs, provider
|
|
214
|
+
choices, diagnostics, long explanations, and secondary actions where they
|
|
215
|
+
remain discoverable without crowding the current task.
|
|
216
|
+
- Match the composition to the workflow. Use a focused page or step flow when
|
|
217
|
+
the work is sequential; use an overview when comparing or monitoring several
|
|
218
|
+
things is genuinely the job. Preserve the user's progress in either case.
|
|
179
219
|
- Remove generic hero copy, feature tours, repeated helper text, nested cards,
|
|
180
220
|
status-chip soup, and decorative AI treatment before adding more styling.
|
|
181
|
-
- For review flows,
|
|
182
|
-
|
|
183
|
-
|
|
221
|
+
- For review flows, choose stacking, side-by-side comparison, or another
|
|
222
|
+
composition based on content length, scanability, and the user's comparison
|
|
223
|
+
task.
|
|
184
224
|
- Compare the result with sibling apps. Shared toolkit behavior should feel
|
|
185
225
|
consistent, but a repeated palette, hero composition, type pairing, and
|
|
186
226
|
radius language without a product reason is visual drift, not consistency.
|
|
187
|
-
- Check the result at the target desktop width and a
|
|
188
|
-
|
|
227
|
+
- Check the result with realistic content at the target desktop width and a
|
|
228
|
+
narrow width. If it feels like documentation instead of a tool, reduce noise
|
|
229
|
+
or clarify the hierarchy.
|
|
189
230
|
|
|
190
231
|
## shadcn/ui Design Rules
|
|
191
232
|
|
|
@@ -203,18 +244,24 @@ as an operator would use it repeatedly:
|
|
|
203
244
|
not show generic "Loading..." text for content loads; reserve `Spinner` for
|
|
204
245
|
brief mutations, uploads, and progress actions. Use the app's existing
|
|
205
246
|
loading primitive when it is a genuine design-system adapter. Empty states
|
|
206
|
-
should
|
|
247
|
+
should communicate the state and offer the appropriate next step or small set
|
|
248
|
+
of choices.
|
|
207
249
|
|
|
208
250
|
## Anti-Patterns
|
|
209
251
|
|
|
210
|
-
Avoid
|
|
252
|
+
Avoid patterns that add visual noise, obscure state, or compete with the user's
|
|
253
|
+
task without a clear product reason:
|
|
211
254
|
|
|
212
255
|
- Generic AI aesthetics: purple gradients, glassy cards everywhere, vague sparkle language, decorative blobs, and context-free hero sections.
|
|
213
256
|
- Custom reimplementations of shadcn primitives.
|
|
214
257
|
- Raw color overrides on shared components when semantic tokens or variants would work.
|
|
215
|
-
- New always-visible controls for rare actions
|
|
216
|
-
|
|
217
|
-
-
|
|
258
|
+
- New always-visible controls for rare actions when a contextual surface would
|
|
259
|
+
preserve discoverability and reduce noise.
|
|
260
|
+
- Full-width banners, persistent helper rows, decorative cards, or explanatory
|
|
261
|
+
chrome for status that could be communicated more clearly with less weight.
|
|
262
|
+
- Hiding essential meaning or operability behind progressive disclosure. Defer
|
|
263
|
+
complexity when it is contextual or infrequent, but preserve labels, focus,
|
|
264
|
+
hit targets, accessibility, and recovery paths.
|
|
218
265
|
- UI cards nested inside other cards.
|
|
219
266
|
- Text or icons that resize or shift fixed-format UI on hover/loading.
|
|
220
267
|
|
|
@@ -3,8 +3,9 @@ name: turn-into-app
|
|
|
3
3
|
description: >-
|
|
4
4
|
Turn visible project context, a proven thread, skill, or workflow into a
|
|
5
5
|
runnable Agent-Native app with simple buttons, visible agent steps, preview,
|
|
6
|
-
and deployment handoff. Use when a user invokes `/turn-into-app
|
|
7
|
-
make a workflow into an app, including from
|
|
6
|
+
and deployment handoff. Use when a user invokes `/turn-into-app`,
|
|
7
|
+
`/make-into-app`, or asks to make a workflow into an app, including from
|
|
8
|
+
Claude or ChatGPT on the web.
|
|
8
9
|
user-invocable: true
|
|
9
10
|
scope: both
|
|
10
11
|
metadata:
|
|
@@ -38,6 +39,15 @@ The build location depends on the host. Treat this as a hard routing rule:
|
|
|
38
39
|
workspace, follow the local implementation steps below. The local agent may
|
|
39
40
|
scaffold, edit, run, and verify the app there.
|
|
40
41
|
|
|
42
|
+
Once the source brief is sufficient to identify a repeatable workflow, the
|
|
43
|
+
handoff is non-interactive. Do not ask the user for visual, product, copy,
|
|
44
|
+
layout, template, integration, or implementation choices that can be resolved
|
|
45
|
+
from the source. Select the source's recommended option; otherwise choose the
|
|
46
|
+
most direct conventional default and record the assumption for later review.
|
|
47
|
+
Only stop for a genuine hard blocker such as missing authorization, a
|
|
48
|
+
destructive external action, an ambiguous target workspace, or no identifiable
|
|
49
|
+
workflow at all.
|
|
50
|
+
|
|
41
51
|
## Default behavior
|
|
42
52
|
|
|
43
53
|
For a local code-agent runtime this is an end-to-end build skill, not a request
|
|
@@ -104,14 +114,16 @@ before creating the app. Read the host-provided context in this order:
|
|
|
104
114
|
Record the brief with these headings before handoff: source and provenance,
|
|
105
115
|
project goal, configuration and constraints, knowledge sources, repeatable
|
|
106
116
|
workflow, inputs and outputs, judgment and review points, representative runs,
|
|
107
|
-
integrations and permissions, and unknowns. This is the compact contract for
|
|
117
|
+
integrations and permissions, and unknowns and assumptions. This is the compact contract for
|
|
108
118
|
the app. It keeps the new app useful without pretending that hidden Project
|
|
109
119
|
history was imported. See [the fresh Project reference](references/fresh-project.md)
|
|
110
120
|
for the host setup and brief template.
|
|
111
121
|
|
|
112
|
-
If the visible Project context has no concrete repeatable job
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
If the visible Project context has no concrete repeatable job and no primary
|
|
123
|
+
goal can be inferred, ask for one focused clarification or a representative
|
|
124
|
+
artifact. Otherwise use the project's primary goal and source conventions; do
|
|
125
|
+
not ask a questionnaire and do not fall back to a generic “what app do you
|
|
126
|
+
want to make?” builder.
|
|
115
127
|
|
|
116
128
|
## Source selection guard
|
|
117
129
|
|
|
@@ -36,7 +36,7 @@ Inputs and outputs:
|
|
|
36
36
|
Judgment and review points:
|
|
37
37
|
Representative runs: none, or 1-3 selected examples
|
|
38
38
|
Integrations and permissions:
|
|
39
|
-
Unknowns and
|
|
39
|
+
Unknowns and assumptions:
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Keep source references bounded. Prefer a file name, URL, resource ID, or short
|
|
@@ -69,6 +69,13 @@ do not fall back to a local sandbox build. Claude Code and Codex Code are the
|
|
|
69
69
|
local-agent exception and may follow the implementation steps in the main
|
|
70
70
|
skill.
|
|
71
71
|
|
|
72
|
+
The brief is an implementation authorization, not a questionnaire. After a
|
|
73
|
+
repeatable workflow is identifiable, choose any source-recommended option
|
|
74
|
+
automatically. For unresolved non-blocking choices, use the most direct
|
|
75
|
+
conventional default, record it under assumptions, and continue. Ask only when
|
|
76
|
+
there is no identifiable workflow, no authorized target workspace, or a
|
|
77
|
+
destructive/credential boundary genuinely prevents the handoff.
|
|
78
|
+
|
|
72
79
|
In a new Project chat, say:
|
|
73
80
|
|
|
74
81
|
```text
|
|
@@ -1,34 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAgentNativeI18nCatalog } from "@agent-native/core/client/i18n";
|
|
2
2
|
|
|
3
3
|
import enUS from "./en-US";
|
|
4
4
|
|
|
5
|
-
export const i18nCatalog = {
|
|
6
|
-
sourceLocale: "en-US",
|
|
5
|
+
export const i18nCatalog = createAgentNativeI18nCatalog({
|
|
7
6
|
messages: enUS,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return (await import("./de-DE")).default;
|
|
20
|
-
case "ja-JP":
|
|
21
|
-
return (await import("./ja-JP")).default;
|
|
22
|
-
case "ko-KR":
|
|
23
|
-
return (await import("./ko-KR")).default;
|
|
24
|
-
case "pt-BR":
|
|
25
|
-
return (await import("./pt-BR")).default;
|
|
26
|
-
case "hi-IN":
|
|
27
|
-
return (await import("./hi-IN")).default;
|
|
28
|
-
case "ar-SA":
|
|
29
|
-
return (await import("./ar-SA")).default;
|
|
30
|
-
default:
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
7
|
+
localeLoaders: {
|
|
8
|
+
"zh-CN": () => import("./zh-CN"),
|
|
9
|
+
"zh-TW": () => import("./zh-TW"),
|
|
10
|
+
"es-ES": () => import("./es-ES"),
|
|
11
|
+
"fr-FR": () => import("./fr-FR"),
|
|
12
|
+
"de-DE": () => import("./de-DE"),
|
|
13
|
+
"ja-JP": () => import("./ja-JP"),
|
|
14
|
+
"ko-KR": () => import("./ko-KR"),
|
|
15
|
+
"pt-BR": () => import("./pt-BR"),
|
|
16
|
+
"hi-IN": () => import("./hi-IN"),
|
|
17
|
+
"ar-SA": () => import("./ar-SA"),
|
|
33
18
|
},
|
|
34
|
-
}
|
|
19
|
+
});
|
|
@@ -81,6 +81,13 @@ or other file-like payloads, design the upload path in the same change:
|
|
|
81
81
|
provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
|
|
82
82
|
columns or stuff files into `application_state`.
|
|
83
83
|
|
|
84
|
+
If the feature adds a server-side dependency carrying a native binary or heavy
|
|
85
|
+
runtime — headless browser, ffmpeg, image/video processing, ML runtime — read
|
|
86
|
+
the `performance` skill §9 before adding it. A deployed app has one `/*` page
|
|
87
|
+
function that every visitor's cache miss wakes, and it ships whatever the server
|
|
88
|
+
bundle depends on. Run that work from a background function or a job so the page
|
|
89
|
+
function never carries the weight.
|
|
90
|
+
|
|
84
91
|
**If the action produces or lists a navigable resource**, add a `link` builder that returns `{ url: buildDeepLink({ app, view, params }), label }`. External coding agents and MCP hosts (Claude / ChatGPT / Claude Code / Cowork / Codex, over MCP/A2A) then surface an "Open in … →" deep link that drops the user back into the running UI focused on the record — for free. If a compatible MCP host should render an inline review/edit surface, also add `mcpApp` with `embedApp()` so the action embeds the real React app route instead of a one-off HTML UI. The `link` builder and `mcpApp` metadata must be pure and synchronous (no I/O). Any external-agent read/ingest action must be `http: { method: "GET" }` + `readOnly: true` + `publicAgent: { expose: true, readOnly: true, requiresAuth: true }`. See the `external-agents` skill.
|
|
85
92
|
|
|
86
93
|
### 3. Skills / Instructions
|
|
@@ -195,4 +202,6 @@ TL;DR: declare the vocabulary once with `defineAppRoles({ appId, roles, defaultR
|
|
|
195
202
|
- **create-skill** — How to create skills for new patterns (area 3 in detail)
|
|
196
203
|
- **storing-data** — Where to store the feature's data
|
|
197
204
|
- **real-time-sync** — How the UI stays in sync when the agent writes data
|
|
205
|
+
- **performance** — Query/load cost, and (§9) cold-start artifact size when a
|
|
206
|
+
feature adds a server-side dependency
|
|
198
207
|
- **internationalization** — How to update localized UI copy and catalogs
|