@agent-native/core 0.137.3 → 0.137.5
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/changelog/2026-08-04-signing-out-now-takes-effect-immediately-after-verifying-a-n.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- 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/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.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/progress/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/secrets/onboarding.js +1 -1
- 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-teams.d.ts +2 -0
- package/dist/server/agent-teams.js +2 -0
- package/dist/server/auth.js +35 -13
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/realtime-token.d.ts +1 -1
- 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
|
@@ -6,7 +6,7 @@ import { cn } from "../utils.js";
|
|
|
6
6
|
* resolve an app's i18n keys.
|
|
7
7
|
*/
|
|
8
8
|
export function SettingsGroup({ id, title, description, className, children, }) {
|
|
9
|
-
return (_jsxs("section", { id: id, className: cn("scroll-mt-16
|
|
9
|
+
return (_jsxs("section", { id: id, className: cn("scroll-mt-16", className), children: [(title || description) && (_jsxs("header", { className: "mb-2.5", children: [title && (_jsx("h2", { className: "text-sm font-semibold text-foreground", children: title })), description && (_jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: description }))] })), _jsx("div", { className: "overflow-hidden rounded-xl border border-border/70 bg-card text-card-foreground", children: _jsx("div", { className: "divide-y divide-border/60", children: children }) })] }));
|
|
10
10
|
}
|
|
11
11
|
/** One setting: label and description on the start side, control on the end. */
|
|
12
12
|
export function SettingsRow({ id, label, description, icon, status, control, children, className, }) {
|
|
@@ -20,15 +20,17 @@ interface SettingsSectionProps {
|
|
|
20
20
|
badge?: string;
|
|
21
21
|
required?: boolean;
|
|
22
22
|
connected?: boolean;
|
|
23
|
+
/** Let a child-owned card surface fill the section without a second wrapper. */
|
|
24
|
+
flat?: boolean;
|
|
25
|
+
/** Render the page content as a row inside a parent SettingsGroup. */
|
|
26
|
+
grouped?: boolean;
|
|
23
27
|
open?: boolean;
|
|
24
28
|
onToggle?: () => void;
|
|
25
29
|
children: ReactNode;
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* framework tabs match app-owned General/Team cards). The visual surface is
|
|
31
|
-
* read from `SettingsSurfaceContext`.
|
|
32
|
+
* Settings sections stay compact and collapsible in the agent sidebar, while
|
|
33
|
+
* the full settings page uses Codex-style headings and always-visible rows.
|
|
32
34
|
*/
|
|
33
35
|
export declare function SettingsSection(props: SettingsSectionProps): import("react").JSX.Element;
|
|
34
36
|
export {};
|
|
@@ -10,10 +10,8 @@ export function useSettingsSurface() {
|
|
|
10
10
|
return useContext(SettingsSurfaceContext);
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* framework tabs match app-owned General/Team cards). The visual surface is
|
|
16
|
-
* read from `SettingsSurfaceContext`.
|
|
13
|
+
* Settings sections stay compact and collapsible in the agent sidebar, while
|
|
14
|
+
* the full settings page uses Codex-style headings and always-visible rows.
|
|
17
15
|
*/
|
|
18
16
|
export function SettingsSection(props) {
|
|
19
17
|
const surface = useSettingsSurface();
|
|
@@ -59,8 +57,10 @@ function SettingsSectionBody({ open, children, }) {
|
|
|
59
57
|
return null;
|
|
60
58
|
return (_jsx("div", { "data-state": open ? "open" : "closed", "aria-hidden": open ? undefined : true, inert: open ? undefined : true, className: "agent-native-settings-section-body", onTransitionEnd: handleTransitionEnd, children: children }));
|
|
61
59
|
}
|
|
62
|
-
function PageSettingsSection({ id,
|
|
63
|
-
return (_jsxs("
|
|
60
|
+
function PageSettingsSection({ id, title, subtitle, badge, required, connected, flat, grouped, children, }) {
|
|
61
|
+
return (_jsxs("section", { id: id, className: "scroll-mt-16", children: [!grouped && (_jsx("div", { className: "mb-2.5 flex items-baseline justify-between gap-3", children: _jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: title }), connected && _jsx(ConnectedDot, { size: "sm" }), required && !connected && (_jsx(StatusBadge, { label: "Required", tone: "required", size: "sm" })), badge && _jsx(StatusBadge, { label: badge, tone: "muted", size: "sm" })] }), subtitle && (_jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: subtitle }))] }) })), _jsx("div", { "data-agent-native-settings-page": "", className: cn(!flat &&
|
|
62
|
+
!grouped &&
|
|
63
|
+
"overflow-hidden rounded-xl border border-border/70 bg-card text-card-foreground"), children: _jsx("div", { className: cn(!flat && !grouped && "divide-y divide-border/60 px-5 py-1 sm:px-6"), children: children }) })] }));
|
|
64
64
|
}
|
|
65
65
|
function SidebarSettingsSection({ id, icon, title, subtitle, badge, required, connected, open = false, onToggle, children, }) {
|
|
66
66
|
return (_jsxs("div", { id: id, className: "rounded-lg border border-border bg-background/50", children: [_jsxs("button", { type: "button", onClick: onToggle, "aria-expanded": open, className: "flex w-full cursor-pointer items-center justify-between px-3 py-2.5 text-start rounded-lg hover:bg-accent/40 transition-colors", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "shrink-0 text-muted-foreground", children: icon }), _jsx("span", { className: "text-[12px] font-medium text-foreground truncate", children: title }), connected && _jsx(ConnectedDot, { size: "sm" }), required && !connected && (_jsx(StatusBadge, { label: "Required", tone: "muted", size: "sm" })), badge && _jsx(StatusBadge, { label: badge, tone: "muted", size: "sm" })] }), _jsx(IconChevronDown, { size: 12, className: `shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })] }), _jsx(SettingsSectionBody, { open: open, children: _jsxs("div", { className: "border-t border-border px-3 pb-3 pt-2.5", children: [subtitle && (_jsx("p", { className: "text-[10px] text-muted-foreground mb-2.5", children: subtitle })), children] }) })] }));
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Tabs, useDesignSystem } from "@agent-native/toolkit/design-system";
|
|
3
|
-
import { IconArrowUpRight, IconHistory, IconSearch, IconSettings, IconUserCircle, IconUsers, IconX, } from "@tabler/icons-react";
|
|
3
|
+
import { IconArrowLeft, IconArrowUpRight, IconHistory, IconSearch, IconSettings, IconUserCircle, IconUsers, IconX, } from "@tabler/icons-react";
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
5
5
|
import { Link } from "react-router";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
7
7
|
function normalizeTabId(value) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
let decoded = value?.replace(/^#/, "").trim() ?? "";
|
|
9
|
+
try {
|
|
10
|
+
decoded = decodeURIComponent(decoded);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// coercion-ok: preserve malformed external hashes for routing fallback.
|
|
14
|
+
// Keep the raw hash when an external link contains malformed encoding.
|
|
15
|
+
}
|
|
16
|
+
const normalized = decoded
|
|
11
17
|
.toLowerCase()
|
|
12
18
|
.replace(/['"]/g, "")
|
|
13
19
|
.replace(/[\s_]+/g, "-");
|
|
@@ -22,6 +28,9 @@ function normalizeTabId(value) {
|
|
|
22
28
|
if (normalized === "workspace" || normalized === "workspace-settings") {
|
|
23
29
|
return "workspace";
|
|
24
30
|
}
|
|
31
|
+
if (normalized === "connections") {
|
|
32
|
+
return "integrations";
|
|
33
|
+
}
|
|
25
34
|
return normalized;
|
|
26
35
|
}
|
|
27
36
|
function resolveTabId(tabs, value) {
|
|
@@ -30,7 +39,15 @@ function resolveTabId(tabs, value) {
|
|
|
30
39
|
return null;
|
|
31
40
|
if (tabs.some((tab) => tab.id === normalized))
|
|
32
41
|
return normalized;
|
|
42
|
+
const nestedTab = tabs
|
|
43
|
+
.filter((tab) => normalized.startsWith(`${tab.id}:`) ||
|
|
44
|
+
tab.id.startsWith(`${normalized}:`))
|
|
45
|
+
.sort((a, b) => b.id.length - a.id.length)[0];
|
|
46
|
+
if (nestedTab)
|
|
47
|
+
return nestedTab.id;
|
|
33
48
|
const section = normalized.split(":", 1)[0];
|
|
49
|
+
if (tabs.some((tab) => tab.id === section))
|
|
50
|
+
return section;
|
|
34
51
|
const owner = tabs.find((tab) => tab.searchEntries?.some((entry) => normalizeTabId(entry.hash ?? entry.id) === section));
|
|
35
52
|
if (owner)
|
|
36
53
|
return owner.id;
|
|
@@ -53,7 +70,7 @@ function updateHashForTab(tabId) {
|
|
|
53
70
|
if (typeof window === "undefined")
|
|
54
71
|
return;
|
|
55
72
|
const { pathname, search } = window.location;
|
|
56
|
-
const hash = tabId === "general" ? "" : `#${
|
|
73
|
+
const hash = tabId === "general" ? "" : `#${tabId}`;
|
|
57
74
|
window.history.pushState(null, "", `${pathname}${search}${hash}`);
|
|
58
75
|
}
|
|
59
76
|
function isEditableElement(element) {
|
|
@@ -65,7 +82,7 @@ function isEditableElement(element) {
|
|
|
65
82
|
tagName === "select" ||
|
|
66
83
|
element.isContentEditable);
|
|
67
84
|
}
|
|
68
|
-
export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs = [], generalLabel = "General", accountLabel = "Account", teamLabel = "Team", whatsNewLabel = "What's new", ariaLabel = "Settings sections", defaultTab = "
|
|
85
|
+
export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs = [], generalLabel = "General", accountLabel = "Account", teamLabel = "Team", whatsNewLabel = "What's new", ariaLabel = "Settings sections", defaultTab = "integrations", className, navClassName, contentClassName, enableSearch = true, searchPlaceholder = "Search settings", searchEntries, generalSearchEntries, value, onValueChange, }) {
|
|
69
86
|
const rootRef = useRef(null);
|
|
70
87
|
const searchInputRef = useRef(null);
|
|
71
88
|
const autoFocusedSearchRef = useRef(false);
|
|
@@ -142,6 +159,12 @@ export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs =
|
|
|
142
159
|
}
|
|
143
160
|
return groups;
|
|
144
161
|
}, [tabs]);
|
|
162
|
+
const tabGroupLabels = {
|
|
163
|
+
app: "Personal",
|
|
164
|
+
integrations: "Integrations",
|
|
165
|
+
workspace: "Workspace",
|
|
166
|
+
agent: "Agent",
|
|
167
|
+
};
|
|
145
168
|
const isControlled = value !== undefined;
|
|
146
169
|
const [internalTab, setInternalTab] = useState(() => activeTabFromHash(tabs, fallbackTab));
|
|
147
170
|
const activeTab = isControlled ? value : internalTab;
|
|
@@ -300,7 +323,7 @@ export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs =
|
|
|
300
323
|
}
|
|
301
324
|
};
|
|
302
325
|
const searching = enableSearch && trimmedQuery.length > 0;
|
|
303
|
-
return (_jsxs("div", { ref: rootRef, className: cn("flex h-full min-h-0 w-full flex-col overflow-hidden bg-background sm:flex-row", className), children: [_jsxs("div", { className: cn("flex shrink-0 flex-col gap-2 bg-background p-2 sm:min-h-0 sm:w-
|
|
326
|
+
return (_jsxs("div", { ref: rootRef, className: cn("flex h-full min-h-0 w-full flex-col overflow-hidden bg-background sm:flex-row", className), children: [_jsxs("div", { className: cn("flex shrink-0 flex-col gap-2 bg-background p-2 sm:min-h-0 sm:w-60 sm:overflow-y-auto sm:p-4", navClassName), children: [_jsxs("a", { href: "/", className: "flex min-h-8 items-center gap-2 rounded-md px-2 text-sm text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground", children: [_jsx(IconArrowLeft, { className: "size-4 shrink-0 rtl:-scale-x-100" }), _jsx("span", { children: "Back to app" })] }), enableSearch ? (_jsxs("div", { className: "relative sm:mb-2", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { ref: searchInputRef, type: "search", value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
|
|
304
327
|
if (event.key === "Escape")
|
|
305
328
|
setQuery("");
|
|
306
329
|
if (event.key === "Enter" && results[0]) {
|
|
@@ -329,25 +352,24 @@ export function SettingsTabsPage({ general, account, team, whatsNew, extraTabs =
|
|
|
329
352
|
changeTab(nextTab);
|
|
330
353
|
if (!isControlled)
|
|
331
354
|
updateHashForTab(nextTab);
|
|
332
|
-
}, orientation: "vertical", "aria-label": ariaLabel, className: "flex gap-1 overflow-x-auto sm:flex-col sm:overflow-x-visible" })) : (_jsx("nav", { "aria-label": ariaLabel, role: "tablist", className: "flex gap-1 overflow-x-auto sm:flex-col sm:overflow-x-visible", children: tabGroups.map((group, groupIndex) => (_jsx("div", { "data-settings-tab-group": group.id, className: cn("contents sm:block", groupIndex > 0 &&
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
355
|
+
}, orientation: "vertical", "aria-label": ariaLabel, className: "flex gap-1 overflow-x-auto sm:flex-col sm:overflow-x-visible" })) : (_jsx("nav", { "aria-label": ariaLabel, role: "tablist", className: "flex gap-1 overflow-x-auto sm:flex-col sm:overflow-x-visible", children: tabGroups.map((group, groupIndex) => (_jsx("div", { "data-settings-tab-group": group.id, className: cn("contents sm:block", groupIndex > 0 && "sm:mt-3 sm:pt-1"), children: _jsxs("div", { className: "contents sm:flex sm:flex-col sm:gap-1", children: [_jsx("div", { className: "hidden px-3 pb-1 pt-1 text-[11px] font-medium text-muted-foreground sm:block", children: tabGroupLabels[group.id] ?? group.id }), group.tabs.map((tab) => {
|
|
356
|
+
const Icon = tab.icon;
|
|
357
|
+
const selected = tab.id === selectedTab?.id;
|
|
358
|
+
const tabContent = (_jsxs(_Fragment, { children: [Icon ? (_jsx(Icon, { className: cn("size-4 shrink-0", selected
|
|
359
|
+
? "text-foreground"
|
|
360
|
+
: "text-muted-foreground") })) : null, _jsx("span", { className: "truncate", children: tab.label }), tab.href ? (_jsx(IconArrowUpRight, { "aria-hidden": "true", className: "size-3.5 shrink-0 text-muted-foreground/80" })) : null] }));
|
|
361
|
+
if (tab.href) {
|
|
362
|
+
return (_jsx(Link, { role: "tab", "aria-selected": selected, to: tab.href, className: cn("flex min-h-9 shrink-0 items-center gap-2 rounded-md px-3 py-2 text-start text-sm font-medium transition-colors sm:w-full", selected
|
|
363
|
+
? "bg-accent text-foreground"
|
|
364
|
+
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: tabContent }, tab.id));
|
|
365
|
+
}
|
|
366
|
+
return (_jsx("button", { type: "button", role: "tab", "aria-selected": selected, "aria-controls": `settings-tabpanel-${tab.id}`, id: `settings-tab-${tab.id}`, onClick: () => {
|
|
367
|
+
changeTab(tab.id);
|
|
368
|
+
if (!isControlled)
|
|
369
|
+
updateHashForTab(tab.id);
|
|
370
|
+
}, className: cn("flex min-h-9 shrink-0 items-center gap-2 rounded-md px-3 py-2 text-start text-sm font-medium transition-colors sm:w-full", selected
|
|
341
371
|
? "bg-accent text-foreground"
|
|
342
372
|
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: tabContent }, tab.id));
|
|
343
|
-
}
|
|
344
|
-
return (_jsx("button", { type: "button", role: "tab", "aria-selected": selected, "aria-controls": `settings-tabpanel-${tab.id}`, id: `settings-tab-${tab.id}`, onClick: () => {
|
|
345
|
-
changeTab(tab.id);
|
|
346
|
-
if (!isControlled)
|
|
347
|
-
updateHashForTab(tab.id);
|
|
348
|
-
}, className: cn("flex min-h-9 shrink-0 items-center gap-2 rounded-md px-3 py-2 text-start text-sm font-medium transition-colors sm:w-full", selected
|
|
349
|
-
? "bg-accent text-foreground"
|
|
350
|
-
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: tabContent }, tab.id));
|
|
351
|
-
}) }) }, group.id))) }))] }), _jsx("div", { id: `settings-tabpanel-${selectedTab?.id ?? "general"}`, role: "tabpanel", "aria-labelledby": `settings-tab-${selectedTab?.id ?? "general"}`, className: cn("min-h-0 min-w-0 flex-1 overflow-y-auto p-4 sm:p-6", contentClassName), children: selectedTab?.content })] }));
|
|
373
|
+
})] }) }, group.id))) }))] }), _jsx("div", { id: `settings-tabpanel-${selectedTab?.id ?? "general"}`, role: "tabpanel", "aria-labelledby": `settings-tab-${selectedTab?.id ?? "general"}`, className: cn("min-h-0 min-w-0 flex-1 overflow-y-auto p-4 sm:p-8 lg:p-10", contentClassName), children: selectedTab?.content })] }));
|
|
352
374
|
}
|
|
353
375
|
//# sourceMappingURL=SettingsTabsPage.js.map
|
|
@@ -10,5 +10,7 @@
|
|
|
10
10
|
* mirrors the server transcription route's key/env resolution.
|
|
11
11
|
*/
|
|
12
12
|
import React from "react";
|
|
13
|
-
export declare function VoiceTranscriptionSection(
|
|
13
|
+
export declare function VoiceTranscriptionSection({ compact, }?: {
|
|
14
|
+
compact?: boolean;
|
|
15
|
+
}): React.JSX.Element;
|
|
14
16
|
//# sourceMappingURL=VoiceTranscriptionSection.d.ts.map
|
|
@@ -10,10 +10,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
* Provider status comes from `/_agent-native/voice-providers/status`, which
|
|
11
11
|
* mirrors the server transcription route's key/env resolution.
|
|
12
12
|
*/
|
|
13
|
-
import { Switch } from "@agent-native/toolkit/design-system";
|
|
13
|
+
import { Picker, Switch } from "@agent-native/toolkit/design-system";
|
|
14
14
|
import { IconAlertCircle, IconCheck, IconChevronDown, IconChevronRight, IconExternalLink, IconLoader2, IconLockOpen, } from "@tabler/icons-react";
|
|
15
15
|
import { useCallback, useEffect, useState } from "react";
|
|
16
16
|
import { agentNativePath } from "../api-path.js";
|
|
17
|
+
import { SettingsRow } from "./SettingsRow.js";
|
|
17
18
|
import { openBuilderConnectPopup, useBuilderStatus, } from "./useBuilderStatus.js";
|
|
18
19
|
const PREFS_URL = agentNativePath("/_agent-native/application-state/voice-transcription-prefs");
|
|
19
20
|
const CLEANUP_PREFS_URL = agentNativePath("/_agent-native/application-state/voice-cleanup-prefs");
|
|
@@ -58,7 +59,7 @@ function batchProvider(provider) {
|
|
|
58
59
|
return DEFAULT_BATCH_PROVIDER;
|
|
59
60
|
return provider;
|
|
60
61
|
}
|
|
61
|
-
export function VoiceTranscriptionSection() {
|
|
62
|
+
export function VoiceTranscriptionSection({ compact = false, } = {}) {
|
|
62
63
|
const [transcriptionMode, setTranscriptionMode] = useState(null);
|
|
63
64
|
const [provider, setProvider] = useState(DEFAULT_BATCH_PROVIDER);
|
|
64
65
|
const [instructions, setInstructions] = useState("");
|
|
@@ -267,14 +268,25 @@ export function VoiceTranscriptionSection() {
|
|
|
267
268
|
if (transcriptionMode === null) {
|
|
268
269
|
return (_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), "Loading\u2026"] }));
|
|
269
270
|
}
|
|
271
|
+
if (compact) {
|
|
272
|
+
return (_jsx(SettingsRow, { label: "Voice transcription", description: "Choose how voice input is transcribed.", control: _jsx(Picker, { mode: "select", options: [
|
|
273
|
+
{ value: "mac-native", label: "Mac Native" },
|
|
274
|
+
{ value: "google-realtime", label: "Google Realtime" },
|
|
275
|
+
{ value: "batch", label: "Batch" },
|
|
276
|
+
], value: transcriptionMode, onChange: (next) => {
|
|
277
|
+
const value = String(next ?? "");
|
|
278
|
+
if (isTranscriptionMode(value))
|
|
279
|
+
chooseSource(value);
|
|
280
|
+
}, "aria-label": "Voice transcription", className: "w-44 text-start" }) }));
|
|
281
|
+
}
|
|
270
282
|
return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "rounded-md border border-border bg-background p-2", children: [_jsx("div", { className: "mb-2 flex items-start justify-between gap-3 px-0.5", children: _jsxs("div", { children: [_jsx("div", { className: "text-[11px] font-medium text-foreground", children: "Live transcription" }), _jsx("p", { className: "mt-0.5 text-[10px] text-muted-foreground", children: "Choose where real-time words come from. Batch still runs after recording stops." })] }) }), _jsxs("div", { className: "space-y-2", children: [_jsx(ProviderOption, { id: "mac-native", selected: transcriptionMode === "mac-native", onSelect: () => chooseSource("mac-native"), title: "Mac Native", subtitle: "Free and fast in the macOS Tauri app. Web clients use the existing browser-native path when available.", rightSlot: _jsx("span", { className: "text-[10px] text-muted-foreground", children: "Tauri default" }) }), _jsx(ProviderOption, { id: "google-realtime", selected: transcriptionMode === "google-realtime", onSelect: () => chooseSource("google-realtime"), disabled: !googleRealtimeReady, title: "Google Realtime", subtitle: googleRealtimeReady
|
|
271
283
|
? "BYOK only for v1. Streams live partials and finals through Google Speech-to-Text."
|
|
272
284
|
: googleRealtimeConfigured
|
|
273
285
|
? "Google credentials are set. Connect Builder completely to mint the managed realtime session."
|
|
274
|
-
: "BYOK only for v1. Configure Google service account before selecting this source.", rightSlot: googleRealtimeReady ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Ready"] })) : googleRealtimeConfigured ? (
|
|
286
|
+
: "BYOK only for v1. Configure Google service account before selecting this source.", rightSlot: googleRealtimeReady ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Ready"] })) : googleRealtimeConfigured ? (_jsx("button", { type: "button", onClick: (e) => {
|
|
275
287
|
e.stopPropagation();
|
|
276
288
|
openBuilderConnect();
|
|
277
|
-
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground", children:
|
|
289
|
+
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground", children: "Connect Builder.io" })) : (_jsxs("button", { type: "button", onClick: (e) => {
|
|
278
290
|
e.stopPropagation();
|
|
279
291
|
setShowAdvanced(true);
|
|
280
292
|
focusKey("GOOGLE_APPLICATION_CREDENTIALS");
|
|
@@ -285,18 +297,18 @@ export function VoiceTranscriptionSection() {
|
|
|
285
297
|
: "Needs key" }))] })] }), _jsxs("div", { className: "rounded-md border border-border bg-background", children: [_jsxs("button", { type: "button", onClick: () => setShowAdvanced((v) => !v), className: "w-full flex items-center justify-between gap-2 px-2.5 py-2 cursor-pointer", children: [_jsxs("span", { className: "text-[11px] font-medium text-foreground inline-flex items-center gap-1", children: [showAdvanced ? (_jsx(IconChevronDown, { size: 12 })) : (_jsx(IconChevronRight, { size: 12, className: "rtl:-scale-x-100" })), "Add API keys"] }), _jsx("span", { className: "text-[10px] text-muted-foreground", children: "Google STT \u00B7 Gemini \u00B7 Groq \u00B7 OpenAI" })] }), showAdvanced && (_jsxs("div", { className: "px-2 pb-2 space-y-2", children: [_jsx(ProviderOption, { id: "google-service-account", selected: transcriptionMode === "google-realtime", onSelect: () => chooseSource("google-realtime"), disabled: !googleRealtimeReady, title: "Google Speech-to-Text service account", subtitle: googleRealtimeConfigured
|
|
286
298
|
? "Service-account JSON is set. Connect Builder to mint the managed realtime WebSocket session."
|
|
287
299
|
: "Service-account JSON for the dedicated realtime WebSocket to Google StreamingRecognize.", rightSlot: googleRealtimeConfigured ===
|
|
288
|
-
null ? null : googleRealtimeReady ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Ready"] })) : googleRealtimeConfigured ? (
|
|
300
|
+
null ? null : googleRealtimeReady ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Ready"] })) : googleRealtimeConfigured ? (_jsx("button", { type: "button", onClick: (e) => {
|
|
289
301
|
e.stopPropagation();
|
|
290
302
|
openBuilderConnect();
|
|
291
|
-
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children:
|
|
303
|
+
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children: "Connect Builder.io" })) : (_jsxs("button", { type: "button", onClick: (e) => {
|
|
292
304
|
e.stopPropagation();
|
|
293
305
|
focusKey("GOOGLE_APPLICATION_CREDENTIALS");
|
|
294
306
|
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children: ["Configure", _jsx(IconExternalLink, { size: 10 })] })) }), _jsx(ProviderOption, { id: "auto", selected: transcriptionMode === "batch" && provider === "auto", onSelect: () => chooseBatchProvider("auto"), title: "Automatic batch fallback", subtitle: "Keep the current Clips fallback chain: Builder Gemini, Gemini, Groq, then OpenAI." }), _jsx(ProviderOption, { id: "builder-gemini", selected: transcriptionMode === "batch" && provider === "builder-gemini", onSelect: () => chooseBatchProvider("builder-gemini"), disabled: !builderStatus?.configured, title: "Builder.io Connect", subtitle: builderStatus?.configured
|
|
295
307
|
? "Use Builder-hosted Gemini Flash-Lite for batch transcription and Luna for text cleanup."
|
|
296
|
-
: "One-click connect for Gemini Flash-Lite transcription and Luna text cleanup. No Google key needed.", rightSlot: builderStatus?.configured ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Connected"] })) : (
|
|
308
|
+
: "One-click connect for Gemini Flash-Lite transcription and Luna text cleanup. No Google key needed.", rightSlot: builderStatus?.configured ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Connected"] })) : (_jsx("button", { type: "button", onClick: (e) => {
|
|
297
309
|
e.stopPropagation();
|
|
298
310
|
openBuilderConnect();
|
|
299
|
-
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children:
|
|
311
|
+
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children: "Connect Builder.io" })) }), _jsx(ProviderOption, { id: "gemini", selected: transcriptionMode === "batch" && provider === "gemini", onSelect: () => chooseBatchProvider("gemini"), title: "Google Gemini", subtitle: "BYOK Gemini for AI cleanup and optional strict batch transcription.", rightSlot: geminiConfigured === null ? null : geminiConfigured ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Key set"] })) : (_jsxs("button", { type: "button", onClick: (e) => {
|
|
300
312
|
e.stopPropagation();
|
|
301
313
|
focusKey("GEMINI_API_KEY");
|
|
302
314
|
}, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40", children: ["Add key", _jsx(IconExternalLink, { size: 10 })] })) }), _jsx(ProviderOption, { id: "openai", selected: transcriptionMode === "batch" && provider === "openai", onSelect: () => chooseBatchProvider("openai"), title: "OpenAI Transcribe", subtitle: "Batch transcription provider. Requires an OpenAI API key.", rightSlot: openAiConfigured === null ? null : openAiConfigured ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Key set"] })) : (_jsxs("button", { type: "button", onClick: (e) => {
|
|
@@ -3,7 +3,7 @@ export type SettingsSectionId = "account" | "llm" | "app-models" | "limits" | "v
|
|
|
3
3
|
export declare const SETTINGS_SECTION_IDS: Set<SettingsSectionId>;
|
|
4
4
|
export declare const ALL_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
5
5
|
export declare const AGENT_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const INTEGRATION_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
7
7
|
export declare const WORKSPACE_SETTINGS_SECTIONS: readonly SettingsSectionId[];
|
|
8
8
|
export declare function buildSectionSearchEntries(sections: readonly SettingsSectionId[]): SettingsSearchEntry[];
|
|
9
9
|
export interface AgentSettingsSearchTab {
|
|
@@ -46,9 +46,9 @@ export const AGENT_SETTINGS_SECTIONS = [
|
|
|
46
46
|
"background",
|
|
47
47
|
"a2a",
|
|
48
48
|
];
|
|
49
|
-
export const
|
|
50
|
-
"secrets",
|
|
49
|
+
export const INTEGRATION_SETTINGS_SECTIONS = [
|
|
51
50
|
"integrations",
|
|
51
|
+
"secrets",
|
|
52
52
|
"email",
|
|
53
53
|
"browser",
|
|
54
54
|
"usage",
|
|
@@ -90,7 +90,7 @@ const SETTINGS_SECTION_SEARCH_META = {
|
|
|
90
90
|
keywords: "triggers scheduled events cron jobs",
|
|
91
91
|
},
|
|
92
92
|
secrets: {
|
|
93
|
-
label: "API
|
|
93
|
+
label: "API keys",
|
|
94
94
|
keywords: "secrets credentials tokens api keys environment variables",
|
|
95
95
|
},
|
|
96
96
|
hosting: {
|
|
@@ -150,15 +150,15 @@ export function getAgentSettingsSearchTabs() {
|
|
|
150
150
|
return [
|
|
151
151
|
{
|
|
152
152
|
id: "agent",
|
|
153
|
-
label: "
|
|
153
|
+
label: "Agent",
|
|
154
154
|
keywords: "agent workspace manage agent model llm limits voice automations",
|
|
155
155
|
searchEntries: buildSectionSearchEntries(AGENT_SETTINGS_SECTIONS),
|
|
156
156
|
},
|
|
157
157
|
{
|
|
158
|
-
id: "
|
|
159
|
-
label: "
|
|
160
|
-
keywords: "connections secrets
|
|
161
|
-
searchEntries: buildSectionSearchEntries(
|
|
158
|
+
id: "integrations",
|
|
159
|
+
label: "Integrations",
|
|
160
|
+
keywords: "integrations agent integrations connections secrets email browser usage tools",
|
|
161
|
+
searchEntries: buildSectionSearchEntries(INTEGRATION_SETTINGS_SECTIONS),
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
id: "organization",
|
|
@@ -6,7 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
*
|
|
7
7
|
* Drop this next to transcript displays in any template.
|
|
8
8
|
*/
|
|
9
|
-
import { IconBolt,
|
|
9
|
+
import { IconBolt, IconLoader2 } from "@tabler/icons-react";
|
|
10
10
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
11
|
import { agentNativePath } from "../api-path.js";
|
|
12
12
|
import { openBuilderConnectPopup } from "../settings/useBuilderStatus.js";
|
|
@@ -82,6 +82,6 @@ export function BuilderTranscriptionCta() {
|
|
|
82
82
|
return null;
|
|
83
83
|
return (_jsxs("div", { className: "flex items-center gap-2 rounded-md border border-border/50 bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: [_jsx(IconBolt, { size: 14, className: "shrink-0 text-muted-foreground/70", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: connecting
|
|
84
84
|
? "Waiting for Builder.io…"
|
|
85
|
-
: "Connect Builder.io for higher-quality transcription — free credits, no API key needed." }), error ? (_jsx("span", { className: "text-destructive text-[10px]", children: error })) : connecting ? (_jsx(IconLoader2, { size: 12, className: "shrink-0 animate-spin" })) : (
|
|
85
|
+
: "Connect Builder.io for higher-quality transcription — free credits, no API key needed." }), error ? (_jsx("span", { className: "text-destructive text-[10px]", children: error })) : connecting ? (_jsx(IconLoader2, { size: 12, className: "shrink-0 animate-spin" })) : (_jsx("button", { type: "button", onClick: handleConnect, className: "ml-auto shrink-0 inline-flex items-center gap-1 rounded bg-foreground px-2 py-1 text-[10px] font-semibold text-background hover:opacity-90 transition-opacity", children: "Connect" }))] }));
|
|
86
86
|
}
|
|
87
87
|
//# sourceMappingURL=BuilderTranscriptionCta.js.map
|
|
@@ -13,9 +13,15 @@ export interface ChatThreadSummary {
|
|
|
13
13
|
createdAt: number;
|
|
14
14
|
updatedAt: number;
|
|
15
15
|
scope: ChatThreadScope | null;
|
|
16
|
+
source?: ChatThreadSource | null;
|
|
16
17
|
pinnedAt?: number | null;
|
|
17
18
|
archivedAt?: number | null;
|
|
18
19
|
}
|
|
20
|
+
export interface ChatThreadSource {
|
|
21
|
+
platform?: string;
|
|
22
|
+
appId?: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
}
|
|
19
25
|
export interface ChatThreadData {
|
|
20
26
|
id: string;
|
|
21
27
|
ownerEmail: string;
|
|
@@ -26,6 +32,7 @@ export interface ChatThreadData {
|
|
|
26
32
|
createdAt: number;
|
|
27
33
|
updatedAt: number;
|
|
28
34
|
scope: ChatThreadScope | null;
|
|
35
|
+
source?: ChatThreadSource | null;
|
|
29
36
|
pinnedAt?: number | null;
|
|
30
37
|
archivedAt?: number | null;
|
|
31
38
|
}
|
|
@@ -57,6 +64,8 @@ export interface UseChatThreadsOptions {
|
|
|
57
64
|
* create/new-chat mode.
|
|
58
65
|
*/
|
|
59
66
|
routeThreadId?: string | null;
|
|
67
|
+
/** Include connected and other-app chats in list/search results. */
|
|
68
|
+
includeExternal?: boolean;
|
|
60
69
|
}
|
|
61
70
|
export declare function useChatThreads(apiUrl?: string, storageKey?: string, scope?: ChatThreadScope | null, options?: UseChatThreadsOptions): {
|
|
62
71
|
threads: ChatThreadSummary[];
|
|
@@ -3,8 +3,14 @@ import { agentNativePath } from "./api-path.js";
|
|
|
3
3
|
const ACTIVE_THREAD_KEY = "agent-chat-active-thread";
|
|
4
4
|
const THREADS_UPDATED_EVENT = "agent-chat:threads-updated";
|
|
5
5
|
const THREADS_PAGE_SIZE = 50;
|
|
6
|
-
async function fetchThreadListPage(apiUrl, offset) {
|
|
7
|
-
|
|
6
|
+
async function fetchThreadListPage(apiUrl, offset, includeExternal) {
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
if (offset > 0)
|
|
9
|
+
params.set("offset", String(offset));
|
|
10
|
+
if (includeExternal)
|
|
11
|
+
params.set("includeExternal", "1");
|
|
12
|
+
const query = params.toString();
|
|
13
|
+
return fetch(`${apiUrl}/threads${query ? `?${query}` : ""}`).then(async (res) => {
|
|
8
14
|
if (!res.ok)
|
|
9
15
|
return undefined;
|
|
10
16
|
const data = await res.json();
|
|
@@ -102,6 +108,7 @@ function nextThreadTitle(currentTitle, incomingTitle, incomingPreview, source =
|
|
|
102
108
|
export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-chat"), storageKey, scope, options) {
|
|
103
109
|
const autoCreate = options?.autoCreate !== false;
|
|
104
110
|
const restoreActiveThread = options?.restoreActiveThread !== false;
|
|
111
|
+
const includeExternal = options?.includeExternal === true;
|
|
105
112
|
const routeControlsActiveThread = options?.routeThreadId !== undefined;
|
|
106
113
|
const routeThreadId = normalizeThreadId(options?.routeThreadId);
|
|
107
114
|
// Each (storageKey, scope) pair gets its own active-thread localStorage key
|
|
@@ -148,6 +155,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
148
155
|
const [isLoadingMoreThreads, setIsLoadingMoreThreads] = useState(false);
|
|
149
156
|
const [threadsLoadError, setThreadsLoadError] = useState(null);
|
|
150
157
|
const nextThreadsOffsetRef = useRef(0);
|
|
158
|
+
const latestFetchRequestRef = useRef(0);
|
|
151
159
|
const threadsRef = useRef(threads);
|
|
152
160
|
threadsRef.current = threads;
|
|
153
161
|
// IDs we generated client-side this session — consumers use this to know
|
|
@@ -341,9 +349,12 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
341
349
|
threads,
|
|
342
350
|
]);
|
|
343
351
|
const fetchThreads = useCallback(async (options) => {
|
|
352
|
+
const requestId = ++latestFetchRequestRef.current;
|
|
344
353
|
try {
|
|
345
354
|
const offset = options?.append ? nextThreadsOffsetRef.current : 0;
|
|
346
|
-
const loaded = await fetchThreadListPage(apiUrl, offset);
|
|
355
|
+
const loaded = await fetchThreadListPage(apiUrl, offset, includeExternal);
|
|
356
|
+
if (requestId !== latestFetchRequestRef.current)
|
|
357
|
+
return undefined;
|
|
347
358
|
if (!loaded) {
|
|
348
359
|
if (!options?.append) {
|
|
349
360
|
setThreadsLoadError("Could not load chat history.");
|
|
@@ -426,12 +437,14 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
426
437
|
return loaded;
|
|
427
438
|
}
|
|
428
439
|
catch {
|
|
440
|
+
if (requestId !== latestFetchRequestRef.current)
|
|
441
|
+
return undefined;
|
|
429
442
|
if (!options?.append) {
|
|
430
443
|
setThreadsLoadError("Could not load chat history.");
|
|
431
444
|
}
|
|
432
445
|
return undefined;
|
|
433
446
|
}
|
|
434
|
-
}, [apiUrl]);
|
|
447
|
+
}, [apiUrl, includeExternal]);
|
|
435
448
|
const loadMoreThreads = useCallback(async () => {
|
|
436
449
|
if (isLoadingMoreThreads || !hasMoreThreads)
|
|
437
450
|
return;
|
|
@@ -980,7 +993,10 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
980
993
|
}, [apiUrl]);
|
|
981
994
|
const searchThreads = useCallback(async (query) => {
|
|
982
995
|
try {
|
|
983
|
-
const
|
|
996
|
+
const params = new URLSearchParams({ q: query });
|
|
997
|
+
if (includeExternal)
|
|
998
|
+
params.set("includeExternal", "1");
|
|
999
|
+
const res = await fetch(`${apiUrl}/threads?${params.toString()}`);
|
|
984
1000
|
if (!res.ok)
|
|
985
1001
|
return [];
|
|
986
1002
|
const data = await res.json();
|
|
@@ -989,7 +1005,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
989
1005
|
catch {
|
|
990
1006
|
return [];
|
|
991
1007
|
}
|
|
992
|
-
}, [apiUrl]);
|
|
1008
|
+
}, [apiUrl, includeExternal]);
|
|
993
1009
|
const getThreadShareState = useCallback(async (threadId) => {
|
|
994
1010
|
try {
|
|
995
1011
|
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`);
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -17,12 +17,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
17
17
|
id?: undefined;
|
|
18
18
|
provider?: undefined;
|
|
19
19
|
} | {
|
|
20
|
+
error?: undefined;
|
|
20
21
|
configured?: undefined;
|
|
21
22
|
connectPath?: undefined;
|
|
22
23
|
url: string;
|
|
23
24
|
id: string;
|
|
24
25
|
provider: string;
|
|
25
|
-
error?: undefined;
|
|
26
26
|
}>;
|
|
27
27
|
export default _default;
|
|
28
28
|
//# sourceMappingURL=upload-image.d.ts.map
|
|
@@ -5,7 +5,7 @@ import { runAgentLoopDirectWithSoftTimeout } from "../agent/run-loop-with-resume
|
|
|
5
5
|
import { startRun } from "../agent/run-manager.js";
|
|
6
6
|
import { buildAssistantMessage, extractThreadMeta, } from "../agent/thread-data-builder.js";
|
|
7
7
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
8
|
-
import { createThread, getThread, updateThreadData, } from "../chat-threads/store.js";
|
|
8
|
+
import { createThread, getThread, setThreadSourceIfMissing, updateThreadData, } from "../chat-threads/store.js";
|
|
9
9
|
import { resolveOrgIdForEmail } from "../org/context.js";
|
|
10
10
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
11
11
|
import { getServiceAccountAccessToken, getServiceAccountEmail, getStartPageToken, googleDocsAdapter, listChanges, listDocComments, } from "./adapters/google-docs.js";
|
|
@@ -274,14 +274,22 @@ async function processComment(fileId, commentId, text, senderName, options, exis
|
|
|
274
274
|
platformContext: { fileId, commentId },
|
|
275
275
|
timestamp: Date.now(),
|
|
276
276
|
};
|
|
277
|
+
const source = {
|
|
278
|
+
platform: PLATFORM,
|
|
279
|
+
url: `https://docs.google.com/document/d/${fileId}/edit`,
|
|
280
|
+
};
|
|
277
281
|
let threadId = existingThreadId;
|
|
278
282
|
if (!threadId) {
|
|
279
283
|
const thread = await createThread(options.ownerEmail, {
|
|
280
284
|
title: `Google Doc: ${senderName}`,
|
|
285
|
+
source,
|
|
281
286
|
});
|
|
282
287
|
await saveThreadMapping(PLATFORM, key, thread.id, { fileId, commentId });
|
|
283
288
|
threadId = thread.id;
|
|
284
289
|
}
|
|
290
|
+
// Older mapped conversations predate thread provenance. Backfill them as
|
|
291
|
+
// they are touched so Dispatch's default local-history view excludes them.
|
|
292
|
+
await setThreadSourceIfMissing(threadId, source);
|
|
285
293
|
const thread = await getThread(threadId);
|
|
286
294
|
const existingMessages = [];
|
|
287
295
|
if (thread?.threadData) {
|
|
@@ -11,7 +11,7 @@ import { startRun, } from "../agent/run-manager.js";
|
|
|
11
11
|
import { buildCurrentTimeUserContext, buildRuntimeContextPrompt, } from "../agent/runtime-context.js";
|
|
12
12
|
import { buildAssistantMessage, extractThreadMeta, threadDataToEngineMessages, } from "../agent/thread-data-builder.js";
|
|
13
13
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
14
|
-
import { createThread, getThread, grantThreadUserShare, } from "../chat-threads/store.js";
|
|
14
|
+
import { createThread, getThread, grantThreadUserShare, setThreadSourceIfMissing, } from "../chat-threads/store.js";
|
|
15
15
|
import { updateThreadData } from "../chat-threads/store.js";
|
|
16
16
|
import { isLocalDatabase } from "../db/client.js";
|
|
17
17
|
import { getOrgA2ASecret, resolveOrgIdForEmail } from "../org/context.js";
|
|
@@ -575,6 +575,11 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
575
575
|
const threadOrgId = opts.orgId ?? (await resolveOrgIdForEmail(ownerEmail));
|
|
576
576
|
const createdThread = await runWithRequestContext({ userEmail: ownerEmail, orgId: threadOrgId ?? undefined }, () => createThread(ownerEmail, {
|
|
577
577
|
title: `${adapter.label}: ${incoming.senderName || incoming.senderId || "User"}`,
|
|
578
|
+
source: {
|
|
579
|
+
platform: incoming.platform,
|
|
580
|
+
appId: options.appId ?? null,
|
|
581
|
+
url: incoming.sourceUrl ?? null,
|
|
582
|
+
},
|
|
578
583
|
}));
|
|
579
584
|
await saveThreadMapping(incoming.platform, incoming.externalThreadId, createdThread.id, incoming.platformContext);
|
|
580
585
|
mapping = {
|
|
@@ -587,6 +592,11 @@ async function processIncomingMessage(incoming, options, opts = {}) {
|
|
|
587
592
|
};
|
|
588
593
|
}
|
|
589
594
|
threadId = mapping.internalThreadId;
|
|
595
|
+
await setThreadSourceIfMissing(threadId, {
|
|
596
|
+
platform: incoming.platform,
|
|
597
|
+
appId: options.appId ?? null,
|
|
598
|
+
url: incoming.sourceUrl ?? null,
|
|
599
|
+
});
|
|
590
600
|
// Load existing thread history for context.
|
|
591
601
|
thread = await getThread(threadId);
|
|
592
602
|
}
|
package/dist/jobs/scheduler.d.ts
CHANGED
|
@@ -23,7 +23,10 @@ export interface SchedulerDeps extends BackgroundAutomationDeps {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Process all due recurring jobs. Called every 60 seconds.
|
|
26
|
-
*
|
|
26
|
+
*
|
|
27
|
+
* Scans may overlap while a long-running job is executing. Each resource is
|
|
28
|
+
* still protected by its persisted running state and a process-local key, so
|
|
29
|
+
* one job cannot run twice while leaving other due jobs waiting behind it.
|
|
27
30
|
*/
|
|
28
31
|
export declare function processRecurringJobs(deps: SchedulerDeps): Promise<void>;
|
|
29
32
|
export declare const jobRunCutOffReason: typeof backgroundRunCutOffReason;
|