@agent-native/core 0.120.1 → 0.120.2

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 (170) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +9 -0
  3. package/corpus/core/docs/content/extensions.mdx +23 -4
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/agent/production-agent.ts +4 -0
  6. package/corpus/core/src/agent/run-manager.ts +36 -10
  7. package/corpus/core/src/agent/types.ts +2 -0
  8. package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +16 -3
  9. package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  10. package/corpus/core/src/client/settings/SettingsPanel.tsx +10 -0
  11. package/corpus/core/src/deploy/build.ts +3 -0
  12. package/corpus/core/src/server/analytics.ts +154 -25
  13. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  14. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  15. package/corpus/core/src/templates/chat/netlify.toml +1 -0
  16. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  17. package/corpus/core/src/vite/client.ts +6 -0
  18. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +27 -43
  19. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -8
  20. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +2 -2
  21. package/corpus/templates/analytics/AGENTS.md +20 -8
  22. package/corpus/templates/analytics/actions/get-explorer-dashboard.ts +3 -0
  23. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +140 -46
  24. package/corpus/templates/analytics/actions/migrate-analytics-artifacts.ts +48 -0
  25. package/corpus/templates/analytics/actions/save-analysis.ts +2 -3
  26. package/corpus/templates/analytics/actions/view-screen.ts +1 -1
  27. package/corpus/templates/analytics/app/components/dashboard/DashboardMetadata.tsx +77 -0
  28. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +7 -1
  29. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
  30. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +103 -502
  31. package/corpus/templates/analytics/app/global.css +30 -0
  32. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -2
  33. package/corpus/templates/analytics/app/i18n-data.ts +80 -0
  34. package/corpus/templates/analytics/app/pages/Agents.tsx +49 -2
  35. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +54 -11
  36. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -53
  37. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +23 -25
  38. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
  39. package/corpus/templates/analytics/app/routes/analyses._index.tsx +3 -2
  40. package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
  41. package/corpus/templates/analytics/changelog/2026-07-23-analytics-now-groups-saved-analyses-and-embedded-extensions-.md +6 -0
  42. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-menus-show-who-created-and-last-updated-each-dashb.md +6 -0
  43. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-usage-now-loads-reliably-for-organizations-with-ma.md +6 -0
  44. package/corpus/templates/analytics/changelog/2026-07-23-long-dashboard-building-requests-now-continue-without-stoppi.md +6 -0
  45. package/corpus/templates/analytics/netlify.toml +4 -0
  46. package/corpus/templates/analytics/server/db/schema.ts +4 -0
  47. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -1
  48. package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +1 -0
  49. package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +1062 -0
  50. package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -52
  51. package/corpus/templates/analytics/server/plugins/core-routes.ts +1 -1
  52. package/corpus/templates/analytics/server/plugins/db.ts +10 -0
  53. package/corpus/templates/assets/actions/generate-image-batch.ts +36 -1
  54. package/corpus/templates/assets/actions/generate-image.ts +28 -1
  55. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +46 -8
  56. package/corpus/templates/assets/app/routes/extensions._index.tsx +2 -2
  57. package/corpus/templates/assets/changelog/2026-07-23-assets-image-generation-now-recovers-after-a-completed-tool-.md +6 -0
  58. package/corpus/templates/assets/netlify.toml +1 -0
  59. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -8
  60. package/corpus/templates/brain/app/routes/extensions._index.tsx +2 -2
  61. package/corpus/templates/brain/netlify.toml +1 -0
  62. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +43 -5
  63. package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +2 -16
  64. package/corpus/templates/calendar/netlify.toml +1 -0
  65. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  66. package/corpus/templates/chat/app/routes/extensions._index.tsx +2 -2
  67. package/corpus/templates/chat/netlify.toml +1 -0
  68. package/corpus/templates/clips/app/components/library/library-layout.tsx +52 -6
  69. package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +2 -16
  70. package/corpus/templates/clips/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  71. package/corpus/templates/clips/changelog/2026-07-23-meeting-recording-meters-and-dismissed-prompts.md +6 -0
  72. package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +1 -1
  73. package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +2 -0
  74. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +1 -3
  75. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +86 -0
  76. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +24 -0
  77. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +5 -69
  78. package/corpus/templates/clips/desktop/src/styles.css +35 -3
  79. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +13 -44
  80. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +119 -17
  81. package/corpus/templates/clips/netlify.toml +1 -0
  82. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -7
  83. package/corpus/templates/content/app/routes/_app.extensions._index.tsx +2 -2
  84. package/corpus/templates/content/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  85. package/corpus/templates/content/netlify.toml +1 -0
  86. package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -17
  87. package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
  88. package/corpus/templates/design/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  89. package/corpus/templates/design/netlify.toml +1 -0
  90. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -1
  91. package/corpus/templates/dispatch/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  92. package/corpus/templates/dispatch/netlify.toml +1 -0
  93. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +41 -45
  94. package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +2 -2
  95. package/corpus/templates/forms/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  96. package/corpus/templates/forms/netlify.toml +1 -0
  97. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +36 -5
  98. package/corpus/templates/macros/app/routes/extensions._index.tsx +2 -2
  99. package/corpus/templates/macros/netlify.toml +1 -0
  100. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -9
  101. package/corpus/templates/mail/app/routes/extensions._index.tsx +2 -2
  102. package/corpus/templates/mail/netlify.toml +1 -0
  103. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +38 -5
  104. package/corpus/templates/plan/app/routes/extensions._index.tsx +2 -2
  105. package/corpus/templates/plan/netlify.toml +1 -0
  106. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +47 -4
  107. package/corpus/templates/slides/app/routes/extensions._index.tsx +2 -2
  108. package/corpus/templates/slides/netlify.toml +1 -0
  109. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +37 -6
  110. package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -2
  111. package/corpus/templates/tasks/app/routes/settings.tsx +31 -0
  112. package/corpus/templates/tasks/netlify.toml +1 -0
  113. package/dist/agent/production-agent.d.ts.map +1 -1
  114. package/dist/agent/production-agent.js +4 -0
  115. package/dist/agent/production-agent.js.map +1 -1
  116. package/dist/agent/run-manager.d.ts +9 -0
  117. package/dist/agent/run-manager.d.ts.map +1 -1
  118. package/dist/agent/run-manager.js +25 -10
  119. package/dist/agent/run-manager.js.map +1 -1
  120. package/dist/agent/types.d.ts +2 -2
  121. package/dist/agent/types.d.ts.map +1 -1
  122. package/dist/agent/types.js.map +1 -1
  123. package/dist/client/extensions/ExtensionsListPage.d.ts +5 -1
  124. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  125. package/dist/client/extensions/ExtensionsListPage.js +5 -3
  126. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  127. package/dist/client/settings/ExtensionsSettingsContent.d.ts +2 -0
  128. package/dist/client/settings/ExtensionsSettingsContent.d.ts.map +1 -0
  129. package/dist/client/settings/ExtensionsSettingsContent.js +10 -0
  130. package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -0
  131. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  132. package/dist/client/settings/SettingsPanel.js +10 -1
  133. package/dist/client/settings/SettingsPanel.js.map +1 -1
  134. package/dist/collab/awareness.d.ts +2 -2
  135. package/dist/collab/awareness.d.ts.map +1 -1
  136. package/dist/deploy/build.js +1 -0
  137. package/dist/deploy/build.js.map +1 -1
  138. package/dist/observability/routes.d.ts +3 -3
  139. package/dist/progress/routes.d.ts +1 -1
  140. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  141. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  142. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  143. package/dist/server/analytics.d.ts +9 -4
  144. package/dist/server/analytics.d.ts.map +1 -1
  145. package/dist/server/analytics.js +111 -22
  146. package/dist/server/analytics.js.map +1 -1
  147. package/dist/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  148. package/dist/templates/chat/app/routes/extensions._index.tsx +2 -2
  149. package/dist/templates/chat/netlify.toml +1 -0
  150. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  151. package/dist/vite/client.d.ts.map +1 -1
  152. package/dist/vite/client.js +2 -0
  153. package/dist/vite/client.js.map +1 -1
  154. package/docs/content/extensions.mdx +23 -4
  155. package/package.json +1 -1
  156. package/src/agent/production-agent.ts +4 -0
  157. package/src/agent/run-manager.ts +36 -10
  158. package/src/agent/types.ts +2 -0
  159. package/src/client/extensions/ExtensionsListPage.tsx +16 -3
  160. package/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  161. package/src/client/settings/SettingsPanel.tsx +10 -0
  162. package/src/deploy/build.ts +3 -0
  163. package/src/server/analytics.ts +154 -25
  164. package/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  165. package/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  166. package/src/templates/chat/netlify.toml +1 -0
  167. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  168. package/src/vite/client.ts +6 -0
  169. package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +0 -165
  170. package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +0 -175
@@ -6,6 +6,7 @@
6
6
 
7
7
  use serde::{Deserialize, Serialize};
8
8
  use serde_json::Value;
9
+ use std::collections::HashMap;
9
10
  use std::sync::atomic::{AtomicBool, Ordering};
10
11
  use std::sync::Mutex;
11
12
  use std::time::Duration;
@@ -28,9 +29,16 @@ const NOTIFICATION_W_LOGICAL: u32 = 504;
28
29
  const NOTIFICATION_H_LOGICAL: u32 = 120;
29
30
  const NOTIFICATION_TOP_MARGIN_LOGICAL: u32 = 44;
30
31
  const NOTIFICATION_RIGHT_MARGIN_LOGICAL: u32 = 0;
32
+ const DISMISSAL_TOMBSTONE_SECS: i64 = 30 * 60;
31
33
 
32
34
  #[derive(Default)]
33
- pub struct MeetingNotificationState(pub Mutex<Option<Value>>);
35
+ pub struct MeetingNotificationState(Mutex<MeetingNotificationStateInner>);
36
+
37
+ #[derive(Default)]
38
+ struct MeetingNotificationStateInner {
39
+ pending: Option<Value>,
40
+ dismissed_until: HashMap<String, i64>,
41
+ }
34
42
 
35
43
  #[allow(dead_code)]
36
44
  #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -176,22 +184,54 @@ pub fn show_meeting_notification_window(app: &AppHandle) -> Result<(), String> {
176
184
  Ok(())
177
185
  }
178
186
 
179
- fn store_pending_meeting_notification(app: &AppHandle, payload: &Value) {
180
- if let Some(state) = app.try_state::<MeetingNotificationState>() {
181
- if let Ok(mut pending) = state.0.lock() {
182
- *pending = Some(payload.clone());
183
- }
184
- }
185
- }
186
-
187
187
  #[tauri::command]
188
188
  pub fn take_pending_meeting_notification(app: AppHandle) -> Result<Option<Value>, String> {
189
189
  let state = app.state::<MeetingNotificationState>();
190
- let mut pending = state
190
+ let mut state = state
191
191
  .0
192
192
  .lock()
193
193
  .map_err(|_| "meeting notification state lock poisoned".to_string())?;
194
- Ok(pending.take())
194
+ let now = chrono::Utc::now().timestamp();
195
+ state.dismissed_until.retain(|_, until| *until > now);
196
+ if state.pending.as_ref().is_some_and(|payload| {
197
+ state
198
+ .dismissed_until
199
+ .contains_key(&notification_key(payload))
200
+ }) {
201
+ state.pending = None;
202
+ }
203
+ Ok(state.pending.take())
204
+ }
205
+
206
+ fn notification_key(payload: &Value) -> String {
207
+ format!(
208
+ "{}|{}|{}",
209
+ payload
210
+ .get("type")
211
+ .and_then(Value::as_str)
212
+ .unwrap_or("calendar"),
213
+ payload
214
+ .get("meetingId")
215
+ .and_then(Value::as_str)
216
+ .unwrap_or_default(),
217
+ payload
218
+ .get("scheduledStart")
219
+ .and_then(Value::as_str)
220
+ .unwrap_or_default(),
221
+ )
222
+ }
223
+
224
+ fn notification_key_from_parts(
225
+ notification_type: &str,
226
+ meeting_id: &str,
227
+ scheduled_start: Option<&str>,
228
+ ) -> String {
229
+ format!(
230
+ "{}|{}|{}",
231
+ notification_type,
232
+ meeting_id,
233
+ scheduled_start.unwrap_or_default()
234
+ )
195
235
  }
196
236
 
197
237
  fn clear_pending_notification(pending: &mut Option<Value>, meeting_id: &str) -> bool {
@@ -211,19 +251,38 @@ pub fn dismiss_meeting_notification(
211
251
  app: AppHandle,
212
252
  meeting_id: String,
213
253
  notification_type: String,
254
+ join_url: Option<String>,
214
255
  platform: Option<String>,
215
256
  scheduled_start: Option<String>,
216
257
  scheduled_end: Option<String>,
217
258
  ) -> Result<(), String> {
218
259
  let state = app.state::<MeetingNotificationState>();
219
- let mut pending = state
260
+ let mut state = state
220
261
  .0
221
262
  .lock()
222
263
  .map_err(|_| "meeting notification state lock poisoned".to_string())?;
223
- clear_pending_notification(&mut pending, &meeting_id);
224
- drop(pending);
264
+ let now = chrono::Utc::now().timestamp();
265
+ state.dismissed_until.retain(|_, until| *until > now);
266
+ state.dismissed_until.insert(
267
+ notification_key_from_parts(&notification_type, &meeting_id, scheduled_start.as_deref()),
268
+ now + DISMISSAL_TOMBSTONE_SECS,
269
+ );
270
+ clear_pending_notification(&mut state.pending, &meeting_id);
271
+ drop(state);
225
272
 
226
- if let Some(platform) = platform.as_deref() {
273
+ let suppression_platform = platform.as_deref().or_else(|| {
274
+ join_url.as_deref().and_then(|url| {
275
+ let url = url.to_ascii_lowercase();
276
+ if url.contains("zoom") {
277
+ Some("zoom")
278
+ } else if url.contains("teams.microsoft") || url.contains("teams") {
279
+ Some("teams")
280
+ } else {
281
+ None
282
+ }
283
+ })
284
+ });
285
+ if let Some(platform) = suppression_platform {
227
286
  crate::adhoc_meetings_watcher::refresh_dismissal_suppression(&app, platform)?;
228
287
  }
229
288
 
@@ -312,14 +371,41 @@ pub async fn notify_meeting_starting(
312
371
  "type": kind,
313
372
  "title": title,
314
373
  "subtitle": body,
315
- "meetingId": meeting_id,
374
+ "meetingId": meeting_id.clone(),
316
375
  "joinUrl": join_url,
317
376
  "platform": platform,
318
377
  "scheduledStart": scheduled_start,
319
378
  "scheduledEnd": scheduled_end,
320
379
  "autoStart": auto_start.unwrap_or(false),
321
380
  });
322
- store_pending_meeting_notification(&app, &payload);
381
+ let state = app.state::<MeetingNotificationState>();
382
+ let should_show = {
383
+ let mut state = state
384
+ .0
385
+ .lock()
386
+ .map_err(|_| "meeting notification state lock poisoned".to_string())?;
387
+ let now = chrono::Utc::now().timestamp();
388
+ state.dismissed_until.retain(|_, until| *until > now);
389
+ if state
390
+ .dismissed_until
391
+ .get(&notification_key(&payload))
392
+ .copied()
393
+ .unwrap_or_default()
394
+ > now
395
+ {
396
+ false
397
+ } else {
398
+ state.pending = Some(payload.clone());
399
+ true
400
+ }
401
+ };
402
+ if !should_show {
403
+ dlog!(
404
+ "[clips-tray] skipped dismissed meeting notification id={}",
405
+ meeting_id
406
+ );
407
+ return Ok(());
408
+ }
323
409
  let _ = app.emit("meetings:show-notification", payload.clone());
324
410
 
325
411
  // Ensure the overlay window exists / is visible for cold starts.
@@ -346,4 +432,20 @@ mod tests {
346
432
  assert!(clear_pending_notification(&mut pending, "meeting-1"));
347
433
  assert!(pending.is_none());
348
434
  }
435
+
436
+ #[test]
437
+ fn dismissal_key_changes_when_a_meeting_is_rescheduled() {
438
+ let first = serde_json::json!({
439
+ "type": "calendar",
440
+ "meetingId": "meeting-1",
441
+ "scheduledStart": "2026-07-23T17:00:00Z"
442
+ });
443
+ let moved = serde_json::json!({
444
+ "type": "calendar",
445
+ "meetingId": "meeting-1",
446
+ "scheduledStart": "2026-07-23T18:00:00Z"
447
+ });
448
+
449
+ assert_ne!(notification_key(&first), notification_key(&moved));
450
+ }
349
451
  }
@@ -6,6 +6,7 @@ functions = "templates/clips/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
11
12
  AUTO_CREATE_DEFAULT_ORG = "1"
@@ -1,10 +1,7 @@
1
1
  import { useCodeMode } from "@agent-native/core/client/agent-chat";
2
2
  import { appPath } from "@agent-native/core/client/api-path";
3
3
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
4
- import {
5
- ExtensionSlot,
6
- ExtensionsSidebarSection,
7
- } from "@agent-native/core/client/extensions";
4
+ import { ExtensionSlot } from "@agent-native/core/client/extensions";
8
5
  import {
9
6
  setClientAppState,
10
7
  useActionMutation,
@@ -1293,7 +1290,7 @@ export function DocumentSidebar({
1293
1290
  >
1294
1291
  <IconHierarchy2 size={15} className="shrink-0" />
1295
1292
  <span className="min-w-0 flex-1 truncate text-start">
1296
- {t("navigation.agent")}
1293
+ {t("settings.agentTitle")}
1297
1294
  </span>
1298
1295
  </Link>
1299
1296
  );
@@ -1861,7 +1858,7 @@ export function DocumentSidebar({
1861
1858
  <IconHierarchy2 size={16} />
1862
1859
  </Link>
1863
1860
  </TooltipTrigger>
1864
- <TooltipContent>{t("navigation.agent")}</TooltipContent>
1861
+ <TooltipContent>{t("settings.agentTitle")}</TooltipContent>
1865
1862
  </Tooltip>
1866
1863
  <Tooltip>
1867
1864
  <TooltipTrigger asChild>
@@ -2092,7 +2089,6 @@ export function DocumentSidebar({
2092
2089
  className="px-2 py-2"
2093
2090
  toolClassName="overflow-hidden rounded-md"
2094
2091
  />
2095
- <ExtensionsSidebarSection />
2096
2092
  </div>
2097
2093
 
2098
2094
  <div className="shrink-0 px-3 py-2">
@@ -1,5 +1,5 @@
1
- import { ExtensionsListPage } from "@agent-native/core/client/extensions";
1
+ import { Navigate } from "react-router";
2
2
 
3
3
  export default function ExtensionsRoute() {
4
- return <ExtensionsListPage />;
4
+ return <Navigate to="/settings#extensions" replace />;
5
5
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Agent settings are clearly labeled Manage agent in the sidebar.
@@ -6,6 +6,7 @@ functions = "templates/content/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
11
12
  AGENT_RUN_SOFT_TIMEOUT_MS = "55000"
@@ -1,6 +1,5 @@
1
1
  import { appPath } from "@agent-native/core/client/api-path";
2
2
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
3
- import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
4
3
  import { useT } from "@agent-native/core/client/i18n";
5
4
  import { OrgSwitcher } from "@agent-native/core/client/org";
6
5
  import { FeedbackButton } from "@agent-native/core/client/ui";
@@ -32,7 +31,10 @@ const navItems = [
32
31
  labelKey: "navigation.designSystems",
33
32
  href: "/design-systems",
34
33
  },
35
- { icon: IconHierarchy2, labelKey: "navigation.agent", href: "/agent" },
34
+ ];
35
+
36
+ const bottomNavItems = [
37
+ { icon: IconHierarchy2, labelKey: "settings.agentTitle", href: "/agent" },
36
38
  { icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
37
39
  ];
38
40
 
@@ -156,25 +158,61 @@ export function Sidebar() {
156
158
  })}
157
159
  </nav>
158
160
 
159
- {!collapsed && (
160
- <div className="mt-auto shrink-0">
161
- <div className="px-2 py-1">
162
- <ExtensionsSidebarSection />
163
- </div>
161
+ <div className="mt-auto shrink-0">
162
+ <nav
163
+ className={cn(
164
+ "grid gap-1",
165
+ collapsed ? "justify-items-center px-1.5 py-1" : "px-2 py-1",
166
+ )}
167
+ >
168
+ {bottomNavItems.map((item) => {
169
+ const Icon = item.icon;
170
+ const isActive = location.pathname.startsWith(item.href);
171
+ const link = (
172
+ <Link
173
+ to={item.href}
174
+ className={cn(
175
+ "flex items-center rounded-lg text-sm",
176
+ collapsed ? "h-9 w-9 justify-center" : "gap-3 px-3 py-2",
177
+ isActive
178
+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
179
+ : "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
180
+ )}
181
+ aria-label={collapsed ? t(item.labelKey) : undefined}
182
+ >
183
+ <Icon className="h-4 w-4 shrink-0" />
184
+ {!collapsed && t(item.labelKey)}
185
+ </Link>
186
+ );
187
+ return collapsed ? (
188
+ <Tooltip key={item.href} delayDuration={0}>
189
+ <TooltipTrigger asChild>{link}</TooltipTrigger>
190
+ <TooltipContent side="right">
191
+ {t(item.labelKey)}
192
+ </TooltipContent>
193
+ </Tooltip>
194
+ ) : (
195
+ <div key={item.href}>{link}</div>
196
+ );
197
+ })}
198
+ </nav>
164
199
 
165
- <div className="px-3 py-2">
166
- <OrgSwitcher reserveSpace />
167
- </div>
200
+ {!collapsed && (
201
+ <div className="mt-auto shrink-0">
202
+ <div className="px-3 py-2">
203
+ <OrgSwitcher reserveSpace />
204
+ </div>
168
205
 
169
- <div className="px-3 py-2">
170
- <DevDatabaseLink />
171
- <div className="flex items-center justify-end gap-1">
172
- <FeedbackButton className="min-w-0 flex-1" />
173
- <ThemeToggle className="h-8 w-8 shrink-0" />
206
+ <div className="px-3 py-2">
207
+ <DevDatabaseLink />
208
+ <div className="flex items-center justify-end gap-1">
209
+ <FeedbackButton className="min-w-0 flex-1" />
210
+ <ThemeToggle className="h-8 w-8 shrink-0" />
211
+ </div>
174
212
  </div>
175
213
  </div>
176
- </div>
177
- )}
214
+ )}
215
+ </div>
178
216
  </div>
179
217
  </aside>
180
218
  );
@@ -1,4 +1,4 @@
1
- import { ExtensionsListPage } from "@agent-native/core/client/extensions";
1
+ import { Navigate } from "react-router";
2
2
 
3
3
  import { messagesByLocale } from "@/i18n-data";
4
4
 
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function ExtensionsRoute() {
10
- return <ExtensionsListPage />;
10
+ return <Navigate to="/settings#extensions" replace />;
11
11
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Agent settings are clearly labeled Manage agent in the sidebar.
@@ -6,6 +6,7 @@ functions = "templates/design/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
11
12
  AGENT_CHAT_DURABLE_BACKGROUND = "true"
@@ -30,7 +30,7 @@ export const dispatchExtensions = {
30
30
  {
31
31
  id: "agent",
32
32
  to: "/agent",
33
- label: "Agent",
33
+ label: "Manage agent",
34
34
  icon: IconHierarchy2,
35
35
  section: "operations",
36
36
  },
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Agent settings are clearly labeled Manage agent in the sidebar.
@@ -6,6 +6,7 @@ functions = "templates/dispatch/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
11
12
 
@@ -5,7 +5,6 @@ import {
5
5
  } from "@agent-native/core/client/agent-chat";
6
6
  import { appPath } from "@agent-native/core/client/api-path";
7
7
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
8
- import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
9
8
  import { useT } from "@agent-native/core/client/i18n";
10
9
  import { OrgSwitcher } from "@agent-native/core/client/org";
11
10
  import { FeedbackButton } from "@agent-native/core/client/ui";
@@ -277,45 +276,47 @@ export function Sidebar() {
277
276
  {newFormPopover}
278
277
  </Popover>
279
278
 
280
- <Tooltip>
281
- <TooltipTrigger asChild>
282
- <Link
283
- to="/agent"
284
- aria-label={t("navigation.agent")}
285
- className={cn(
286
- "forms-sidebar-nav-item flex size-10 items-center justify-center rounded-lg active:scale-[0.96] transition-[background-color,box-shadow,color,transform]",
287
- location.pathname.startsWith("/agent")
288
- ? "bg-accent text-accent-foreground"
289
- : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
290
- )}
291
- >
292
- <IconHierarchy2 className="h-4 w-4" />
293
- </Link>
294
- </TooltipTrigger>
295
- <TooltipContent side="right">
296
- {t("navigation.agent")}
297
- </TooltipContent>
298
- </Tooltip>
279
+ <div className="mt-auto flex flex-col items-center gap-1">
280
+ <Tooltip>
281
+ <TooltipTrigger asChild>
282
+ <Link
283
+ to="/agent"
284
+ aria-label={t("settings.agentTitle")}
285
+ className={cn(
286
+ "forms-sidebar-nav-item flex size-10 items-center justify-center rounded-lg active:scale-[0.96] transition-[background-color,box-shadow,color,transform]",
287
+ location.pathname.startsWith("/agent")
288
+ ? "bg-accent text-accent-foreground"
289
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
290
+ )}
291
+ >
292
+ <IconHierarchy2 className="h-4 w-4" />
293
+ </Link>
294
+ </TooltipTrigger>
295
+ <TooltipContent side="right">
296
+ {t("settings.agentTitle")}
297
+ </TooltipContent>
298
+ </Tooltip>
299
299
 
300
- <Tooltip>
301
- <TooltipTrigger asChild>
302
- <Link
303
- to="/settings"
304
- aria-label={t("navigation.settings")}
305
- className={cn(
306
- "forms-sidebar-nav-item flex size-10 items-center justify-center rounded-lg active:scale-[0.96] transition-[background-color,box-shadow,color,transform]",
307
- location.pathname === "/settings"
308
- ? "bg-accent text-accent-foreground"
309
- : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
310
- )}
311
- >
312
- <IconSettings className="h-4 w-4" />
313
- </Link>
314
- </TooltipTrigger>
315
- <TooltipContent side="right">
316
- {t("navigation.settings")}
317
- </TooltipContent>
318
- </Tooltip>
300
+ <Tooltip>
301
+ <TooltipTrigger asChild>
302
+ <Link
303
+ to="/settings"
304
+ aria-label={t("navigation.settings")}
305
+ className={cn(
306
+ "forms-sidebar-nav-item flex size-10 items-center justify-center rounded-lg active:scale-[0.96] transition-[background-color,box-shadow,color,transform]",
307
+ location.pathname === "/settings"
308
+ ? "bg-accent text-accent-foreground"
309
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
310
+ )}
311
+ >
312
+ <IconSettings className="h-4 w-4" />
313
+ </Link>
314
+ </TooltipTrigger>
315
+ <TooltipContent side="right">
316
+ {t("navigation.settings")}
317
+ </TooltipContent>
318
+ </Tooltip>
319
+ </div>
319
320
  </nav>
320
321
  </TooltipProvider>
321
322
  </div>
@@ -446,7 +447,7 @@ export function Sidebar() {
446
447
  )}
447
448
  >
448
449
  <IconHierarchy2 size={14} className="shrink-0" />
449
- <span>{t("navigation.agent")}</span>
450
+ <span>{t("settings.agentTitle")}</span>
450
451
  </Link>
451
452
 
452
453
  <Link
@@ -464,11 +465,6 @@ export function Sidebar() {
464
465
  </Link>
465
466
  </div>
466
467
 
467
- {/* Tools */}
468
- <div className="shrink-0 px-1.5 py-1.5">
469
- <ExtensionsSidebarSection />
470
- </div>
471
-
472
468
  {/* Footer */}
473
469
  <div className="shrink-0 space-y-2 px-3 py-2">
474
470
  <OrgSwitcher />
@@ -1,4 +1,4 @@
1
- import { ExtensionsListPage } from "@agent-native/core/client/extensions";
1
+ import { Navigate } from "react-router";
2
2
 
3
3
  import messages from "@/i18n/en-US";
4
4
 
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function ExtensionsRoute() {
10
- return <ExtensionsListPage />;
10
+ return <Navigate to="/settings#extensions" replace />;
11
11
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Agent settings are clearly labeled Manage agent in the sidebar.
@@ -6,6 +6,7 @@ functions = "templates/forms/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
11
12
 
@@ -1,7 +1,6 @@
1
1
  import { AgentSidebar } from "@agent-native/core/client/agent-chat";
2
2
  import { agentNativePath, appPath } from "@agent-native/core/client/api-path";
3
3
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
4
- import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
5
4
  import { useT } from "@agent-native/core/client/i18n";
6
5
  import { OrgSwitcher } from "@agent-native/core/client/org";
7
6
  import { FeedbackButton } from "@agent-native/core/client/ui";
@@ -39,6 +38,9 @@ import { Header } from "./Header";
39
38
  const navItems = [
40
39
  { icon: IconFlame, labelKey: "navigation.entry", href: "/" },
41
40
  { icon: IconChartBar, labelKey: "navigation.analytics", href: "/analytics" },
41
+ ];
42
+
43
+ const bottomNavItems = [
42
44
  { icon: IconHierarchy2, labelKey: "settings.agentTitle", href: "/agent" },
43
45
  { icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
44
46
  ];
@@ -287,12 +289,41 @@ function SidebarContent({
287
289
  })}
288
290
  </nav>
289
291
 
292
+ <nav className="grid shrink-0 gap-1 px-2 py-1">
293
+ {bottomNavItems.map((item) => {
294
+ const Icon = item.icon;
295
+ const label = t(item.labelKey);
296
+ const isActive = pathname.startsWith(item.href);
297
+ const link = (
298
+ <Link
299
+ key={item.href}
300
+ to={item.href}
301
+ aria-label={collapsed ? label : undefined}
302
+ className={cn(
303
+ "flex h-9 items-center rounded-lg text-sm transition-colors",
304
+ collapsed ? "justify-center px-0" : "gap-3 px-3",
305
+ isActive
306
+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
307
+ : "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
308
+ )}
309
+ >
310
+ <Icon className="h-4 w-4 shrink-0" />
311
+ {!collapsed && label}
312
+ </Link>
313
+ );
314
+ return collapsed ? (
315
+ <Tooltip key={item.href}>
316
+ <TooltipTrigger asChild>{link}</TooltipTrigger>
317
+ <TooltipContent side="right">{label}</TooltipContent>
318
+ </Tooltip>
319
+ ) : (
320
+ link
321
+ );
322
+ })}
323
+ </nav>
324
+
290
325
  {!collapsed && (
291
326
  <>
292
- <div className="px-2 py-2">
293
- <ExtensionsSidebarSection />
294
- </div>
295
-
296
327
  <div className="space-y-2 px-3 py-2">
297
328
  <DevDatabaseLink />
298
329
  <FeedbackButton />
@@ -1,4 +1,4 @@
1
- import { ExtensionsListPage } from "@agent-native/core/client/extensions";
1
+ import { Navigate } from "react-router";
2
2
 
3
3
  import messages from "@/i18n/en-US";
4
4
 
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function ExtensionsRoute() {
10
- return <ExtensionsListPage />;
10
+ return <Navigate to="/settings#extensions" replace />;
11
11
  }
@@ -6,5 +6,6 @@ functions = "templates/macros/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"