@agent-native/core 0.176.0-nightly-20260828040116 → 0.176.1

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 (116) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +15 -0
  3. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +19 -18
  4. package/corpus/templates/analytics/docs/schemas/tracked-events.md +5 -1
  5. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +8 -6
  6. package/corpus/templates/assets/.agents/skills/assets-navigation/SKILL.md +9 -6
  7. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +22 -21
  8. package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +1 -1
  9. package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +11 -9
  10. package/corpus/templates/assets/AGENTS.md +16 -11
  11. package/corpus/templates/assets/CHANGELOG.md +6 -0
  12. package/corpus/templates/assets/actions/_helpers.ts +15 -0
  13. package/corpus/templates/assets/actions/_template-access.ts +71 -0
  14. package/corpus/templates/assets/actions/_template-input.ts +51 -0
  15. package/corpus/templates/assets/actions/associate-template.ts +39 -0
  16. package/corpus/templates/assets/actions/create-generation-preset.ts +3 -68
  17. package/corpus/templates/assets/actions/create-generation-session.ts +7 -10
  18. package/corpus/templates/assets/actions/create-library-from-preset.ts +2 -2
  19. package/corpus/templates/assets/actions/create-library.ts +2 -2
  20. package/corpus/templates/assets/actions/create-template.ts +86 -0
  21. package/corpus/templates/assets/actions/delete-generation-preset.ts +3 -29
  22. package/corpus/templates/assets/actions/delete-library.ts +11 -2
  23. package/corpus/templates/assets/actions/delete-template.ts +36 -0
  24. package/corpus/templates/assets/actions/duplicate-library.ts +9 -5
  25. package/corpus/templates/assets/actions/duplicate-template.ts +81 -0
  26. package/corpus/templates/assets/actions/generate-asset.ts +6 -3
  27. package/corpus/templates/assets/actions/generate-image-batch.ts +6 -5
  28. package/corpus/templates/assets/actions/generate-image.ts +23 -18
  29. package/corpus/templates/assets/actions/get-generation-session.ts +14 -5
  30. package/corpus/templates/assets/actions/get-template.ts +25 -0
  31. package/corpus/templates/assets/actions/list-generation-presets.ts +8 -26
  32. package/corpus/templates/assets/actions/list-templates.ts +90 -0
  33. package/corpus/templates/assets/actions/merge-duplicate-templates.ts +178 -0
  34. package/corpus/templates/assets/actions/navigate.ts +4 -1
  35. package/corpus/templates/assets/actions/rerun-generation-run.ts +3 -5
  36. package/corpus/templates/assets/actions/update-generation-preset.ts +4 -88
  37. package/corpus/templates/assets/actions/update-template.ts +87 -0
  38. package/corpus/templates/assets/actions/view-screen.ts +10 -0
  39. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +6 -1
  40. package/corpus/templates/assets/app/components/library/CreateTemplateDialog.tsx +214 -0
  41. package/corpus/templates/assets/app/components/library/TemplatesPanel.tsx +116 -0
  42. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -2
  43. package/corpus/templates/assets/app/i18n-data.ts +393 -0
  44. package/corpus/templates/assets/app/lib/asset-urls.ts +34 -0
  45. package/corpus/templates/assets/app/lib/picker-chat-handoff.ts +9 -5
  46. package/corpus/templates/assets/app/lib/template-composer-reference.ts +62 -0
  47. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +2 -2
  48. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +7 -2431
  49. package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +4 -7
  50. package/corpus/templates/assets/app/routes/library.tsx +15 -31
  51. package/corpus/templates/assets/app/routes/templates.$templateId.tsx +2492 -0
  52. package/corpus/templates/assets/app/routes/templates._index.tsx +360 -0
  53. package/corpus/templates/assets/app/routes/templates.tsx +11 -0
  54. package/corpus/templates/assets/changelog/2026-08-26-templates-across-brand-kits.md +5 -0
  55. package/corpus/templates/assets/server/db/index.ts +10 -0
  56. package/corpus/templates/assets/server/db/schema.ts +25 -0
  57. package/corpus/templates/assets/server/lib/generation-presets.ts +94 -32
  58. package/corpus/templates/assets/server/lib/{preset-chat-context.ts → template-chat-context.ts} +48 -34
  59. package/corpus/templates/assets/server/plugins/agent-chat.ts +72 -64
  60. package/corpus/templates/assets/server/plugins/creative-context.ts +0 -2
  61. package/corpus/templates/assets/server/plugins/db.ts +87 -0
  62. package/corpus/templates/assets/shared/api.ts +12 -0
  63. package/corpus/templates/chat/CHANGELOG.md +11 -0
  64. package/corpus/templates/clips/app/components/library/search-bar.tsx +7 -1
  65. package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -1
  66. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +262 -6
  67. package/corpus/templates/design/CHANGELOG.md +28 -0
  68. package/corpus/templates/design/actions/update-file.ts +4 -6
  69. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +5 -2
  70. package/corpus/templates/design/app/components/design/EditPanel.tsx +8 -0
  71. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +397 -12
  72. package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +15 -0
  73. package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +14 -0
  74. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +352 -111
  75. package/corpus/templates/design/app/components/design/inspector/design-icons.tsx +1 -0
  76. package/corpus/templates/design/app/pages/DesignEditor.tsx +85 -5
  77. package/corpus/templates/design/app/pages/design-editor/commands/apply-layout-flow.ts +78 -0
  78. package/corpus/templates/design/app/pages/design-editor/commands/pasted-image-files.ts +110 -14
  79. package/corpus/templates/design/changelog/2026-08-27-grid-auto-layout-now-lays-children-out-in-cells-and-shows-the-cell-grid.md +6 -0
  80. package/corpus/templates/design/changelog/2026-08-27-outermost-frames-now-show-their-name-on-the-canvas.md +6 -0
  81. package/corpus/templates/design/server/source-workspace.ts +1 -7
  82. package/corpus/templates/design/shared/code-layer.ts +46 -10
  83. package/corpus/templates/design/shared/locked-layers.ts +178 -64
  84. package/corpus/templates/factory/AGENTS.md +2 -1
  85. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +757 -42
  86. package/corpus/templates/factory/actions/ingest-github-observation.ts +10 -1
  87. package/corpus/templates/factory/actions/reconcile-triage-run.ts +3 -0
  88. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +10 -1
  89. package/corpus/templates/factory/server/triage/ai-services-git.ts +6 -0
  90. package/corpus/templates/factory/server/triage/contracts.ts +1 -0
  91. package/corpus/templates/factory/server/triage/github-client.ts +93 -15
  92. package/corpus/templates/factory/server/triage/pr-monitor.ts +3 -0
  93. package/corpus/templates/factory/server/triage/pr-policy.ts +243 -31
  94. package/corpus/templates/factory/server/triage/review-skill-alignment.ts +16 -4
  95. package/corpus/templates/slides/CHANGELOG.md +15 -0
  96. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +7 -2
  97. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +37 -1
  98. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +941 -219
  99. package/corpus/templates/slides/app/components/editor/SlidesLayersPanel.tsx +209 -0
  100. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +194 -4
  101. package/corpus/templates/slides/app/components/editor/slide-style.ts +36 -0
  102. package/corpus/templates/slides/app/context/DeckContext.tsx +2 -0
  103. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  104. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +26 -8
  105. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +83 -2
  106. package/corpus/templates/slides/app/pages/DeckEditor.tsx +213 -51
  107. package/corpus/templates/slides/app/root.tsx +25 -6
  108. package/dist/observability/routes.d.ts +3 -3
  109. package/dist/observability/traces.d.ts +8 -0
  110. package/dist/observability/traces.js +27 -0
  111. package/dist/progress/routes.d.ts +1 -1
  112. package/dist/secrets/routes.d.ts +9 -9
  113. package/dist/templates/chat/CHANGELOG.md +11 -0
  114. package/package.json +3 -3
  115. package/src/templates/chat/CHANGELOG.md +11 -0
  116. package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +0 -326
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: 8654
34
+ - template files: 8675
@@ -3,6 +3,21 @@
3
3
  All notable user-facing changes to Agent-Native Analytics are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-08-27
7
+
8
+ ### Added
9
+
10
+ - Dashboard owners can archive dashboards from the actions menu.
11
+ - See signup, onboarding, activation, and sharing drop-off in one filterable dashboard.
12
+
13
+ ### Improved
14
+
15
+ - Show connected Google names and profile photos in analytics
16
+
17
+ ### Fixed
18
+
19
+ - Analytics exports now show a direct download in chat and reject failed responses
20
+
6
21
  ## 2026-08-26
7
22
 
8
23
  ### Improved
@@ -117,24 +117,25 @@ event_name = '$ai_sentiment'
117
117
 
118
118
  Useful query fields live in `properties`:
119
119
 
120
- | Property | Description |
121
- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
122
- | `$ai_trace_id`, `run_id` | Agent run id |
123
- | `$ai_session_id`, `thread_id` | Chat/thread id, when available |
124
- | `$ai_model`, `model` | Model used |
125
- | `$ai_provider`, `provider` | Engine/provider name |
126
- | `$ai_input_tokens`, `input_tokens` | Input tokens |
127
- | `$ai_output_tokens`, `output_tokens` | Output tokens |
128
- | `cache_read_tokens`, `cache_write_tokens` | Prompt-cache token counts |
129
- | `$ai_total_cost_usd`, `cost_usd` | Estimated run cost in USD |
130
- | `cost_cents_x100` | Estimated run cost in centicents |
131
- | `duration_ms` | Run duration in milliseconds |
132
- | `$ai_latency` | Model time in seconds (run duration minus tool time), on `$ai_generation` |
133
- | `tool_calls`, `successful_tools`, `failed_tools` | Complete tool-call counts |
134
- | `tools`, `tools_truncated` | First 50 tool names, offsets, durations, statuses, and error classes, including interrupted calls |
135
- | `delegated`, `delegation_protocol`, `caller_app` | Delegated-run attribution |
136
- | `a2a_task_id`, `parent_run_id`, `parent_turn_id` | Cross-app trace linkage, when available |
137
- | `$ai_is_error`, `status`, `$ai_error` | Error status and message, when applicable |
120
+ | Property | Description |
121
+ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
122
+ | `$ai_trace_id`, `run_id` | Agent run id |
123
+ | `$ai_session_id`, `thread_id` | Chat/thread id, when available |
124
+ | `$ai_model`, `model` | Model used |
125
+ | `$ai_provider`, `provider` | Engine/provider name |
126
+ | `$ai_input_tokens`, `input_tokens` | Input tokens |
127
+ | `$ai_output_tokens`, `output_tokens` | Output tokens |
128
+ | `cache_read_tokens`, `cache_write_tokens` | Prompt-cache token counts |
129
+ | `$ai_total_cost_usd`, `cost_usd` | Estimated run cost in USD |
130
+ | `cost_cents_x100` | Estimated run cost in centicents |
131
+ | `duration_ms` | Run duration in milliseconds |
132
+ | `$ai_latency` | Model time in seconds (run duration minus tool time), on `$ai_generation` |
133
+ | `tool_calls`, `successful_tools`, `failed_tools` | Complete tool-call counts |
134
+ | `tools`, `tools_truncated` | First 50 tool names, offsets, durations, statuses, and error classes, including interrupted calls |
135
+ | `delegated`, `delegation_protocol`, `caller_app` | Delegated-run attribution |
136
+ | `a2a_task_id`, `parent_run_id`, `parent_turn_id` | Cross-app trace linkage, when available |
137
+ | `$ai_is_error`, `status`, `$ai_error` | Error status and message, when applicable |
138
+ | `$ai_http_status` | Provider HTTP status: 200 on a completed call, the reported status on a failed one, absent when the failure carried none |
138
139
 
139
140
  The `tools` array never includes tool arguments, results, or error messages.
140
141
  Use `tools_truncated` with the complete `tool_calls` count when a run exceeds
@@ -28,7 +28,11 @@ Events tracked by application instrumentation and stored in the configured appli
28
28
  server-side tracking. Properties include `$ai_trace_id`, `$ai_session_id`,
29
29
  `$ai_model`, `$ai_provider`, `$ai_input_tokens`, `$ai_output_tokens`,
30
30
  `$ai_latency`, `$ai_total_cost_usd`, `run_id`, `thread_id`,
31
- `cost_cents_x100`, `duration_ms`, `tool_calls`, `status`, and error fields.
31
+ `cost_cents_x100`, `duration_ms`, `tool_calls`, `status`, `$ai_http_status`,
32
+ and error fields. `$ai_http_status` is 200 on a call that streamed to
33
+ completion and the provider's status on one that failed; it is absent when
34
+ the failure carried no status, so an unclassifiable transport drop is never
35
+ reported as a known rejection.
32
36
  `$ai_latency` is model time in seconds; `duration_ms` is the full run in
33
37
  milliseconds, and the two differ by the time spent in tools.
34
38
  A bounded `tools` array records only tool names, relative start times,
@@ -50,13 +50,15 @@ claiming a brand match.
50
50
  `generate-image-batch`, `generate-video`, `refresh-generation-run`, and
51
51
  `export-asset`.
52
52
  - In chat, consume composer `@` references as structured generation inputs:
53
- `brand-kit` maps to `libraryId`, `preset` maps to `presetId`, and
53
+ `brand-kit` maps to `libraryId`, `template` maps to `templateId`, and
54
54
  `media-type` chooses image generation versus video generation. If no mention
55
55
  is available, use `view-screen`, `list-libraries`, and
56
- `list-generation-presets` to choose explicit args.
57
- - Use generation presets when the user asks for a repeatable output format
58
- like social image, blog hero, or diagram. Call `list-generation-presets` for
59
- the library and pass `presetId` through generation/refinement actions.
56
+ `list-templates` to choose explicit args.
57
+ - Use Templates when the user asks for a repeatable output format like social
58
+ image, blog hero, or diagram. Call `list-templates` and pass `templateId`
59
+ through generation/refinement actions. Templates may be global or associated
60
+ with one brand kit; only associated templates can pin images, skeletons, or
61
+ a canonical logo. `*-generation-preset` actions are deprecated aliases.
60
62
  - Use generation sessions when another person needs to continue improving a
61
63
  candidate. Sessions carry the brief, preset, active asset, feedback, and run
62
64
  IDs without requiring the original chat thread.
@@ -90,7 +92,7 @@ claiming a brand match.
90
92
  `generate-image-batch` returns, use its returned `images` / asset fields
91
93
  directly; do not call `get-generation-run`, `refresh-generation-run`, or
92
94
  regenerate just to verify image runs.
93
- 5. For preset-backed work, pass a mentioned or selected `presetId`; for handoff
95
+ 5. For template-backed work, pass a mentioned or selected `templateId`; for handoff
94
96
  work, pass `sessionId`.
95
97
  6. Let the server choose a small deterministic reference set unless the user
96
98
  named exact assets. Canonical style anchors come from
@@ -26,12 +26,15 @@ generation, or embed target is unclear.
26
26
  use the right agent sidebar only on non-Create routes with view-transition
27
27
  handoff back to `/`.
28
28
 
29
- ## Generation preset editor
30
-
31
- - Humans can edit an existing generation preset from
32
- `/brand-kits/:libraryId/presets/:presetId`. Use `navigate` with
33
- `{ view: "preset", libraryId, presetId }` when sending a user to that editor.
34
- - Preset skeletons are edited from the same route; see `logo-composite` for the
29
+ ## Templates
30
+
31
+ - Humans browse Templates at `/templates` and edit one at
32
+ `/templates/:templateId`. Use `navigate` with `{ view: "templates" }` or
33
+ `{ view: "template", templateId }`. Legacy `{ view: "preset", libraryId,
34
+ presetId }` navigation still resolves for existing conversations.
35
+ - Global templates work with any accessible brand kit. Associated templates are
36
+ limited to their kit and are required for pinned images, skeletons, and logo
37
+ compositing. See `logo-composite` for the
35
38
  `settings.skeletonSpec` shape and compositing behavior.
36
39
 
37
40
  ## Context tab
@@ -58,8 +58,8 @@ evidence, screenshots, or exact logos.
58
58
  IDs/URLs; do not follow it with `get-generation-run`,
59
59
  `refresh-generation-run`, or more generation unless the user asks for another
60
60
  direction or the returned slot has `ok: false`.
61
- - For repeatable deliverables, honor a `preset` @mention as `presetId` or call
62
- `list-generation-presets` when choosing one. Pass the preset through
61
+ - For repeatable deliverables, honor a `template` @mention as `templateId` or
62
+ call `list-templates` when choosing one. Pass the template through
63
63
  `generate-image`, `generate-image-batch`, `refine-image`, or
64
64
  `rerun-generation-run`.
65
65
  - For designer handoff, preserve `sessionId` and call
@@ -77,40 +77,40 @@ evidence, screenshots, or exact logos.
77
77
  `generate-image-batch` / `refine-image`. The design team uses the audit log
78
78
  to review quality by app, library, model, prompt, and lineage.
79
79
 
80
- ## Composer Mentions And Tagged Presets
80
+ ## Composer Mentions And Tagged Templates
81
81
 
82
82
  - Composer `@` mentions are the source of generation inputs. Map `brand-kit`
83
- references to `libraryId`, `preset` references to `presetId`, and `media-type`
83
+ references to `libraryId`, `template` references to `templateId`, and `media-type`
84
84
  references to choosing image (`generate-image` / `generate-image-batch`) or
85
85
  video (`generate-video`) generation.
86
86
  - The current library view auto-tags its brand kit as a visible removable chip,
87
- and the generation preset editor auto-tags both its brand kit and preset.
87
+ and the template editor auto-tags an associated template with its brand kit.
88
88
  - The image model is the only remaining composer-side default; the image-model
89
89
  picker writes `imageGenerationModel`, which image generation actions may use
90
90
  when `model` is omitted.
91
- - When a `preset` is tagged, the server embeds that preset's aesthetics and
91
+ - When a `template` is tagged, the server embeds that template's aesthetics and
92
92
  creative philosophy (brand style brief, prompt template, text/logo policy,
93
- output format) into your message inside a `<tagged-generation-presets>` block.
93
+ output format) into your message inside a `<tagged-templates>` block.
94
94
  Study and internalize that brief before you generate — let it drive
95
- composition, mood, lighting, and subject — then pass the `presetId` to
95
+ composition, mood, lighting, and subject — then pass the `templateId` to
96
96
  `generate-image` / `generate-image-batch` so the saved format/model/tier/logo
97
97
  apply automatically. Do not restate those as ad-hoc args.
98
98
 
99
- ## Preset-first Generation
99
+ ## Template-first Generation
100
100
 
101
- - Image requests without a tagged preset are preset-first: the user may not know
102
- presets exist. Compare the request against each preset's title, description,
101
+ - Image requests without a tagged template are template-first: the user may not know
102
+ templates exist. Compare the request against each template's title, description,
103
103
  and category, and if one matches the use case (e.g. "livestream poster" -> a
104
- Livestream Announcement preset), generate with its `presetId` instead of
105
- ad-hoc settings. Only generate presetless when nothing plausibly matches.
104
+ Livestream Announcement template), generate with its `templateId` instead of
105
+ ad-hoc settings. Only generate without a template when nothing plausibly matches.
106
106
  - Before any ad-hoc generation for a brand kit, call
107
- `list-generation-presets` and scan titles/descriptions/categories for a
108
- use-case match. A preset encodes the designer's format, model, layout, and
107
+ `list-templates` and scan titles/descriptions/categories for a use-case match.
108
+ A template encodes the designer's format, model, layout, and
109
109
  reference board; using it is always better than improvising.
110
- - If one preset clearly matches: use its `presetId`; do not restate its saved
110
+ - If one template clearly matches: use its `templateId`; do not restate its saved
111
111
  aspect ratio/size/model/tier. If several plausibly match: pick the best and
112
112
  state which one you used; do not ask the user to choose.
113
- - Match named people/products/backdrops in the request to the preset's
113
+ - Match named people/products/backdrops in the request to the template's
114
114
  reference board entry labels in `settings.presetReferences`. Fill required
115
115
  variable entries via `presetReferenceFills`: search the library for assets of
116
116
  those people first; ask the user for photos only when none exist. Never skip a
@@ -122,8 +122,9 @@ evidence, screenshots, or exact logos.
122
122
  optional `textPlacement` to `generate-image` or each `generate-image-batch`
123
123
  slot. Keep the general `prompt` for creative direction; the structured text
124
124
  fields are what allow the pipeline to render copy instead of suppressing it.
125
- - If nothing matches: generate ad-hoc, say that no preset fit, and mention a
126
- preset could be created for this recurring use case.
125
+ - If nothing matches: generate ad-hoc, say that no template fit, and mention a
126
+ template could be created for this recurring use case. The deprecated
127
+ `*-generation-preset` actions remain aliases for existing agent threads.
127
128
 
128
129
  ## Prompting
129
130
 
@@ -131,13 +132,13 @@ evidence, screenshots, or exact logos.
131
132
  - Let the server choose references unless the user named exact assets. Automatic
132
133
  generation uses up to 6 relevant current references, seeded by canonical
133
134
  style anchors; explicit `referenceAssetIds` are preserved.
134
- - Preset reference boards live on tagged presets as named entries such as a
135
+ - Template reference boards live on tagged templates as named entries such as a
135
136
  usual host, product, backdrop, style sample, or per-event speaker. Fixed
136
137
  entries attach automatically. Variable entries may be replaced for a run with
137
138
  `presetReferenceFills`; each fill REPLACES that entry's pinned images rather
138
139
  than appending. Required variable entries block generation until you provide
139
140
  at least one image.
140
- - When a tagged preset brief names required variable references, collect the
141
+ - When a tagged template brief names required variable references, collect the
141
142
  needed images from the user's attachments or the library and pass
142
143
  `presetReferenceFills: [{ referenceId, assetIds }]` to `generate-image` or
143
144
  `generate-image-batch`. Board images are additive to brand style references.
@@ -113,7 +113,7 @@ filtered views.
113
113
 
114
114
  For a blog-to-brand-kit workflow: inspect the page, pick the strongest image
115
115
  URLs, import each URL into the target `libraryId`, then wire the returned
116
- `assetId`s into generation preset reference fills or call `set-canonical-logo`
116
+ `assetId`s into associated Template reference fills or call `set-canonical-logo`
117
117
  for the exact logo. Imported assets are stored as `status: "reference"` with
118
118
  `sourceUrl` provenance, so downstream generation, preset boards, and logo
119
119
  compositing can use them like uploaded reference assets.
@@ -10,24 +10,26 @@ LLMs — including Gemini Pro — degrade complex logos. They smear gradients, d
10
10
  ## How it works
11
11
 
12
12
  1. The library has a `canonicalLogoUrl` (set via `set-canonical-logo --libraryId --assetId`). The asset's role is `logo_reference`.
13
- 2. **Logo compositing is a preset option.** A generation preset carries `includeLogo` (stored in the preset `settings` and surfaced as a first-class field). When a generation resolves to a preset with `includeLogo: true`, `generate-image` composites the logo. A generate call's own `includeLogo` arg, when passed, overrides the preset for that run; when omitted, the preset's value wins.
14
- 3. **Preset skeletons generalize logo compositing.** A preset can also carry `settings.skeletonSpec`: background first, generated subject second, foreground layers last. If the skeleton already has a `foreground` layer with `source: "canonicalLogo"`, `includeLogo` is treated as a no-op for that run so the logo is not stamped twice. If the skeleton does not include the logo and `includeLogo` is true, the existing canonical-logo layer is appended at the default upper-right position during compositing.
13
+ 2. **Logo compositing is an associated-template option.** A Template carries `includeLogo` (stored in its `settings` and surfaced as a first-class field). Global templates cannot enable it because a canonical logo belongs to a brand kit. When a generation resolves to an associated template with `includeLogo: true`, `generate-image` composites the logo. A generate call's own `includeLogo` arg, when passed, overrides the template for that run; when omitted, the template's value wins.
14
+ 3. **Template skeletons generalize logo compositing.** An associated template can carry `settings.skeletonSpec`: background first, generated subject second, foreground layers last. If the skeleton already has a `foreground` layer with `source: "canonicalLogo"`, `includeLogo` is treated as a no-op for that run so the logo is not stamped twice. If the skeleton does not include the logo and `includeLogo` is true, the existing canonical-logo layer is appended at the default upper-right position during compositing.
15
15
  4. When logo compositing is on, the prompt envelope adds:
16
16
  > Leave a clean uncluttered area in the upper-right for the real brand logo; do not draw or approximate the logo yourself.
17
17
  5. Gemini returns an image with empty space in that corner.
18
18
  6. `compositeLogo()` from `server/lib/image-processing.ts` (Sharp) loads the canonical logo PNG / SVG, resizes it to ~16% of the image width with reasonable inset, and composites it onto the generated image. Skeleton runs use `applyPresetSkeleton()` at the same seam.
19
19
  7. Output: the image with the actual logo, pixel-perfect, vector-quality if the source is SVG.
20
20
 
21
- Set `includeLogo` via `create-generation-preset` / `update-generation-preset`.
21
+ Set `includeLogo` via `create-template` / `update-template` after associating
22
+ the template with a brand kit. The `*-generation-preset` actions are deprecated
23
+ aliases retained for existing threads.
22
24
  `generate-image` / `generate-image-batch` stamp the library's pixel-perfect
23
- canonical logo onto the result when the resolved preset has it on, and it is a
25
+ canonical logo onto the result when the resolved template has it on, and it is a
24
26
  no-op if the library has no canonical logo. The model never draws the logo
25
27
  itself.
26
28
 
27
- ## Preset skeletons
29
+ ## Template skeletons
28
30
 
29
- Preset skeletons live in `settings.skeletonSpec` on generation presets and are
30
- edited from `/brand-kits/:libraryId/presets/:presetId`. They composite a
31
+ Template skeletons live in `settings.skeletonSpec` on associated templates and
32
+ are edited from `/templates/:templateId`. They composite a
31
33
  generated subject onto an uploaded brand background image and optional
32
34
  foreground layers.
33
35
 
@@ -58,8 +60,8 @@ foreground layers.
58
60
 
59
61
  ## When to use it
60
62
 
61
- - The user turned on "Composite canonical logo" when creating a generation preset (the preset then stamps the logo on every image made with it).
62
- - The agent infers the user wants the logo for a one-off (e.g. "make a hero with our brand logo") — pass `includeLogo: true` on that single generate call to override the preset.
63
+ - The user turned on "Composite canonical logo" on an associated template (the template then stamps the logo on every image made with it).
64
+ - The agent infers the user wants the logo for a one-off (e.g. "make a hero with our brand logo") — pass `includeLogo: true` on that single generate call to override the template.
63
65
  - The image will appear in a customer-facing context where logo accuracy matters.
64
66
 
65
67
  ## When NOT to use it
@@ -12,9 +12,9 @@ Read the relevant skill in `.agents/skills/` before deeper work:
12
12
  - `creative-context` for cross-app source reuse, pinned packs, provenance, and
13
13
  context opt-out.
14
14
  - `library-management` for kits, collections, access, imports, and duplication.
15
- - `asset-generation` and `image-generation` for generation paths, presets,
15
+ - `asset-generation` and `image-generation` for generation paths, templates,
16
16
  composer mentions, reference boards, and embedded text.
17
- - `logo-composite` for canonical logo compositing and preset skeletons.
17
+ - `logo-composite` for canonical logo compositing and template skeletons.
18
18
  - `assets-navigation` for routes, tabs, chat surfaces, and `navigate` targets.
19
19
  - `agent-engines` for model and engine configuration.
20
20
  - `a2a-assets` for MCP/A2A callers, skill install paths, and host rendering.
@@ -38,12 +38,15 @@ Read the relevant skill in `.agents/skills/` before deeper work:
38
38
  - Preserve provenance and metadata for generated or imported assets.
39
39
  - Use `view-screen` when the active library, selected asset, picker, generation,
40
40
  or embed target is unclear.
41
- - Image work is preset-first. Follow the `creative-context` reuse ladder, then
42
- check `list-generation-presets` and generate with a matching `presetId`
41
+ - Image work is template-first. Follow the `creative-context` reuse ladder,
42
+ then check `list-templates` and generate with a matching `templateId`
43
43
  instead of ad hoc settings; see `image-generation`.
44
- - When a `preset` is tagged, the server embeds its brand style brief into your
45
- message inside a `<tagged-generation-presets>` block. Internalize that brief,
46
- then pass the `presetId` instead of restating its saved settings as args.
44
+ - Templates are global or associated with one brand kit. Only associated
45
+ templates can pin images, skeleton plates, or a canonical logo.
46
+ - When a `template` is tagged, the server embeds its brief inside a
47
+ `<tagged-templates>` block. Internalize it, then pass the `templateId`
48
+ instead of restating saved settings as args. `*-generation-preset` actions
49
+ are deprecated aliases for existing threads.
47
50
  - Keep inline previews and picker outputs lightweight; fetch full asset details
48
51
  through actions when needed.
49
52
  - Use framework sharing/collaboration primitives for ownable assets.
@@ -55,7 +58,8 @@ Read the relevant skill in `.agents/skills/` before deeper work:
55
58
  `{ view: "library", selection: "all" | libraryId, tab, scope, folderId, search }`,
56
59
  the embedded picker uses
57
60
  `{ view: "picker", mediaType, libraryId, query, prompt, aspectRatio }`, and the
58
- preset editor uses `{ view: "preset", libraryId, presetId }`.
61
+ template gallery uses `{ view: "templates" }`, and an editor uses
62
+ `{ view: "template", templateId }`. Legacy preset navigation still resolves.
59
63
  - `creative-context` holds
60
64
  `{ contextMode, selectedContextId, currentPackId, pinnedPackId }`. Respect
61
65
  `contextMode: "off"` without silently restoring a pack.
@@ -71,7 +75,7 @@ Uncommon actions stay discoverable through `tool-search`.
71
75
 
72
76
  | Action | Purpose |
73
77
  | --- | --- |
74
- | `navigate` | Move the UI to a picker, library, generation, asset, preset, or settings surface |
78
+ | `navigate` | Move the UI to a picker, library, template, generation, asset, or settings surface |
75
79
  | `view-screen` | Read current navigation, selection, and visible ids |
76
80
  | `list-libraries` / `match-library` | Find or disambiguate a brand kit |
77
81
  | `duplicate-library` | Make a private copy of a Brand Kit |
@@ -79,8 +83,9 @@ Uncommon actions stay discoverable through `tool-search`.
79
83
  | `import-asset-from-url` | Ingest external brand or blog imagery as a reference asset |
80
84
  | `import-style-from-url` | Render a website and merge its design.md-style visual language into a library or collection |
81
85
  | `set-canonical-logo` | Pin the kit's pixel-perfect logo |
82
- | `list-generation-presets` | List repeatable output formats before generating |
83
- | `create-generation-preset` / `update-generation-preset` | Author preset format, references, `includeLogo`, skeleton |
86
+ | `list-templates` / `get-template` | Find accessible reusable generation recipes |
87
+ | `create-template` / `update-template` | Author a global or brand-kit template |
88
+ | `associate-template` / `duplicate-template` | Move a template's scope or copy it into a kit |
84
89
  | `generate-image` / `generate-image-batch` | Generate image candidates (synchronous) |
85
90
  | `generate-video` | Generate video, then poll `refresh-generation-run` |
86
91
  | `refine-image` / `edit-image` / `restyle-image` | Iterate on an existing asset |
@@ -3,6 +3,12 @@
3
3
  All notable user-facing changes to Assets are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-08-26
7
+
8
+ ### Added
9
+
10
+ - Templates are now their own surface and can be used across brand kits.
11
+
6
12
  ## 2026-08-22
7
13
 
8
14
  ### Fixed
@@ -7,6 +7,7 @@ import type {
7
7
  AssetLineageSummary,
8
8
  GenerationSessionItemSummary,
9
9
  GenerationPresetSummary,
10
+ TemplateSummary,
10
11
  GenerationSessionSummary,
11
12
  ImageAssetMetadata,
12
13
  StyleBrief,
@@ -196,6 +197,20 @@ export function serializeGenerationPreset(row: any): GenerationPresetSummary {
196
197
  };
197
198
  }
198
199
 
200
+ export function serializeTemplate(row: any): TemplateSummary {
201
+ const preset = serializeGenerationPreset(row);
202
+ const libraryId = row.libraryId ?? null;
203
+ return {
204
+ ...preset,
205
+ libraryId,
206
+ scope: libraryId ? "library" : "global",
207
+ visibility: row.visibility ?? "private",
208
+ ownerEmail: row.ownerEmail,
209
+ accessRole: typeof row.accessRole === "string" ? row.accessRole : undefined,
210
+ libraryTitle: row.libraryTitle ?? null,
211
+ };
212
+ }
213
+
199
214
  export function serializeGenerationSession(row: any): GenerationSessionSummary {
200
215
  const items = Array.isArray(row.items)
201
216
  ? (row.items as GenerationSessionItemSummary[])
@@ -0,0 +1,71 @@
1
+ import {
2
+ accessFilter,
3
+ assertAccess,
4
+ resolveAccess,
5
+ type ShareRole,
6
+ } from "@agent-native/core/sharing";
7
+ import { eq, inArray, or } from "drizzle-orm";
8
+
9
+ import { getDb, schema } from "../server/db/index.js";
10
+
11
+ const roleRank: Record<ShareRole | "owner", number> = {
12
+ viewer: 1,
13
+ commenter: 2,
14
+ editor: 3,
15
+ admin: 4,
16
+ owner: 5,
17
+ };
18
+
19
+ export async function resolveTemplateAccess(
20
+ id: string,
21
+ minRole: ShareRole | "owner" = "viewer",
22
+ ) {
23
+ // guard:allow-unscoped — this helper combines the template ACL with the
24
+ // inherited Brand Kit ACL before exposing the row to its callers.
25
+ const [template] = await getDb()
26
+ .select()
27
+ .from(schema.assetTemplates)
28
+ .where(eq(schema.assetTemplates.id, id))
29
+ .limit(1);
30
+ if (!template) throw new Error("Template not found or not accessible.");
31
+ const ownAccess = await resolveAccess("asset-template", id);
32
+ const libraryAccess = template.libraryId
33
+ ? await resolveAccess("asset-library", template.libraryId)
34
+ : null;
35
+ const access =
36
+ libraryAccess &&
37
+ (!ownAccess || roleRank[libraryAccess.role] > roleRank[ownAccess.role])
38
+ ? libraryAccess
39
+ : ownAccess;
40
+ if (!access) throw new Error("Template not found or not accessible.");
41
+ if (roleRank[access.role] < roleRank[minRole]) {
42
+ throw new Error(`Template requires ${minRole} access.`);
43
+ }
44
+ return { ...access, resource: template };
45
+ }
46
+
47
+ export async function assertTemplateTargetLibraryAccess(
48
+ libraryId: string | null | undefined,
49
+ ) {
50
+ if (libraryId) await assertAccess("asset-library", libraryId, "editor");
51
+ }
52
+
53
+ export async function accessibleTemplateFilter() {
54
+ const libraries = await getDb()
55
+ .select({ id: schema.assetLibraries.id })
56
+ .from(schema.assetLibraries)
57
+ .where(accessFilter(schema.assetLibraries, schema.assetLibraryShares));
58
+ const templateAccess = accessFilter(
59
+ schema.assetTemplates,
60
+ schema.assetTemplateShares,
61
+ );
62
+ return libraries.length
63
+ ? or(
64
+ templateAccess,
65
+ inArray(
66
+ schema.assetTemplates.libraryId,
67
+ libraries.map((library) => library.id),
68
+ ),
69
+ )
70
+ : templateAccess;
71
+ }
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ ASPECT_RATIOS,
5
+ GENERATION_PRESET_REFERENCE_POLICIES,
6
+ IMAGE_CATEGORIES,
7
+ IMAGE_MODELS,
8
+ IMAGE_SIZES,
9
+ } from "../shared/api.js";
10
+ import { generationPresetSettingsSchema } from "./_generation-preset-settings.js";
11
+
12
+ export const templateFieldsSchema = z.object({
13
+ libraryId: z.string().nullable().optional(),
14
+ collectionId: z.string().nullable().optional(),
15
+ title: z.string().min(1).optional(),
16
+ description: z.string().nullable().optional(),
17
+ category: z.enum(IMAGE_CATEGORIES).optional(),
18
+ promptTemplate: z.string().nullable().optional(),
19
+ aspectRatio: z.enum(ASPECT_RATIOS).optional(),
20
+ imageSize: z.enum(IMAGE_SIZES).optional(),
21
+ model: z.enum(IMAGE_MODELS).optional(),
22
+ textPolicy: z.string().optional(),
23
+ referencePolicy: z.enum(GENERATION_PRESET_REFERENCE_POLICIES).optional(),
24
+ includeLogo: z.coerce.boolean().optional(),
25
+ settings: generationPresetSettingsSchema.optional(),
26
+ sortOrder: z.coerce.number().optional(),
27
+ });
28
+
29
+ export function templateHasPins(settings: Record<string, unknown>) {
30
+ const refs = Array.isArray(settings.presetReferences)
31
+ ? settings.presetReferences
32
+ : [];
33
+ const pinned = refs.flatMap((reference) => {
34
+ if (!reference || typeof reference !== "object") return [];
35
+ const entry = reference as {
36
+ id?: unknown;
37
+ label?: unknown;
38
+ assetIds?: unknown;
39
+ };
40
+ if (!Array.isArray(entry.assetIds) || !entry.assetIds.length) return [];
41
+ const name =
42
+ typeof entry.label === "string" && entry.label.trim()
43
+ ? entry.label.trim()
44
+ : typeof entry.id === "string" && entry.id
45
+ ? entry.id
46
+ : "unnamed reference";
47
+ return [`reference \"${name}\"`];
48
+ });
49
+ const skeleton = settings.skeletonSpec ? ["skeletonSpec"] : [];
50
+ return [...pinned, ...skeleton];
51
+ }
@@ -0,0 +1,39 @@
1
+ import { defineAction } from "@agent-native/core/action";
2
+ import { eq } from "drizzle-orm";
3
+ import { z } from "zod";
4
+
5
+ import { getDb, schema } from "../server/db/index.js";
6
+ import { nowIso, parseJson } from "../server/lib/json.js";
7
+ import { serializeTemplate } from "./_helpers.js";
8
+ import {
9
+ assertTemplateTargetLibraryAccess,
10
+ resolveTemplateAccess,
11
+ } from "./_template-access.js";
12
+ import { templateHasPins } from "./_template-input.js";
13
+
14
+ export default defineAction({
15
+ description: "Move an asset template between global scope and one Brand Kit.",
16
+ schema: z.object({ id: z.string(), libraryId: z.string().nullable() }),
17
+ run: async ({ id, libraryId }) => {
18
+ const template = (await resolveTemplateAccess(id, "editor")).resource;
19
+ await assertTemplateTargetLibraryAccess(libraryId);
20
+ const pins = templateHasPins(
21
+ parseJson<Record<string, unknown>>(template.settings, {}),
22
+ );
23
+ if (libraryId !== template.libraryId && pins.length) {
24
+ throw new Error(
25
+ `Clear pinned template settings before changing Brand Kits: ${pins.join(", ")}.`,
26
+ );
27
+ }
28
+ const updates = {
29
+ libraryId,
30
+ ...(libraryId !== template.libraryId ? { collectionId: null } : {}),
31
+ updatedAt: nowIso(),
32
+ };
33
+ await getDb()
34
+ .update(schema.assetTemplates)
35
+ .set(updates)
36
+ .where(eq(schema.assetTemplates.id, id));
37
+ return serializeTemplate({ ...template, ...updates });
38
+ },
39
+ });