@agent-native/core 0.137.2 → 0.137.4

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 (176) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  3. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +53 -1
  4. package/corpus/templates/analytics/actions/gong-calls.ts +37 -17
  5. package/corpus/templates/analytics/app/lib/data-sources.ts +1 -1
  6. package/corpus/templates/analytics/server/lib/gong.ts +51 -2
  7. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  8. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +53 -1
  9. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  10. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +53 -1
  11. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  12. package/corpus/templates/brain/server/register-secrets.ts +1 -1
  13. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  14. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +53 -1
  15. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  16. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  17. package/corpus/templates/chat/AGENTS.md +11 -0
  18. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  19. package/corpus/templates/chat/app/root.tsx +1 -1
  20. package/corpus/templates/chat/app/routes/agent.tsx +29 -13
  21. package/corpus/templates/chat/vite.config.ts +42 -0
  22. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  23. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +53 -1
  24. package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
  25. package/corpus/templates/clips/app/components/library/library-grid.tsx +2 -6
  26. package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -6
  27. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +1 -3
  28. package/corpus/templates/clips/app/routes/bug-report.tsx +1 -8
  29. package/corpus/templates/clips/app/routes/import.tsx +1 -3
  30. package/corpus/templates/clips/changelog/2026-08-04-recording-buttons-are-now-text-only-for-a-cleaner-clips-inte.md +6 -0
  31. package/corpus/templates/clips/changelog/2026-08-04-save-settings-now-matches-the-other-clips-settings-buttons.md +6 -0
  32. package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
  33. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +53 -1
  35. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  36. package/corpus/templates/crm/app/routes/settings.tsx +2 -2
  37. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  38. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +53 -1
  39. package/corpus/templates/design/actions/import-figma-clipboard.ts +1 -1
  40. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +53 -1
  42. package/corpus/templates/dispatch/changelog/2026-08-04-dispatch-keeps-connected-chats-out-of-local-history-by-defau.md +6 -0
  43. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  44. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +53 -1
  45. package/corpus/templates/factory/README.md +1 -1
  46. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  47. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +53 -1
  48. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  49. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +53 -1
  50. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  51. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +53 -1
  52. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -2
  53. package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
  54. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  55. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +53 -1
  56. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  57. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +53 -1
  58. package/corpus/templates/slides/actions/generate-image-api.ts +15 -4
  59. package/corpus/templates/slides/actions/import-google-slides-reference.ts +83 -0
  60. package/corpus/templates/slides/actions/import-pptx.ts +134 -117
  61. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +387 -0
  62. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +78 -48
  63. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +377 -187
  64. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -1
  65. package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +20 -1
  66. package/corpus/templates/slides/app/i18n/en-US.ts +15 -0
  67. package/corpus/templates/slides/app/lib/new-deck-reference-selection.ts +22 -0
  68. package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -1
  69. package/corpus/templates/slides/app/pages/Index.tsx +172 -85
  70. package/corpus/templates/slides/server/lib/assets-image-delegation.ts +4 -2
  71. package/corpus/templates/slides/shared/api.ts +14 -1
  72. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  73. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +53 -1
  74. package/dist/chat-threads/schema.d.ts +57 -0
  75. package/dist/chat-threads/schema.js +3 -0
  76. package/dist/chat-threads/store.d.ts +26 -0
  77. package/dist/chat-threads/store.js +84 -6
  78. package/dist/client/AgentPanel.js +11 -5
  79. package/dist/client/ConnectBuilderCard.js +1 -1
  80. package/dist/client/agent-page/AgentEmptyState.d.ts +2 -1
  81. package/dist/client/agent-page/AgentEmptyState.js +6 -2
  82. package/dist/client/agent-page/AgentJobsTab.d.ts +3 -1
  83. package/dist/client/agent-page/AgentJobsTab.js +55 -44
  84. package/dist/client/agent-page/AgentTabFrame.d.ts +2 -1
  85. package/dist/client/agent-page/AgentTabFrame.js +4 -2
  86. package/dist/client/agent-page/AgentTabsPage.js +12 -8
  87. package/dist/client/agent-page/AgentWorkspaceContent.d.ts +10 -0
  88. package/dist/client/agent-page/AgentWorkspaceContent.js +110 -0
  89. package/dist/client/agent-page/AutomationDetailsDialog.js +1 -1
  90. package/dist/client/chat/run-recovery.js +3 -3
  91. package/dist/client/error-format.js +1 -1
  92. package/dist/client/integrations/IntegrationsPanel.d.ts +1 -0
  93. package/dist/client/integrations/IntegrationsPanel.js +149 -5
  94. package/dist/client/onboarding/FirstRunOnboarding.js +130 -15
  95. package/dist/client/onboarding/index.d.ts +1 -1
  96. package/dist/client/onboarding/index.js +1 -1
  97. package/dist/client/onboarding/use-onboarding.js +12 -2
  98. package/dist/client/onboarding/use-preview-mode.d.ts +4 -0
  99. package/dist/client/onboarding/use-preview-mode.js +9 -0
  100. package/dist/client/resources/BuiltinCapabilityDetail.js +2 -2
  101. package/dist/client/resources/ResourceTree.d.ts +4 -1
  102. package/dist/client/resources/ResourceTree.js +13 -8
  103. package/dist/client/resources/ResourcesPanel.js +7 -3
  104. package/dist/client/resources/mcp-integration-catalog.js +4 -4
  105. package/dist/client/resources/use-mcp-servers.js +6 -6
  106. package/dist/client/settings/AgentsSection.js +15 -16
  107. package/dist/client/settings/AutomationsSection.js +1 -1
  108. package/dist/client/settings/DemoModeSection.js +1 -1
  109. package/dist/client/settings/SettingsPanel.d.ts +3 -1
  110. package/dist/client/settings/SettingsPanel.js +284 -88
  111. package/dist/client/settings/SettingsRow.js +1 -1
  112. package/dist/client/settings/SettingsSection.d.ts +6 -4
  113. package/dist/client/settings/SettingsSection.js +6 -6
  114. package/dist/client/settings/SettingsTabsPage.js +47 -25
  115. package/dist/client/settings/VoiceTranscriptionSection.d.ts +3 -1
  116. package/dist/client/settings/VoiceTranscriptionSection.js +20 -8
  117. package/dist/client/settings/agent-settings-search.d.ts +1 -1
  118. package/dist/client/settings/agent-settings-search.js +8 -8
  119. package/dist/client/transcription/BuilderTranscriptionCta.js +2 -2
  120. package/dist/client/use-chat-threads.d.ts +9 -0
  121. package/dist/client/use-chat-threads.js +22 -6
  122. package/dist/collab/routes.d.ts +1 -1
  123. package/dist/integrations/google-docs-poller.js +9 -1
  124. package/dist/integrations/webhook-handler.js +11 -1
  125. package/dist/jobs/scheduler.d.ts +4 -1
  126. package/dist/jobs/scheduler.js +34 -9
  127. package/dist/localization/default-messages.js +40 -40
  128. package/dist/mcp-client/oauth-routes.js +1 -1
  129. package/dist/notifications/routes.d.ts +1 -1
  130. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  131. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  132. package/dist/resources/handlers.d.ts +1 -1
  133. package/dist/secrets/onboarding.js +1 -1
  134. package/dist/secrets/routes.d.ts +9 -9
  135. package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
  136. package/dist/server/agent-chat/browser-team-tools.js +1 -0
  137. package/dist/server/agent-chat-plugin.js +14 -1
  138. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  139. package/dist/server/agent-teams.d.ts +2 -0
  140. package/dist/server/agent-teams.js +2 -0
  141. package/dist/server/workspace-provider-oauth.js +1 -1
  142. package/dist/setup-connections/onboarding.js +2 -2
  143. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  144. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  145. package/dist/templates/chat/AGENTS.md +11 -0
  146. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
  147. package/dist/templates/chat/app/root.tsx +1 -1
  148. package/dist/templates/chat/app/routes/agent.tsx +29 -13
  149. package/dist/templates/chat/vite.config.ts +42 -0
  150. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  151. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
  152. package/dist/templates/default/AGENTS.md +11 -0
  153. package/dist/templates/default/vite.config.ts +42 -0
  154. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  155. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  156. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
  157. package/dist/templates/workspace-core/AGENTS.md +11 -0
  158. package/dist/templates/workspace-root/AGENTS.md +14 -0
  159. package/dist/vite/client.js +56 -0
  160. package/package.json +2 -2
  161. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  162. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  163. package/src/templates/chat/AGENTS.md +11 -0
  164. package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
  165. package/src/templates/chat/app/root.tsx +1 -1
  166. package/src/templates/chat/app/routes/agent.tsx +29 -13
  167. package/src/templates/chat/vite.config.ts +42 -0
  168. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  169. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
  170. package/src/templates/default/AGENTS.md +11 -0
  171. package/src/templates/default/vite.config.ts +42 -0
  172. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  173. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  174. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
  175. package/src/templates/workspace-core/AGENTS.md +11 -0
  176. package/src/templates/workspace-root/AGENTS.md +14 -0
@@ -77,7 +77,10 @@ passed this requirement yet.
77
77
 
78
78
  ## Aesthetic Guidelines
79
79
 
80
- - **Typography**: Use the product's existing type system first. For net-new public pages, choose characterful but readable type and keep sizing appropriate to the surface.
80
+ - **Typography**: Use the product's existing type system first. For SaaS and
81
+ operational apps, make a clear sans-serif hierarchy the default; reserve a
82
+ serif or editorial face for a deliberate content preview or brand moment,
83
+ not the whole application shell.
81
84
  - **Color and theme**: Use semantic tokens and CSS variables. Avoid one-note palettes and default purple/blue gradients unless the brand demands them.
82
85
  - **Motion**: Prefer purposeful transitions and small state changes. Use CSS transitions/keyframes unless the app already uses a motion library. Never `transition-all` — list the properties that actually change (e.g. `transition-[opacity,transform]`). Use the shared easing tokens defined in `packages/core/src/styles/agent-native.css` instead of hand-typing curves: `var(--ease-drawer)` (260ms, drawers/app chrome), `var(--ease-collapse)` (200ms, expand/collapse), `var(--ease-out-strong)` (snappy entrances) — in Tailwind, `ease-[var(--ease-collapse)]`. Enter/exit with ease-out, never `ease-in`. Overlays that zoom in must set the Radix origin var (e.g. `origin-[--radix-popover-content-transform-origin]`). Animate `transform`/`opacity`, not width/height/padding/box-shadow. Gate looping or large-movement animations with `motion-reduce:`. Command palettes and keyboard-triggered actions get no animation.
83
86
  - **Composition**: Match the workflow. Operational apps should be dense and scannable; marketing or portfolio pages can be more immersive.
@@ -115,6 +118,55 @@ passed this requirement yet.
115
118
  - Keep UI optimistic where possible: update cache and navigation immediately, then reconcile or roll back on mutation result.
116
119
  - Custom styles belong in Tailwind classes, component CSS, or the existing global CSS theme file; avoid inline styles.
117
120
 
121
+ ### Agent Surface And Page Boundaries
122
+
123
+ - Treat the domain UI and the agent as two coordinated surfaces. The domain
124
+ page should make the repeatable job fast; the agent should handle judgment,
125
+ exploration, and actions that benefit from conversation.
126
+ - Keep domain work on a named domain route such as `/automations`, `/block`, or
127
+ `/workflow`. Preserve the starter's full-page chat route (`/` or `/chat/*`)
128
+ when it exists; do not replace it with a domain form while leaving the shell
129
+ configured as if it were chat.
130
+ - Use the persistent right `AgentSidebar` for contextual AI. A button that
131
+ sends work to `sendToAgentChat` must open or focus that sidebar and leave the
132
+ user on the current domain surface. Use full-page chat for chat-first work,
133
+ not as a hidden transport for a domain button.
134
+ - Keep the left navigation domain-specific. A page called Automations,
135
+ Block time, or Create deck should not be nested under a generic Chat item;
136
+ Chat is its own destination and the right rail is the contextual assistant.
137
+ - Never use sparkle, wand, magic, robot, or similar decorative AI icons. Use a
138
+ familiar message, assistant, or neutral action icon, and let the button copy
139
+ explain the intent. An icon-only control needs a tooltip and accessible name.
140
+ - Give the persistent agent drawer a quiet but intentional boundary: a subtle
141
+ surface shift, divider, or both. The sidebar and domain page should not read
142
+ as one undifferentiated slab, and the treatment should remain calm when the
143
+ drawer opens or closes.
144
+ - Treat an AI-labeled button as a contract. Buttons named Ask agent, Review
145
+ with agent, Refine, Generate with AI, or similar must call
146
+ `sendToAgentChat` with bounded context, `openSidebar: true`, and the intended
147
+ `submit` mode. A deterministic local action is useful, but label it local,
148
+ preview, or analyze rather than implying it invoked an agent.
149
+
150
+ ### Product Surface Review
151
+
152
+ Before shipping a new app or a substantial redesign, review the first viewport
153
+ as an operator would use it repeatedly:
154
+
155
+ - Show one clear job title, the current state, and one primary next action.
156
+ - Put optional inputs, provider choices, diagnostics, long explanations, and
157
+ secondary actions behind a disclosure, a later step, a menu, or the agent
158
+ sidebar. Do not put multiple unrelated forms side by side by default.
159
+ - Prefer a short step flow or a focused page per domain job over one giant
160
+ dashboard. A route can have several states, but it should reveal one state
161
+ at a time and preserve the user's progress.
162
+ - Remove generic hero copy, feature tours, repeated helper text, nested cards,
163
+ status-chip soup, and decorative AI treatment before adding more styling.
164
+ - For review flows, stack the source/original first and the generated or safe
165
+ result second by default. Use side-by-side comparison only when the content
166
+ is short enough to scan without excessive horizontal reading.
167
+ - Check the result at the target desktop width and a narrow width. If the first
168
+ viewport feels like documentation instead of a tool, subtract again.
169
+
118
170
  ## shadcn/ui Design Rules
119
171
 
120
172
  - Use built-in component variants first (`variant`, `size`) before overriding classes.
@@ -296,6 +296,63 @@ export declare const chatThreads: import("drizzle-orm/sqlite-core").SQLiteTableW
296
296
  }, {}, {
297
297
  length: number;
298
298
  }>;
299
+ sourcePlatform: import("drizzle-orm/sqlite-core").SQLiteColumn<{
300
+ name: "source_platform";
301
+ tableName: "chat_threads";
302
+ dataType: "string";
303
+ columnType: "SQLiteText";
304
+ data: string;
305
+ driverParam: string;
306
+ notNull: false;
307
+ hasDefault: false;
308
+ isPrimaryKey: false;
309
+ isAutoincrement: false;
310
+ hasRuntimeDefault: false;
311
+ enumValues: [string, ...string[]];
312
+ baseColumn: never;
313
+ identity: undefined;
314
+ generated: undefined;
315
+ }, {}, {
316
+ length: number;
317
+ }>;
318
+ sourceAppId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
319
+ name: "source_app_id";
320
+ tableName: "chat_threads";
321
+ dataType: "string";
322
+ columnType: "SQLiteText";
323
+ data: string;
324
+ driverParam: string;
325
+ notNull: false;
326
+ hasDefault: false;
327
+ isPrimaryKey: false;
328
+ isAutoincrement: false;
329
+ hasRuntimeDefault: false;
330
+ enumValues: [string, ...string[]];
331
+ baseColumn: never;
332
+ identity: undefined;
333
+ generated: undefined;
334
+ }, {}, {
335
+ length: number;
336
+ }>;
337
+ sourceUrl: import("drizzle-orm/sqlite-core").SQLiteColumn<{
338
+ name: "source_url";
339
+ tableName: "chat_threads";
340
+ dataType: "string";
341
+ columnType: "SQLiteText";
342
+ data: string;
343
+ driverParam: string;
344
+ notNull: false;
345
+ hasDefault: false;
346
+ isPrimaryKey: false;
347
+ isAutoincrement: false;
348
+ hasRuntimeDefault: false;
349
+ enumValues: [string, ...string[]];
350
+ baseColumn: never;
351
+ identity: undefined;
352
+ generated: undefined;
353
+ }, {}, {
354
+ length: number;
355
+ }>;
299
356
  };
300
357
  dialect: 'sqlite';
301
358
  }>;
@@ -14,6 +14,9 @@ export const chatThreads = table("chat_threads", {
14
14
  pinnedAt: integer("pinned_at"),
15
15
  archivedAt: integer("archived_at"),
16
16
  shareTokenHash: text("share_token_hash"),
17
+ sourcePlatform: text("source_platform"),
18
+ sourceAppId: text("source_app_id"),
19
+ sourceUrl: text("source_url"),
17
20
  ...ownableColumns(),
18
21
  });
19
22
  export const chatThreadShares = createSharesTable("chat_thread_shares");
@@ -26,6 +26,11 @@ export interface ChatThreadScope {
26
26
  id: string;
27
27
  label?: string;
28
28
  }
29
+ export interface ChatThreadSource {
30
+ platform?: string | null;
31
+ appId?: string | null;
32
+ url?: string | null;
33
+ }
29
34
  export interface ChatThread {
30
35
  id: string;
31
36
  ownerEmail: string;
@@ -38,6 +43,7 @@ export interface ChatThread {
38
43
  scope: ChatThreadScope | null;
39
44
  pinnedAt: number | null;
40
45
  archivedAt: number | null;
46
+ source: ChatThreadSource | null;
41
47
  orgId: string | null;
42
48
  visibility: "private" | "org" | "public";
43
49
  }
@@ -51,6 +57,7 @@ export interface ChatThreadSummary {
51
57
  scope: ChatThreadScope | null;
52
58
  pinnedAt: number | null;
53
59
  archivedAt: number | null;
60
+ source: ChatThreadSource | null;
54
61
  orgId: string | null;
55
62
  visibility: "private" | "org" | "public";
56
63
  }
@@ -65,11 +72,18 @@ export declare function createThread(ownerEmail: string, opts?: {
65
72
  id?: string;
66
73
  title?: string;
67
74
  scope?: ChatThreadScope | null;
75
+ source?: ChatThreadSource | null;
68
76
  }): Promise<ChatThread>;
69
77
  export declare function registerChatThreadsShareable(): void;
70
78
  export declare function ensureChatThreadTables(): Promise<void>;
71
79
  export declare function resolveThreadAccess(userEmail: string | null | undefined, threadId: string | null | undefined, minRole?: ShareRole | "owner", ctx?: Omit<AccessContext, "userEmail">): Promise<ChatThread | null>;
72
80
  export declare function getThread(id: string): Promise<ChatThread | null>;
81
+ /**
82
+ * Fill missing provenance on a thread without rewriting an established origin.
83
+ * Integration retries and long-lived mapped conversations both pass through
84
+ * this path, so the first source remains the source shown in chat history.
85
+ */
86
+ export declare function setThreadSourceIfMissing(id: string, source: ChatThreadSource | null | undefined): Promise<boolean>;
73
87
  export declare function forkThread(sourceId: string, ownerEmail: string, opts?: {
74
88
  id?: string;
75
89
  source?: ForkThreadSourceSnapshot | null;
@@ -99,6 +113,14 @@ export interface ListThreadsOptions {
99
113
  * (e.g. an "Archived" filter or restoring one via `setThreadArchived`).
100
114
  */
101
115
  includeArchived?: boolean;
116
+ /**
117
+ * Include connected and other-app threads. The HTTP chat list defaults this
118
+ * to false so each app shows its own local chats first; internal callers
119
+ * keep the historical all-sources behavior unless they opt out explicitly.
120
+ */
121
+ includeExternal?: boolean;
122
+ /** Current app id used by the local-only view. */
123
+ sourceAppId?: string | null;
102
124
  }
103
125
  export declare function listThreads(ownerEmail: string, options?: ListThreadsOptions | number, legacyOffset?: number): Promise<ChatThreadSummary[]>;
104
126
  export declare function searchThreads(ownerEmail: string, query: string, limit?: number, options?: {
@@ -109,6 +131,10 @@ export declare function searchThreads(ownerEmail: string, query: string, limit?:
109
131
  orgId?: string | null;
110
132
  /** See `ListThreadsOptions.includeArchived` — defaults to false. */
111
133
  includeArchived?: boolean;
134
+ /** See `ListThreadsOptions.includeExternal`. */
135
+ includeExternal?: boolean;
136
+ /** Current app id used by the local-only view. */
137
+ sourceAppId?: string | null;
112
138
  }): Promise<ChatThreadSummary[]>;
113
139
  /**
114
140
  * Scope a thread should carry after a run inside a resource: adopt when it has
@@ -65,6 +65,9 @@ async function ensureTable() {
65
65
  pinned_at ${intType()},
66
66
  archived_at ${intType()},
67
67
  share_token_hash TEXT,
68
+ source_platform TEXT,
69
+ source_app_id TEXT,
70
+ source_url TEXT,
68
71
  org_id TEXT,
69
72
  visibility TEXT NOT NULL DEFAULT 'private'
70
73
  )
@@ -92,6 +95,9 @@ async function ensureTable() {
92
95
  ["pinned_at", intType()],
93
96
  ["archived_at", intType()],
94
97
  ["share_token_hash", "TEXT"],
98
+ ["source_platform", "TEXT"],
99
+ ["source_app_id", "TEXT"],
100
+ ["source_url", "TEXT"],
95
101
  ["org_id", "TEXT"],
96
102
  ["visibility", "TEXT NOT NULL DEFAULT 'private'"],
97
103
  ]) {
@@ -113,6 +119,7 @@ async function ensureTable() {
113
119
  // and skip the SHARE-locking CREATE INDEX when already present.
114
120
  await ensureIndexExists("chat_threads_owner_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`);
115
121
  await ensureIndexExists("chat_threads_scope_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`);
122
+ await ensureIndexExists("chat_threads_source_updated_idx", `CREATE INDEX IF NOT EXISTS chat_threads_source_updated_idx ON chat_threads (owner_email, source_app_id, updated_at)`);
116
123
  // Public share-link resolution looks threads up by token hash;
117
124
  // without this index it degrades to a LIKE scan over every blob.
118
125
  await ensureIndexExists("chat_threads_share_token_idx", `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`);
@@ -132,6 +139,9 @@ async function ensureTable() {
132
139
  ["pinned_at", intType()],
133
140
  ["archived_at", intType()],
134
141
  ["share_token_hash", "TEXT"],
142
+ ["source_platform", "TEXT"],
143
+ ["source_app_id", "TEXT"],
144
+ ["source_url", "TEXT"],
135
145
  ["org_id", "TEXT"],
136
146
  ["visibility", "TEXT NOT NULL DEFAULT 'private'"],
137
147
  ]) {
@@ -166,6 +176,7 @@ async function ensureTable() {
166
176
  for (const ddl of [
167
177
  `CREATE INDEX IF NOT EXISTS chat_threads_owner_updated_idx ON chat_threads (owner_email, updated_at)`,
168
178
  `CREATE INDEX IF NOT EXISTS chat_threads_scope_updated_idx ON chat_threads (scope_type, scope_id, updated_at)`,
179
+ `CREATE INDEX IF NOT EXISTS chat_threads_source_updated_idx ON chat_threads (owner_email, source_app_id, updated_at)`,
169
180
  `CREATE INDEX IF NOT EXISTS chat_threads_share_token_idx ON chat_threads (share_token_hash)`,
170
181
  CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,
171
182
  ]) {
@@ -238,6 +249,24 @@ function readScope(r) {
238
249
  const label = r.scope_label;
239
250
  return label ? { type, id, label } : { type, id };
240
251
  }
252
+ function readSource(r) {
253
+ const platform = typeof r.source_platform === "string" && r.source_platform.trim()
254
+ ? r.source_platform.trim()
255
+ : null;
256
+ const appId = typeof r.source_app_id === "string" && r.source_app_id.trim()
257
+ ? r.source_app_id.trim()
258
+ : null;
259
+ const url = typeof r.source_url === "string" && r.source_url.trim()
260
+ ? r.source_url.trim()
261
+ : null;
262
+ if (!platform && !appId && !url)
263
+ return null;
264
+ return {
265
+ ...(platform ? { platform } : {}),
266
+ ...(appId ? { appId } : {}),
267
+ ...(url ? { url } : {}),
268
+ };
269
+ }
241
270
  function readNullableNumber(value) {
242
271
  if (value == null)
243
272
  return null;
@@ -303,6 +332,7 @@ function rowToThread(r) {
303
332
  scope: readScope(r),
304
333
  pinnedAt: readNullableNumber(r.pinned_at),
305
334
  archivedAt: readNullableNumber(r.archived_at),
335
+ source: readSource(r),
306
336
  orgId: r.org_id ?? null,
307
337
  visibility: readVisibility(r.visibility),
308
338
  };
@@ -324,6 +354,7 @@ function rowToSummary(r) {
324
354
  scope: readScope(r),
325
355
  pinnedAt: readNullableNumber(r.pinned_at),
326
356
  archivedAt: readNullableNumber(r.archived_at),
357
+ source: readSource(r),
327
358
  orgId: r.org_id ?? null,
328
359
  visibility: readVisibility(r.visibility),
329
360
  };
@@ -335,9 +366,10 @@ export async function createThread(ownerEmail, opts) {
335
366
  const now = Date.now();
336
367
  const title = opts?.title ?? "";
337
368
  const scope = opts?.scope ?? null;
369
+ const source = opts?.source ?? null;
338
370
  const orgId = getRequestOrgId() ?? null;
339
371
  await client.execute({
340
- sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, '', '{}', 0, ?, ?, ?, ?, ?, ?, 'private')`,
372
+ sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, source_platform, source_app_id, source_url, org_id, visibility) VALUES (?, ?, ?, '', '{}', 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')`,
341
373
  args: [
342
374
  id,
343
375
  ownerEmail,
@@ -347,6 +379,9 @@ export async function createThread(ownerEmail, opts) {
347
379
  scope?.type ?? null,
348
380
  scope?.id ?? null,
349
381
  scope?.label ?? null,
382
+ source?.platform ?? null,
383
+ source?.appId ?? null,
384
+ source?.url ?? null,
350
385
  orgId,
351
386
  ],
352
387
  });
@@ -362,18 +397,19 @@ export async function createThread(ownerEmail, opts) {
362
397
  scope,
363
398
  pinnedAt: null,
364
399
  archivedAt: null,
400
+ source,
365
401
  orgId,
366
402
  visibility: "private",
367
403
  };
368
404
  }
369
- const THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;
405
+ const THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, source_platform, source_app_id, source_url, org_id, visibility`;
370
406
  // The list/summary path deliberately omits `thread_data`: it is the full
371
407
  // message-history JSON blob and selecting it for every row turns "open the
372
408
  // sidebar" into "download every conversation". The summary derives nothing
373
409
  // from the blob anymore — preview and message_count are dedicated columns
374
410
  // (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /
375
411
  // `getThread`) still returns the full blob.
376
- const SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;
412
+ const SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, source_platform, source_app_id, source_url, org_id, visibility`;
377
413
  export function registerChatThreadsShareable() {
378
414
  registerShareableResource({
379
415
  type: "chat_thread",
@@ -412,6 +448,28 @@ export async function getThread(id) {
412
448
  return null;
413
449
  return rowToThread(rows[0]);
414
450
  }
451
+ /**
452
+ * Fill missing provenance on a thread without rewriting an established origin.
453
+ * Integration retries and long-lived mapped conversations both pass through
454
+ * this path, so the first source remains the source shown in chat history.
455
+ */
456
+ export async function setThreadSourceIfMissing(id, source) {
457
+ if (!source || (!source.platform && !source.appId && !source.url)) {
458
+ return false;
459
+ }
460
+ await ensureTable();
461
+ const client = getDbExec();
462
+ const result = await client.execute({
463
+ sql: `UPDATE chat_threads SET source_platform = COALESCE(source_platform, ?), source_app_id = COALESCE(source_app_id, ?), source_url = COALESCE(source_url, ?) WHERE id = ?`,
464
+ args: [
465
+ source.platform ?? null,
466
+ source.appId ?? null,
467
+ source.url ?? null,
468
+ id,
469
+ ],
470
+ });
471
+ return result.rowsAffected > 0;
472
+ }
415
473
  export async function forkThread(sourceId, ownerEmail, opts) {
416
474
  const snapshot = normalizeForkSourceSnapshot(opts?.source);
417
475
  let source = await getThread(sourceId);
@@ -464,7 +522,7 @@ export async function forkThread(sourceId, ownerEmail, opts) {
464
522
  const client = getDbExec();
465
523
  const orgId = getRequestOrgId() ?? null;
466
524
  await client.execute({
467
- sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, org_id, visibility) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')`,
525
+ sql: `INSERT INTO chat_threads (id, owner_email, title, preview, thread_data, message_count, created_at, updated_at, scope_type, scope_id, scope_label, source_platform, source_app_id, source_url, org_id, visibility) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')`,
468
526
  args: [
469
527
  id,
470
528
  ownerEmail,
@@ -477,6 +535,9 @@ export async function forkThread(sourceId, ownerEmail, opts) {
477
535
  source.scope?.type ?? null,
478
536
  source.scope?.id ?? null,
479
537
  source.scope?.label ?? null,
538
+ null,
539
+ null,
540
+ null,
480
541
  orgId,
481
542
  ],
482
543
  });
@@ -492,6 +553,7 @@ export async function forkThread(sourceId, ownerEmail, opts) {
492
553
  scope: source.scope,
493
554
  pinnedAt: null,
494
555
  archivedAt: null,
556
+ source: null,
495
557
  orgId,
496
558
  visibility: "private",
497
559
  };
@@ -521,14 +583,22 @@ export async function listThreads(ownerEmail, options = {}, legacyOffset) {
521
583
  const offset = opts.offset ?? 0;
522
584
  const client = getDbExec();
523
585
  // `message_count > 0` is the authoritative "has messages" signal maintained
524
- // on every write, so the old `OR thread_data LIKE '%"messages"%'` substring
525
- // scan over the full blob is no longer needed here.
586
+ // on every write. The local-only view adds a narrowly scoped legacy marker
587
+ // check below because older integration rows predate persisted source fields.
526
588
  const access = chatThreadAccessSql(ownerEmail, opts.orgId ?? getRequestOrgId());
527
589
  const filters = [access.sql, `message_count > 0`];
528
590
  const args = [...access.args];
529
591
  if (!opts.includeArchived) {
530
592
  filters.push(`archived_at IS NULL`);
531
593
  }
594
+ if (opts.includeExternal === false) {
595
+ filters.push(`source_platform IS NULL`);
596
+ filters.push(`thread_data NOT LIKE '%"integrationDeliveryAttempted":true%'`);
597
+ if (opts.sourceAppId) {
598
+ filters.push(`(source_app_id IS NULL OR source_app_id = ?)`);
599
+ args.push(opts.sourceAppId);
600
+ }
601
+ }
532
602
  if (opts.scope) {
533
603
  filters.push(`scope_type = ? AND scope_id = ?`);
534
604
  args.push(opts.scope.type, opts.scope.id);
@@ -565,6 +635,14 @@ export async function searchThreads(ownerEmail, query, limit = 50, options = {})
565
635
  if (!options.includeArchived) {
566
636
  filters.push(`archived_at IS NULL`);
567
637
  }
638
+ if (options.includeExternal === false) {
639
+ filters.push(`source_platform IS NULL`);
640
+ filters.push(`thread_data NOT LIKE '%"integrationDeliveryAttempted":true%'`);
641
+ if (options.sourceAppId) {
642
+ filters.push(`(source_app_id IS NULL OR source_app_id = ?)`);
643
+ args.push(options.sourceAppId);
644
+ }
645
+ }
568
646
  if (options.scope) {
569
647
  filters.push(`scope_type = ? AND scope_id = ?`);
570
648
  args.push(options.scope.type, options.scope.id);
@@ -52,6 +52,7 @@ import { RealtimeVoiceModeProvider } from "./composer/index.js";
52
52
  import { getFramePostMessageTargetOrigin, isTrustedFrameMessage, } from "./frame.js";
53
53
  import { useT } from "./i18n.js";
54
54
  import { isFirstRunOnboardingEnabled } from "./onboarding/first-run-enabled.js";
55
+ import { useOnboardingPreviewMode } from "./onboarding/use-preview-mode.js";
55
56
  import { recoverFromStaleChunkError } from "./route-chunk-recovery.js";
56
57
  import { AgentNativeRouteWarmup } from "./route-warmup.js";
57
58
  import { withBuilderConnectTrackingParams } from "./settings/useBuilderStatus.js";
@@ -70,9 +71,10 @@ function settingsRouteHashForSection(section) {
70
71
  if (normalized.startsWith("secrets") ||
71
72
  normalized.includes("api") ||
72
73
  normalized === "integrations" ||
74
+ normalized === "connections" ||
73
75
  normalized === "email" ||
74
76
  normalized === "browser") {
75
- return "#connections";
77
+ return "#integrations";
76
78
  }
77
79
  if (normalized === "account" ||
78
80
  normalized === "workspace" ||
@@ -377,7 +379,7 @@ function CodeAccessUnavailablePanel({ title, description, ctaLabel, ctaHref, sec
377
379
  : withBuilderUtmTrackingParams("https://builder.io", {
378
380
  content: "code_access_unavailable_panel",
379
381
  });
380
- return (_jsxs("div", { className: cn("rounded-lg border border-border bg-muted/35 text-center", compact ? "mx-3 mt-2 px-3 py-2.5" : "max-w-[300px] px-4 py-4"), children: [_jsx("div", { className: cn("mx-auto flex items-center justify-center rounded-full bg-background text-muted-foreground", compact ? "mb-2 h-8 w-8" : "mb-3 h-10 w-10"), children: _jsx(IconTerminal2, { className: compact ? "h-4 w-4" : "h-5 w-5" }) }), _jsx("p", { className: "text-sm font-medium text-foreground", children: title }), _jsx("p", { className: cn("mt-1 text-muted-foreground", compact ? "text-[11px] leading-snug" : "text-xs leading-relaxed"), children: description }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center justify-center gap-2", children: [ctaHref ? (_jsxs("a", { href: ctaHref, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background hover:opacity-90", children: [ctaLabel, _jsx(IconExternalLink, { className: "h-3 w-3" })] })) : null, _jsxs("a", { href: builderHref, target: "_blank", rel: "noreferrer", onClick: () => {
382
+ return (_jsxs("div", { className: cn("rounded-lg border border-border bg-muted/35 text-center", compact ? "mx-3 mt-2 px-3 py-2.5" : "max-w-[300px] px-4 py-4"), children: [_jsx("div", { className: cn("mx-auto flex items-center justify-center rounded-full bg-background text-muted-foreground", compact ? "mb-2 h-8 w-8" : "mb-3 h-10 w-10"), children: _jsx(IconTerminal2, { className: compact ? "h-4 w-4" : "h-5 w-5" }) }), _jsx("p", { className: "text-sm font-medium text-foreground", children: title }), _jsx("p", { className: cn("mt-1 text-muted-foreground", compact ? "text-[11px] leading-snug" : "text-xs leading-relaxed"), children: description }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center justify-center gap-2", children: [ctaHref ? (_jsxs("a", { href: ctaHref, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background hover:opacity-90", children: [ctaLabel, _jsx(IconExternalLink, { className: "h-3 w-3" })] })) : null, _jsx("a", { href: builderHref, target: "_blank", rel: "noreferrer", onClick: () => {
381
383
  trackEvent("builder connect clicked", {
382
384
  feature: "builder",
383
385
  stage: "client",
@@ -385,12 +387,14 @@ function CodeAccessUnavailablePanel({ title, description, ctaLabel, ctaHref, sec
385
387
  flow: "background_agent",
386
388
  connect_url_kind: builderConnectUrl ? "provided" : "fallback",
387
389
  });
388
- }, className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", children: [secondaryCtaLabel, _jsx(IconExternalLink, { className: "h-3 w-3" })] })] })] }));
390
+ }, className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", children: secondaryCtaLabel })] })] }));
389
391
  }
390
392
  function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, emptyStateText, emptyStateAddon, suggestions, dynamicSuggestions, showHeader = true, onCollapse, isFullscreen, onToggleFullscreen, devAppUrl, storageKey, restoreActiveThread = true, scope, showScopeBadge, browserTabId, threadUrlSync, chatNotice, showTabBar = true, showPageNewChatButton = false, allowSettingsMode = true, chatOnly = false, agentPageHref, codeAccess, ...assistantChatProps }) {
391
393
  const t = useT();
392
394
  const navigate = useNavigate();
393
395
  const mounted = useClientOnly();
396
+ const onboardingPreviewMode = useOnboardingPreviewMode();
397
+ const showFirstRunOnboarding = SHOW_FIRST_RUN_ONBOARDING || onboardingPreviewMode;
394
398
  const insideAgentSidebar = React.useContext(AgentSidebarOnboardingContext);
395
399
  const feedbackEnabled = resolveFeedbackUrl(undefined, mounted ? undefined : null) !== null;
396
400
  const keyPrefix = storageKey ? `:${storageKey}` : "";
@@ -870,7 +874,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
870
874
  `[data-agent-fullscreen='true'] .agent-plan-mode-callout{` +
871
875
  `max-width:${FULLSCREEN_CHAT_COLUMN_MAX_PX}px;` +
872
876
  `margin-left:auto;margin-right:auto;width:100%;}`,
873
- } }), SHOW_ONBOARDING && mounted && (_jsx(Suspense, { fallback: null, children: _jsx(OnboardingPanel, {}) })), SHOW_FIRST_RUN_ONBOARDING && mounted && !insideAgentSidebar && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsx("div", { className: cn("flex flex-col min-h-0", mode === "chat" ? "flex-1" : "shrink-0"), children: mounted && (_jsx(Suspense, { fallback: _jsx(ChatLoadingSkeleton, { renderHeader: showHeader ? renderChatHeader : undefined, centerComposerWhenEmpty: assistantChatProps.centerComposerWhenEmpty, composerSlot: assistantChatProps.composerSlot, composerAreaClassName: assistantChatProps.composerAreaClassName, composerLayoutVariant: assistantChatProps.composerLayoutVariant }), children: _jsx(MultiTabAssistantChatLazy, { ...assistantChatProps, agentChatSurface: effectiveAgentChatSurface, apiUrl: apiUrl, showHeader: false, renderHeader: showHeader ? renderChatHeader : undefined, showTabBar: showTabBar, renderOverlay: showPageNewChatButton && !showHeader
877
+ } }), SHOW_ONBOARDING && mounted && (_jsx(Suspense, { fallback: null, children: _jsx(OnboardingPanel, {}) })), showFirstRunOnboarding && mounted && !insideAgentSidebar && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsx("div", { className: cn("flex flex-col min-h-0", mode === "chat" ? "flex-1" : "shrink-0"), children: mounted && (_jsx(Suspense, { fallback: _jsx(ChatLoadingSkeleton, { renderHeader: showHeader ? renderChatHeader : undefined, centerComposerWhenEmpty: assistantChatProps.centerComposerWhenEmpty, composerSlot: assistantChatProps.composerSlot, composerAreaClassName: assistantChatProps.composerAreaClassName, composerLayoutVariant: assistantChatProps.composerLayoutVariant }), children: _jsx(MultiTabAssistantChatLazy, { ...assistantChatProps, agentChatSurface: effectiveAgentChatSurface, apiUrl: apiUrl, showHeader: false, renderHeader: showHeader ? renderChatHeader : undefined, showTabBar: showTabBar, renderOverlay: showPageNewChatButton && !showHeader
874
878
  ? renderPageChatOverlay
875
879
  : undefined, contentHidden: mode !== "chat", emptyStateText: emptyStateText, emptyStateAddon: emptyStateAddon, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, onSwitchToCli: () => switchMode("cli"), execMode: execMode, onExecModeChange: switchExecMode, storageKey: storageKey, restoreActiveThread: restoreActiveThread, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync }) })) }), canUseCodeTools
876
880
  ? mode === "cli" &&
@@ -1310,6 +1314,8 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
1310
1314
  * Use AgentToggleButton in your header to open/close it.
1311
1315
  */
1312
1316
  export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, }) {
1317
+ const onboardingPreviewMode = useOnboardingPreviewMode();
1318
+ const showFirstRunOnboarding = SHOW_FIRST_RUN_ONBOARDING || onboardingPreviewMode;
1313
1319
  const initialWidth = defaultSidebarWidth ?? sidebarWidth ?? 380;
1314
1320
  const [open, setOpen] = useState(() => openOnChatRunning || getInitialAgentSidebarOpen(defaultOpen, storageKey));
1315
1321
  const [presentationMode, setPresentationMode] = useState(false);
@@ -1735,7 +1741,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
1735
1741
  : undefined, "data-agent-sidebar-layout": panelLayout, "data-agent-sidebar-position": position, "data-agent-sidebar-state": panelOpen ? "open" : "closed", "data-agent-sidebar-resizing": isResizing ? "true" : undefined, "data-agent-sidebar-chat-handoff": chatViewTransitionHandoff ? "true" : undefined, style: chatViewTransition
1736
1742
  ? getAgentChatViewTransitionStyle(panelStyle)
1737
1743
  : panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, threadFooterSlot: threadFooterSlot, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), isFullscreen: effectiveFullscreen, onToggleFullscreen: isMobile ? undefined : (onFullscreenRequest ?? toggleFullscreen), storageKey: storageKey, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
1738
- return (_jsx(AgentSidebarOnboardingContext.Provider, { value: true, children: _jsxs(RealtimeVoiceModeProvider, { browserTabId: browserTabId, children: [SHOW_FIRST_RUN_ONBOARDING && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsxs("div", { className: "agent-sidebar-shell flex min-w-0 flex-1 h-screen overflow-hidden", "data-agent-sidebar-position": position, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: [_jsx(AgentNativeRouteWarmup, {}), isMobile &&
1744
+ return (_jsx(AgentSidebarOnboardingContext.Provider, { value: true, children: _jsxs(RealtimeVoiceModeProvider, { browserTabId: browserTabId, children: [showFirstRunOnboarding && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsxs("div", { className: "agent-sidebar-shell flex min-w-0 flex-1 h-screen overflow-hidden", "data-agent-sidebar-position": position, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: [_jsx(AgentNativeRouteWarmup, {}), isMobile &&
1739
1745
  !presentationMode &&
1740
1746
  (mobileAnimationEnabled ? shouldRenderPanel : open) && (_jsx("div", { className: cn("agent-sidebar-backdrop fixed inset-0 bg-foreground/40", mobileAnimationEnabled && !panelOpen && "pointer-events-none"), "data-agent-sidebar-animation": mobileAnimationEnabled ? "mobile" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", style: { zIndex: SIDEBAR_OVERLAY_Z_INDEX - 1 }, onClick: () => setOpenPersisted(false) })), shouldMountPanel ? _jsx(URLSync, { browserTabId: browserTabId }) : null, isLeft && !presentationMode ? sidebar : null, _jsx("div", { className: "agent-sidebar-main-surface flex flex-1 flex-col overflow-auto min-w-0", "data-agent-sidebar-main-position": position, "data-agent-sidebar-main-state": !isMobile &&
1741
1747
  !effectiveFullscreen &&
@@ -189,6 +189,6 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
189
189
  return (_jsx("div", { className: cn("my-2 rounded-lg border border-border overflow-hidden"), children: _jsxs("div", { className: "flex items-start gap-3 px-4 py-3.5 bg-gradient-to-br from-teal-500/5 via-transparent to-transparent", children: [_jsx("div", { className: cn("flex h-9 w-9 shrink-0 items-center justify-center rounded-lg", "bg-foreground text-background"), children: runResult ? (_jsx(IconLoader2, { className: "h-5 w-5 animate-spin" })) : (_jsx(BuilderBMark, { className: "h-5 w-5" })) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "flex items-center gap-2 flex-wrap", children: _jsx("span", { className: "text-sm font-semibold text-foreground", children: title }) }), _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground leading-relaxed", children: subtitle }), showWaitlist && (_jsxs("a", { href: DESKTOP_DOWNLOAD_URL, target: "_blank", rel: "noopener noreferrer", className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground no-underline hover:text-foreground", children: ["Download desktop app", _jsx(IconExternalLink, { className: "h-3 w-3" })] })), err && _jsx("div", { className: "mt-2 text-xs text-destructive", children: err }), _jsx("div", { className: "mt-3", children: runResult ? (_jsxs("a", { href: withBuilderUtmTrackingParams(runResult.url, {
190
190
  campaign: "product",
191
191
  content: "connect_builder_card_branch",
192
- }), target: "_blank", rel: "noopener noreferrer", className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90"), children: ["Open branch in Builder", _jsx(IconExternalLink, { className: "h-3.5 w-3.5" })] })) : canSend ? (_jsx("button", { type: "button", onClick: handleSend, disabled: sending, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", sending && "opacity-70 cursor-wait"), children: sending ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Sending to Builder\u2026"] })) : (_jsx(_Fragment, { children: "Send to Builder" })) })) : showWaitlist && !waitlistJoined ? (_jsx("button", { type: "button", onClick: handleJoinWaitlist, disabled: joiningWaitlist, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", joiningWaitlist && "opacity-70 cursor-wait"), children: joiningWaitlist ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Joining\u2026"] })) : (_jsx(_Fragment, { children: "Join the waitlist" })) })) : !configured ? (_jsx("button", { type: "button", onClick: () => flow.start(), disabled: connecting, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", connecting && "opacity-70 cursor-wait"), children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Waiting for Builder\u2026"] })) : (_jsxs(_Fragment, { children: ["Connect Builder", _jsx(IconExternalLink, { className: "h-3.5 w-3.5" })] })) })) : null })] })] }) }));
192
+ }), target: "_blank", rel: "noopener noreferrer", className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90"), children: ["Open branch in Builder", _jsx(IconExternalLink, { className: "h-3.5 w-3.5" })] })) : canSend ? (_jsx("button", { type: "button", onClick: handleSend, disabled: sending, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", sending && "opacity-70 cursor-wait"), children: sending ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Sending to Builder\u2026"] })) : (_jsx(_Fragment, { children: "Send to Builder" })) })) : showWaitlist && !waitlistJoined ? (_jsx("button", { type: "button", onClick: handleJoinWaitlist, disabled: joiningWaitlist, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", joiningWaitlist && "opacity-70 cursor-wait"), children: joiningWaitlist ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Joining\u2026"] })) : (_jsx(_Fragment, { children: "Join the waitlist" })) })) : !configured ? (_jsx("button", { type: "button", onClick: () => flow.start(), disabled: connecting, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90", connecting && "opacity-70 cursor-wait"), children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { className: "h-3.5 w-3.5 animate-spin" }), "Waiting for Builder\u2026"] })) : ("Connect Builder") })) : null })] })] }) }));
193
193
  }
194
194
  //# sourceMappingURL=ConnectBuilderCard.js.map
@@ -7,7 +7,8 @@ interface AgentEmptyStateProps {
7
7
  description?: ReactNode;
8
8
  action?: ReactNode;
9
9
  className?: string;
10
+ variant?: "inline" | "card";
10
11
  }
11
- export declare function AgentEmptyState({ icon: Icon, title, description, action, className, }: AgentEmptyStateProps): import("react").JSX.Element;
12
+ export declare function AgentEmptyState({ icon: Icon, title, description, action, className, variant, }: AgentEmptyStateProps): import("react").JSX.Element;
12
13
  export {};
13
14
  //# sourceMappingURL=AgentEmptyState.d.ts.map
@@ -1,6 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../utils.js";
3
- export function AgentEmptyState({ icon: Icon, title, description, action, className, }) {
4
- return (_jsxs("div", { className: cn("flex min-w-0 items-start gap-3 border-y border-border/60 py-5", className), children: [Icon ? (_jsx(Icon, { "aria-hidden": "true", className: "mt-0.5 size-4 shrink-0 text-muted-foreground" })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: title }), description ? (_jsx("p", { className: "mt-1 max-w-2xl break-words text-sm leading-relaxed text-muted-foreground", children: description })) : null, action ? _jsx("div", { className: "mt-3", children: action }) : null] })] }));
3
+ export function AgentEmptyState({ icon: Icon, title, description, action, className, variant = "inline", }) {
4
+ return (_jsxs("div", { className: cn(variant === "card"
5
+ ? "flex min-w-0 flex-col items-center gap-2 rounded-xl border border-border/70 bg-card px-5 py-8 text-center"
6
+ : "flex min-w-0 items-start gap-3 border-y border-border/60 py-5", className), children: [Icon ? (_jsx(Icon, { "aria-hidden": "true", className: cn("shrink-0 text-muted-foreground", variant === "card"
7
+ ? "mb-1 size-8 rounded-full bg-muted p-2"
8
+ : "mt-0.5 size-4") })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: title }), description ? (_jsx("p", { className: cn("mt-1 break-words text-sm leading-relaxed text-muted-foreground", variant === "card" && "mx-auto max-w-md"), children: description })) : null, action ? (_jsx("div", { className: cn(variant === "card" ? "mt-4" : "mt-3"), children: action })) : null] })] }));
5
9
  }
6
10
  //# sourceMappingURL=AgentEmptyState.js.map
@@ -1,4 +1,6 @@
1
1
  import type { AgentPageTabProps } from "./types.js";
2
2
  export declare function organizationAutomationCreationContext(): string;
3
- export declare function AgentJobsTab({ canManageOrg }: AgentPageTabProps): import("react").JSX.Element;
3
+ export declare function AgentJobsTab({ canManageOrg, hideHeader, }: AgentPageTabProps & {
4
+ hideHeader?: boolean;
5
+ }): import("react").JSX.Element;
4
6
  //# sourceMappingURL=AgentJobsTab.d.ts.map