@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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +37 -17
- package/corpus/templates/analytics/app/lib/data-sources.ts +1 -1
- package/corpus/templates/analytics/server/lib/gong.ts +51 -2
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/app/routes/settings.tsx +1 -1
- package/corpus/templates/brain/server/register-secrets.ts +1 -1
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/AGENTS.md +11 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +29 -13
- package/corpus/templates/chat/vite.config.ts +42 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
- package/corpus/templates/clips/app/components/library/library-grid.tsx +2 -6
- package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -6
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +1 -3
- package/corpus/templates/clips/app/routes/bug-report.tsx +1 -8
- package/corpus/templates/clips/app/routes/import.tsx +1 -3
- package/corpus/templates/clips/changelog/2026-08-04-recording-buttons-are-now-text-only-for-a-cleaner-clips-inte.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-04-save-settings-now-matches-the-other-clips-settings-buttons.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/crm/app/routes/settings.tsx +2 -2
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/design/actions/import-figma-clipboard.ts +1 -1
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/dispatch/changelog/2026-08-04-dispatch-keeps-connected-chats-out-of-local-history-by-defau.md +6 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/factory/README.md +1 -1
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -4
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +83 -0
- package/corpus/templates/slides/actions/import-pptx.ts +134 -117
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +387 -0
- package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +78 -48
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +377 -187
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -1
- package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +20 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +15 -0
- package/corpus/templates/slides/app/lib/new-deck-reference-selection.ts +22 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -1
- package/corpus/templates/slides/app/pages/Index.tsx +172 -85
- package/corpus/templates/slides/server/lib/assets-image-delegation.ts +4 -2
- package/corpus/templates/slides/shared/api.ts +14 -1
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/chat-threads/schema.d.ts +57 -0
- package/dist/chat-threads/schema.js +3 -0
- package/dist/chat-threads/store.d.ts +26 -0
- package/dist/chat-threads/store.js +84 -6
- package/dist/client/AgentPanel.js +11 -5
- package/dist/client/ConnectBuilderCard.js +1 -1
- package/dist/client/agent-page/AgentEmptyState.d.ts +2 -1
- package/dist/client/agent-page/AgentEmptyState.js +6 -2
- package/dist/client/agent-page/AgentJobsTab.d.ts +3 -1
- package/dist/client/agent-page/AgentJobsTab.js +55 -44
- package/dist/client/agent-page/AgentTabFrame.d.ts +2 -1
- package/dist/client/agent-page/AgentTabFrame.js +4 -2
- package/dist/client/agent-page/AgentTabsPage.js +12 -8
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +10 -0
- package/dist/client/agent-page/AgentWorkspaceContent.js +110 -0
- package/dist/client/agent-page/AutomationDetailsDialog.js +1 -1
- package/dist/client/chat/run-recovery.js +3 -3
- package/dist/client/error-format.js +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts +1 -0
- package/dist/client/integrations/IntegrationsPanel.js +149 -5
- package/dist/client/onboarding/FirstRunOnboarding.js +130 -15
- package/dist/client/onboarding/index.d.ts +1 -1
- package/dist/client/onboarding/index.js +1 -1
- package/dist/client/onboarding/use-onboarding.js +12 -2
- package/dist/client/onboarding/use-preview-mode.d.ts +4 -0
- package/dist/client/onboarding/use-preview-mode.js +9 -0
- package/dist/client/resources/BuiltinCapabilityDetail.js +2 -2
- package/dist/client/resources/ResourceTree.d.ts +4 -1
- package/dist/client/resources/ResourceTree.js +13 -8
- package/dist/client/resources/ResourcesPanel.js +7 -3
- package/dist/client/resources/mcp-integration-catalog.js +4 -4
- package/dist/client/resources/use-mcp-servers.js +6 -6
- package/dist/client/settings/AgentsSection.js +15 -16
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.js +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -1
- package/dist/client/settings/SettingsPanel.js +284 -88
- package/dist/client/settings/SettingsRow.js +1 -1
- package/dist/client/settings/SettingsSection.d.ts +6 -4
- package/dist/client/settings/SettingsSection.js +6 -6
- package/dist/client/settings/SettingsTabsPage.js +47 -25
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +3 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +20 -8
- package/dist/client/settings/agent-settings-search.d.ts +1 -1
- package/dist/client/settings/agent-settings-search.js +8 -8
- package/dist/client/transcription/BuilderTranscriptionCta.js +2 -2
- package/dist/client/use-chat-threads.d.ts +9 -0
- package/dist/client/use-chat-threads.js +22 -6
- package/dist/collab/routes.d.ts +1 -1
- package/dist/integrations/google-docs-poller.js +9 -1
- package/dist/integrations/webhook-handler.js +11 -1
- package/dist/jobs/scheduler.d.ts +4 -1
- package/dist/jobs/scheduler.js +34 -9
- package/dist/localization/default-messages.js +40 -40
- package/dist/mcp-client/oauth-routes.js +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/onboarding.js +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
- package/dist/server/agent-chat/browser-team-tools.js +1 -0
- package/dist/server/agent-chat-plugin.js +14 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams.d.ts +2 -0
- package/dist/server/agent-teams.js +2 -0
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +2 -2
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/chat/AGENTS.md +11 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +29 -13
- package/dist/templates/chat/vite.config.ts +42 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/default/AGENTS.md +11 -0
- package/dist/templates/default/vite.config.ts +42 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/workspace-core/AGENTS.md +11 -0
- package/dist/templates/workspace-root/AGENTS.md +14 -0
- package/dist/vite/client.js +56 -0
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/chat/AGENTS.md +11 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +29 -13
- package/src/templates/chat/vite.config.ts +42 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/default/AGENTS.md +11 -0
- package/src/templates/default/vite.config.ts +42 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/workspace-core/AGENTS.md +11 -0
- 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
|
|
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
|
|
525
|
-
//
|
|
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 "#
|
|
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,
|
|
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:
|
|
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, {}) })),
|
|
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: [
|
|
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"] })) : (
|
|
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(
|
|
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
|
|
3
|
+
export declare function AgentJobsTab({ canManageOrg, hideHeader, }: AgentPageTabProps & {
|
|
4
|
+
hideHeader?: boolean;
|
|
5
|
+
}): import("react").JSX.Element;
|
|
4
6
|
//# sourceMappingURL=AgentJobsTab.d.ts.map
|