@agent-native/core 0.147.0 → 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.
Files changed (172) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  4. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  5. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  6. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  8. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  9. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
  10. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  11. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  12. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  13. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  17. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  18. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  19. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  20. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  21. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  22. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  23. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  24. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  25. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  26. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  27. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  28. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  29. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  30. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  31. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  32. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  33. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  35. package/corpus/templates/content/app/i18n/index.ts +14 -29
  36. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  38. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  39. package/corpus/templates/design/actions/import-code.ts +2 -43
  40. package/corpus/templates/design/app/i18n/index.ts +14 -29
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  42. package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
  43. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  44. package/corpus/templates/factory/AGENTS.md +40 -49
  45. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  46. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  47. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  48. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  49. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  50. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  51. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  52. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  53. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  54. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  55. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  56. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  57. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  58. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  59. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  60. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  61. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  62. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  63. package/corpus/templates/factory/app/routes/factory.tsx +95 -42
  64. package/corpus/templates/factory/server/db/schema.ts +37 -0
  65. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  67. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  68. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  69. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  70. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  71. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  72. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  73. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  74. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  75. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  76. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  77. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  79. package/corpus/templates/slides/actions/import-code.ts +2 -43
  80. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  81. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  82. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  83. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  84. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  85. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  86. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  87. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  88. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  89. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  90. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  91. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  92. package/dist/agent/engine/provider-env-vars.js +1 -1
  93. package/dist/agent/engine/registry.d.ts +8 -6
  94. package/dist/agent/engine/registry.js +37 -24
  95. package/dist/agent/tool-search.d.ts +1 -0
  96. package/dist/agent/tool-search.js +17 -1
  97. package/dist/automations/service.js +4 -10
  98. package/dist/brand-kit/brand-signals.d.ts +13 -0
  99. package/dist/brand-kit/brand-signals.js +15 -0
  100. package/dist/brand-kit/index.d.ts +2 -2
  101. package/dist/brand-kit/index.js +1 -1
  102. package/dist/cli/plan-blocks.d.ts +3 -18
  103. package/dist/cli/plan-blocks.js +2 -95
  104. package/dist/cli/plan-publish-store.d.ts +2 -61
  105. package/dist/cli/plan-publish-store.js +2 -127
  106. package/dist/cli/skills-content/connection.d.ts +1 -1
  107. package/dist/cli/skills-content/connection.js +1 -52
  108. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  109. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  110. package/dist/client/agent-engine-key.d.ts +14 -4
  111. package/dist/client/agent-engine-key.js +51 -5
  112. package/dist/client/agent-provider-catalog.d.ts +20 -0
  113. package/dist/client/agent-provider-catalog.js +100 -0
  114. package/dist/client/blocks/index.d.ts +1 -0
  115. package/dist/client/blocks/index.js +1 -0
  116. package/dist/client/chat/run-recovery.js +4 -48
  117. package/dist/client/chat-first.js +4 -3
  118. package/dist/client/i18n.d.ts +14 -0
  119. package/dist/client/i18n.js +18 -0
  120. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  121. package/dist/client/settings/ProviderSetupForm.js +145 -0
  122. package/dist/client/settings/SettingsPanel.js +52 -49
  123. package/dist/client/settings/index.d.ts +2 -0
  124. package/dist/client/settings/index.js +2 -0
  125. package/dist/coding-tools/run-code.d.ts +5 -0
  126. package/dist/coding-tools/run-code.js +196 -36
  127. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  128. package/dist/coding-tools/tool-orchestration.js +107 -0
  129. package/dist/collab/awareness.d.ts +2 -2
  130. package/dist/jobs/frontmatter.d.ts +9 -0
  131. package/dist/jobs/frontmatter.js +16 -0
  132. package/dist/jobs/scheduler.js +8 -8
  133. package/dist/jobs/tools.d.ts +1 -1
  134. package/dist/jobs/tools.js +2 -7
  135. package/dist/localization/default-messages.d.ts +20 -0
  136. package/dist/localization/default-messages.js +25 -5
  137. package/dist/observability/routes.d.ts +3 -3
  138. package/dist/onboarding/app-profile.js +1 -1
  139. package/dist/progress/routes.d.ts +1 -1
  140. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  141. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  142. package/dist/resources/handlers.d.ts +1 -1
  143. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  144. package/dist/secrets/routes.d.ts +9 -9
  145. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  146. package/dist/server/agent-chat/run-code-tools.js +3 -1
  147. package/dist/server/agent-chat-plugin.js +6 -6
  148. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  149. package/dist/server/agent-engine-api-key-route.js +43 -12
  150. package/dist/server/agents-bundle.js +2 -1
  151. package/dist/server/auth.js +21 -5
  152. package/dist/server/credential-provider.js +1 -0
  153. package/dist/server/design-token-utils.d.ts +18 -0
  154. package/dist/server/design-token-utils.js +31 -0
  155. package/dist/server/onboarding-html.js +22 -2
  156. package/dist/server/realtime-token.d.ts +1 -1
  157. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  158. package/dist/templates/chat/app/i18n/index.ts +14 -29
  159. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  160. package/dist/templates/default/app/i18n/index.ts +14 -29
  161. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  162. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  163. package/dist/triggers/dispatcher.js +1 -8
  164. package/docs/content/environment-variables.mdx +39 -38
  165. package/package.json +4 -4
  166. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  167. package/src/templates/chat/app/i18n/index.ts +14 -29
  168. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  169. package/src/templates/default/app/i18n/index.ts +14 -29
  170. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  171. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  172. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 7926
34
+ - template files: 7931
@@ -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 a new page,
6
- app, or marketing surface, defining visual identity, or doing a design pass
7
- ("make this look good"). Do not load it for routine UI edits: adding a field
8
- to an existing form, fixing spacing, wiring a button, or changing copy.
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 narrowed and Verification rescoped deliberately; an upstream sync
14
- must not restore the broad auto-load triggers or screenshot-everything step.
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 is the primary action?
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 in the first five seconds, and what should be progressively disclosed?
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
- Default to Apple/Linear-level restraint: make the primary workflow obvious, then remove everything that does not help that workflow right now. A polished UI often has fewer visible controls, fewer borders, fewer labels, and fewer explanatory surfaces than the first reasonable implementation.
56
-
57
- ### Progressive Disclosure Is A Design Requirement
58
-
59
- Treat an all-at-once interface as a defect to fix during design, not as a
60
- styling preference. Before coding, inventory every piece of content and action
61
- on the surface, then assign each one to the smallest useful visibility level:
62
-
63
- 1. **Immediate** — the page title, current state, one primary action, and the
64
- compact context needed to choose what to do next.
65
- 2. **Expanded** — the details needed for the selected item or active workflow.
66
- 3. **On demand** — advanced settings, diagnostics, credentials, metadata,
67
- destructive actions, documentation, and rarely used tools.
68
-
69
- Use single-select accordions or simple disclosure rows for sibling panels when
70
- the user is choosing one item at a time. Inside an expanded panel, keep another
71
- layer for independent concerns instead of dumping every form, explanation, and
72
- secondary action into the first reveal. Prefer one flat panel with alignment,
73
- dividers, and whitespace over nested cards; provider or product icons should
74
- not receive decorative borders or containers unless the container communicates
75
- state or interaction. A collapsed row should still show the item name, status,
76
- and a concise summary so the user can scan the whole surface without opening
77
- everything.
78
-
79
- Before shipping, ask: “What can disappear until the user asks for it?” Then
80
- verify collapsed, expanded, loading, empty, error, and narrow-width states.
81
- If the first viewport contains multiple forms, repeated explanatory copy,
82
- documentation links, and controls for unrelated tasks, the surface has not
83
- passed this requirement yet.
84
-
85
- - **Start by subtracting**: Before adding a visible control, banner, toolbar row, card, or explanatory block, ask what can be removed, merged, renamed, or moved into an existing affordance.
86
- - **One primary action**: Each surface should have one dominant next action. Secondary actions belong in menus, popovers, command palettes, disclosure rows, or contextual hover/focus states unless they are used constantly.
87
- - **Progressively disclose rare work**: Advanced options, diagnostics, metadata, settings, import/export, destructive actions, and inspection tools should stay tucked away until requested. Prefer small icon triggers with tooltips, popovers, drawers, or detail panels over permanent chrome.
88
- - **Keep chrome quiet**: Avoid new always-visible bars, badges, callouts, helper text, and counters unless they prevent mistakes or are central to repeated use. Status can often be a dot, ring, muted count, or tooltip.
89
- - **Favor content over containers**: Do not wrap every section in a card. Use whitespace, alignment, typography, dividers, and full-width bands before adding boxes.
90
- - **Design for repeated use**: Production app UI should feel calm after the hundredth use. If a control shouts, animates, explains itself, or occupies a full row for an occasional action, hide or compress it.
91
- - **Make absence intentional**: Empty states should be sparse and action-oriented. Do not fill blank space with marketing copy, decorative art, or lists of features just because the screen feels empty.
92
- - **Use familiar primitives**: Icon buttons need clear tooltips. Menus, popovers, tabs, switches, and segmented controls should carry complexity instead of exposing every option at once.
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 first viewport
170
- as an operator would use it repeatedly:
171
-
172
- - Show one clear job title, the current state, and one primary next action.
173
- - Put optional inputs, provider choices, diagnostics, long explanations, and
174
- secondary actions behind a disclosure, a later step, a menu, or the agent
175
- sidebar. Do not put multiple unrelated forms side by side by default.
176
- - Prefer a short step flow or a focused page per domain job over one giant
177
- dashboard. A route can have several states, but it should reveal one state
178
- at a time and preserve the user's progress.
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, stack the source/original first and the generated or safe
182
- result second by default. Use side-by-side comparison only when the content
183
- is short enough to scan without excessive horizontal reading.
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 narrow width. If the first
188
- viewport feels like documentation instead of a tool, subtract again.
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 have one clear next action.
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. Prefer menus, popovers, sheets, tabs, collapsibles, or advanced sections.
216
- - Full-width banners, persistent helper rows, decorative cards, or explanatory chrome for status that could be a compact affordance.
217
- - Treating progressive disclosure as optional. If a control is not part of the main daily workflow, hide it until context, hover, focus, or explicit user intent makes it relevant.
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
 
@@ -190,8 +190,15 @@ for an explicitly selected organization. It is dry-run by default. It uses the
190
190
  scoped credential resolver, fixed high-water marks, separate organization and
191
191
  legacy-owner cursors, atomic local checkpoints, a local lock, and a durable
192
192
  database lease shared with the shipped worker. The tuple-paging indexes are
193
- installed by the additive analytics migration. It does not change the Analytics
194
- sink or perform cutover.
193
+ installed by the additive analytics migration, including a filtered cursor
194
+ index for the default `http.response` exclusion. By default it copies the most
195
+ recent 60 days, paging from the oldest eligible row to the newest so an
196
+ existing checkpoint can resume without duplicates or gaps. Use
197
+ `--lookback-days=30` when a 30-day window is sufficient; the worker accepts
198
+ 30-60 days only. It skips the high-volume `http.response` infrastructure
199
+ telemetry by default. Override the exclusion list with `--skip-events=<csv>`;
200
+ an empty value includes every event name. It does not change the Analytics sink
201
+ or perform cutover.
195
202
 
196
203
  ```bash
197
204
  pnpm backfill:first-party-bigquery \
@@ -217,8 +224,48 @@ AGENT_NATIVE_ANALYTICS_BIGQUERY_BACKFILL_ALLOW=1 pnpm backfill:first-party-bigqu
217
224
  --max-batches=100
218
225
  ```
219
226
 
227
+ The shipped durable worker uses the same policy. Set
228
+ `ANALYTICS_BIGQUERY_BACKFILL_LOOKBACK_DAYS` and
229
+ `ANALYTICS_BIGQUERY_BACKFILL_SKIP_EVENTS` to override its 30-60 day window and
230
+ comma-separated event exclusions. The default exclusion is only
231
+ `http.response`; action responses, exceptions, pageviews, session events,
232
+ agent-run events, A2A invocations, session replay, and public-key metadata are
233
+ preserved.
234
+
235
+ ### Postgres event volume guard
236
+
237
+ New tenants that remain on the default Postgres sink are capped at 1,000,000
238
+ accepted events per fixed UTC 30-day window. The reservation is atomic per
239
+ organization (or per owner for legacy personal keys), so concurrent `/track`
240
+ requests cannot overshoot the cap. Once reached, `/track` returns HTTP 429 with
241
+ guidance to connect an external analytics database or BigQuery. SQL-only
242
+ exception issues and public-key last-used metadata are still preserved for a
243
+ rejected batch; session replay uses its separate quota path.
244
+
245
+ Operators can raise or lower the guard with:
246
+
247
+ ```bash
248
+ ANALYTICS_FIRST_PARTY_POSTGRES_EVENT_VOLUME_LIMIT=1000000
249
+ ANALYTICS_FIRST_PARTY_POSTGRES_EVENT_VOLUME_WINDOW_DAYS=30
250
+ ```
251
+
252
+ The guard applies only while an organization uses the `postgres` sink. Dual
253
+ write and BigQuery-only organizations continue to accept events through the
254
+ warehouse path while the migration state machine controls cutover.
255
+
256
+ Postgres cleanup is intentionally a separate bounded action:
257
+ `purge-first-party-analytics-postgres` is dry-run by default, limits work to a
258
+ 30-60 day window, counts only the current organization (legacy owner rows are
259
+ opt-in), and compares the scoped BigQuery count before any delete. It never
260
+ removes exception issues, session replay, public-key metadata, migration state,
261
+ or volume counters. A write also requires a completed BigQuery cutover, the
262
+ exact `PURGE_FIRST_PARTY_POSTGRES_EVENTS` confirmation, normal action approval,
263
+ and parity unless `allowUncopiedEvents=true` is explicitly accepted.
264
+
220
265
  The checkpoint file contains cursors and counts, not event payloads or
221
- credentials. A short page triggers a fresh high-water check so rows written
266
+ credentials. A v1 checkpoint is upgraded in place with the bounded source
267
+ window and event filter while retaining its cursor and copied counts. A short
268
+ page triggers a fresh high-water check so rows written
222
269
  while the worker is running are included. A partial BigQuery acknowledgement
223
270
  does not advance the cursor; retry it promptly, or run an insertId-deduplication
224
271
  or `MERGE` pass on the target table before finalizing.
@@ -0,0 +1,190 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import {
3
+ getRequestOrgId,
4
+ getRequestUserEmail,
5
+ } from "@agent-native/core/server";
6
+ import { z } from "zod";
7
+
8
+ import { requireAnalyticsAdminContext } from "../server/lib/db-admin-connections.js";
9
+ import {
10
+ assertFirstPartyAnalyticsBigQueryReady,
11
+ getFirstPartyAnalyticsBackend,
12
+ getFirstPartyAnalyticsBigQueryMetrics,
13
+ } from "../server/lib/first-party-analytics-backend.js";
14
+ import {
15
+ countFirstPartyAnalyticsPostgresRows,
16
+ purgeFirstPartyAnalyticsPostgresRows,
17
+ } from "../server/lib/first-party-analytics-purge.js";
18
+
19
+ const confirmation = "PURGE_FIRST_PARTY_POSTGRES_EVENTS" as const;
20
+ const DAY_MS = 24 * 60 * 60 * 1000;
21
+
22
+ async function resolveScope() {
23
+ const userEmail = getRequestUserEmail();
24
+ const orgId = getRequestOrgId();
25
+ const admin = await requireAnalyticsAdminContext({ userEmail, orgId });
26
+ return { userEmail: admin.userEmail, orgId: admin.orgId };
27
+ }
28
+
29
+ export default defineAction({
30
+ description:
31
+ "Dry-run or explicitly purge a bounded 30-60 day window of the current organization's first-party event rows and derived rollups from Postgres after BigQuery cutover. The default is read-only. The write path requires the BigQuery sink, a completed backfill, exact confirmation, and normal action approval; exception issues, session replay, public-key metadata, migration state, and volume counters are never deleted.",
32
+ agentTool: false,
33
+ schema: z.object({
34
+ lookbackDays: z
35
+ .number()
36
+ .int()
37
+ .min(30)
38
+ .max(60)
39
+ .optional()
40
+ .default(60)
41
+ .describe("Bound the purge to the most recent 30-60 days (default 60)."),
42
+ dryRun: z
43
+ .boolean()
44
+ .optional()
45
+ .default(true)
46
+ .describe("Inspect counts without deleting when true (default)."),
47
+ includeLegacyOwnerRows: z
48
+ .boolean()
49
+ .optional()
50
+ .default(false)
51
+ .describe(
52
+ "Include legacy rows with this owner's email and no org id. Keep false unless the dry-run proves those rows belong to this migration.",
53
+ ),
54
+ allowUncopiedEvents: z
55
+ .boolean()
56
+ .optional()
57
+ .default(false)
58
+ .describe(
59
+ "Allow deletion when the scoped BigQuery event count is lower than Postgres. Keep false to prevent data loss from skipped historical event types.",
60
+ ),
61
+ confirm: z
62
+ .literal(confirmation)
63
+ .optional()
64
+ .describe(
65
+ "Required for deletion: PURGE_FIRST_PARTY_POSTGRES_EVENTS. Do not send it for a dry run.",
66
+ ),
67
+ }),
68
+ needsApproval: ({ dryRun }) => !dryRun,
69
+ run: async ({
70
+ lookbackDays,
71
+ dryRun,
72
+ includeLegacyOwnerRows,
73
+ allowUncopiedEvents,
74
+ confirm,
75
+ }) => {
76
+ const scope = await resolveScope();
77
+ if (!dryRun && confirm !== confirmation) {
78
+ throw new Error(
79
+ `Refusing to delete first-party Postgres events without confirm=${confirmation}. Run a dry run first, then repeat with the exact confirmation token.`,
80
+ );
81
+ }
82
+
83
+ const backend = await getFirstPartyAnalyticsBackend(scope);
84
+ const startReceivedAt = new Date(
85
+ Date.now() - lookbackDays * DAY_MS,
86
+ ).toISOString();
87
+ const window = {
88
+ startReceivedAt,
89
+ startEventDate: startReceivedAt.slice(0, 10),
90
+ };
91
+ const postgres = await countFirstPartyAnalyticsPostgresRows(
92
+ scope,
93
+ includeLegacyOwnerRows,
94
+ window,
95
+ );
96
+ let bigQuery: {
97
+ eventCount: number;
98
+ dailyRollupRows: number;
99
+ firstEventDate: string | null;
100
+ lastEventDate: string | null;
101
+ } | null = null;
102
+ let bigQueryError: string | null = null;
103
+ if (backend.table) {
104
+ try {
105
+ await assertFirstPartyAnalyticsBigQueryReady(backend.table, {
106
+ includeRowCount: false,
107
+ });
108
+ bigQuery = await getFirstPartyAnalyticsBigQueryMetrics(
109
+ scope,
110
+ backend.table,
111
+ { includeLegacyOwnerRows, startDate: window.startEventDate },
112
+ );
113
+ } catch (error) {
114
+ bigQueryError = error instanceof Error ? error.message : String(error);
115
+ }
116
+ }
117
+
118
+ const uncopiedEventRows = bigQuery
119
+ ? Math.max(0, postgres.eventRows - bigQuery.eventCount)
120
+ : null;
121
+ const safeToDelete =
122
+ backend.sink === "bigquery" &&
123
+ backend.backfillCompleted === true &&
124
+ bigQueryError === null &&
125
+ bigQuery !== null &&
126
+ uncopiedEventRows === 0;
127
+
128
+ if (!dryRun) {
129
+ if (backend.sink !== "bigquery") {
130
+ throw new Error(
131
+ "Postgres purge is blocked until this organization has completed the normal BigQuery cutover.",
132
+ );
133
+ }
134
+ if (backend.backfillCompleted !== true) {
135
+ throw new Error(
136
+ "Postgres purge is blocked until the durable BigQuery backfill reports completed.",
137
+ );
138
+ }
139
+ if (bigQueryError || !bigQuery) {
140
+ throw new Error(
141
+ `Postgres purge is blocked because BigQuery readiness could not be verified: ${bigQueryError ?? "unknown warehouse state"}`,
142
+ );
143
+ }
144
+ if (uncopiedEventRows !== 0 && !allowUncopiedEvents) {
145
+ throw new Error(
146
+ `Postgres purge is blocked: ${uncopiedEventRows} scoped event rows are not present in BigQuery. Keep allowUncopiedEvents=false unless this loss is explicitly accepted.`,
147
+ );
148
+ }
149
+ const deleted = await purgeFirstPartyAnalyticsPostgresRows(
150
+ scope,
151
+ includeLegacyOwnerRows,
152
+ window,
153
+ );
154
+ return {
155
+ dryRun: false,
156
+ lookbackDays,
157
+ window,
158
+ deleted,
159
+ bigQuery,
160
+ uncopiedEventRows,
161
+ includeLegacyOwnerRows,
162
+ preserved: [
163
+ "analytics_exception_events",
164
+ "error_issues",
165
+ "error_issue_occurrences",
166
+ "session_recordings",
167
+ "session_replay_chunks",
168
+ "session_replay_ingests",
169
+ "analytics_public_keys",
170
+ "analytics_event_volume_usage",
171
+ ],
172
+ };
173
+ }
174
+
175
+ return {
176
+ dryRun: true,
177
+ lookbackDays,
178
+ window,
179
+ sink: backend.sink,
180
+ backfillCompleted: backend.backfillCompleted === true,
181
+ postgres,
182
+ bigQuery,
183
+ bigQueryError,
184
+ uncopiedEventRows,
185
+ includeLegacyOwnerRows,
186
+ safeToDelete,
187
+ confirmationRequired: confirmation,
188
+ };
189
+ },
190
+ });
@@ -1,34 +1,19 @@
1
- import { type AgentNativeI18nCatalog } from "@agent-native/core/client/i18n";
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
- loadMessages: async (locale) => {
9
- switch (locale) {
10
- case "zh-CN":
11
- return (await import("./zh-CN")).default;
12
- case "zh-TW":
13
- return (await import("./zh-TW")).default;
14
- case "es-ES":
15
- return (await import("./es-ES")).default;
16
- case "fr-FR":
17
- return (await import("./fr-FR")).default;
18
- case "de-DE":
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
- } satisfies AgentNativeI18nCatalog;
19
+ });