@agent-native/core 0.155.0 → 0.157.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +19 -4
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +7 -2
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/global.css +4 -0
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +18 -15
- package/corpus/templates/brain/app/routes/sources.tsx +1 -2
- package/corpus/templates/calendar/app/hooks/use-bookings.ts +12 -2
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +64 -2
- package/corpus/templates/calendar/server/handlers/bookings.ts +219 -93
- package/corpus/templates/calendar/server/plugins/auth.ts +0 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -1
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-recording.ts +5 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +97 -65
- package/corpus/templates/clips/actions/import-loom-recording.ts +5 -3
- package/corpus/templates/clips/actions/request-recording-access.ts +272 -0
- package/corpus/templates/clips/actions/stitch-recordings.ts +5 -3
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +38 -63
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +177 -134
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -21
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +13 -30
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +24 -17
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +151 -20
- package/corpus/templates/clips/changelog/2026-08-14-long-resumable-uploads-now-abort-cleanly-and-show-errors.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-14-standardized-share-popovers.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +11 -3
- package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +37 -8
- package/corpus/templates/clips/chrome-extension/src/github-preview.ts +3 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -25
- package/corpus/templates/clips/desktop/src/app.tsx +24 -0
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +42 -13
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +11 -18
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +1 -0
- package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
- package/corpus/templates/clips/desktop/src/styles.css +24 -9
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +154 -176
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +115 -31
- package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +7 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +6 -1
- package/corpus/templates/clips/server/lib/emails.ts +23 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +55 -0
- package/corpus/templates/clips/server/lib/recordings.ts +2 -1
- package/corpus/templates/clips/server/lib/resumable-upload-cleanup.ts +49 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +34 -7
- package/corpus/templates/clips/server/lib/upload-interruption.ts +15 -1
- package/corpus/templates/clips/server/lib/upload-lease.ts +94 -9
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +82 -7
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +71 -12
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -3
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +19 -0
- package/corpus/templates/clips/server/routes/api/uploads/reap.post.ts +8 -1
- package/corpus/templates/clips/shared/recording-link.ts +4 -0
- package/corpus/templates/clips/shared/share-loader-response.ts +2 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +7 -16
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +6 -2
- package/corpus/templates/factory/actions/view-screen.ts +15 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +58 -189
- package/corpus/templates/factory/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +7 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +3 -1
- package/corpus/templates/factory/app/routes/agents.tsx +9 -0
- package/corpus/templates/mail/server/plugins/auth.ts +0 -2
- package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +50 -14
- package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -19
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +7 -1
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +108 -19
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/editor-shortcuts.ts +46 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +143 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +100 -8
- package/dist/agent/types.d.ts +9 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +22 -17
- package/dist/client/AssistantChat.d.ts +15 -1
- package/dist/client/AssistantChat.js +135 -48
- package/dist/client/HighlightedCodeBlock.js +12 -2
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/chat/markdown-renderer.js +20 -5
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +1 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/settings/AccountSettingsCard.js +48 -19
- package/dist/client/sharing/ShareButton.d.ts +1 -2
- package/dist/client/sharing/ShareButton.js +151 -81
- package/dist/client/sharing/ShareDialog.js +5 -4
- package/dist/client/use-chat-threads.js +10 -14
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +0 -2
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +18 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/onboarding-html.d.ts +1 -0
- package/dist/server/onboarding-html.js +2 -88
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/shared/markdown-block-split.d.ts +16 -0
- package/dist/shared/markdown-block-split.js +81 -5
- package/dist/styles/agent-native.css +13 -0
- package/dist/voice/voice-cleanup-prompt.js +1 -0
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +2 -2
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +0 -350
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ShareCopyRow, ShareTrigger } from "@agent-native/toolkit/sharing";
|
|
2
3
|
import * as Select from "@radix-ui/react-select";
|
|
3
|
-
import { IconLock, IconWorld, IconTrash, IconCheck, IconChevronDown, IconLoader2,
|
|
4
|
+
import { IconLock, IconWorld, IconTrash, IconCheck, IconChevronDown, IconLoader2, IconSearch, IconSearchOff, IconUsersGroup, } from "@tabler/icons-react";
|
|
4
5
|
import { useEffect, useId, useRef, useState, } from "react";
|
|
5
6
|
import { writeClipboardText } from "../clipboard.js";
|
|
6
7
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
8
|
+
import { useT } from "../i18n.js";
|
|
7
9
|
import { cn } from "../utils.js";
|
|
8
10
|
import { useShareButtonController, } from "./useShareButtonController.js";
|
|
9
11
|
// Match shadcn's <Button size="sm" variant="outline"> sizing so the trigger
|
|
10
12
|
// sits flush next to other controls while staying transparent at rest.
|
|
11
13
|
const BUTTON_BASE = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0";
|
|
12
|
-
const BUTTON_OUTLINE_SM = cn(BUTTON_BASE, "h-9 px-3 border border-[hsl(var(--sidebar-border,var(--input)))] bg-transparent text-foreground hover:bg-[hsl(var(--sidebar-accent,var(--accent)))] hover:text-[hsl(var(--sidebar-accent-foreground,var(--accent-foreground)))]");
|
|
13
14
|
const BUTTON_PRIMARY_SM = cn(BUTTON_BASE, "h-9 px-4 bg-primary text-primary-foreground hover:bg-primary/90");
|
|
14
15
|
const BUTTON_GHOST_ICON = cn(BUTTON_BASE, "h-7 w-7 p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground");
|
|
15
16
|
const SHARE_POPOVER_SURFACE = "border border-border bg-popover text-popover-foreground";
|
|
@@ -17,46 +18,77 @@ const SHARE_NESTED_OVERLAY_ATTR = "data-agent-native-share-overlay";
|
|
|
17
18
|
const SHARE_NESTED_OVERLAY_Z = "z-[100020]";
|
|
18
19
|
const VIS_META = {
|
|
19
20
|
private: {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
labelKey: "agentChat.share.private",
|
|
22
|
+
descriptionKey: "agentChat.share.privateDescription",
|
|
23
|
+
defaultLabel: "Private",
|
|
24
|
+
defaultDescription: "Only people with access can view",
|
|
22
25
|
Icon: IconLock,
|
|
23
26
|
},
|
|
24
27
|
org: {
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
labelKey: "agentChat.share.organization",
|
|
29
|
+
descriptionKey: "agentChat.share.organizationDescription",
|
|
30
|
+
defaultLabel: "Organization",
|
|
31
|
+
defaultDescription: "Anyone in your organization can view",
|
|
27
32
|
Icon: IconUsersGroup,
|
|
28
33
|
},
|
|
29
34
|
public: {
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
labelKey: "agentChat.share.public",
|
|
36
|
+
descriptionKey: "agentChat.share.publicDescription",
|
|
37
|
+
defaultLabel: "Public",
|
|
38
|
+
defaultDescription: "Anyone with the link can view",
|
|
32
39
|
Icon: IconWorld,
|
|
33
40
|
},
|
|
34
41
|
};
|
|
35
|
-
function visibilityMeta(visibility, copy) {
|
|
42
|
+
function visibilityMeta(visibility, t, copy) {
|
|
36
43
|
const base = VIS_META[visibility];
|
|
37
44
|
const override = copy?.[visibility];
|
|
38
45
|
return {
|
|
39
|
-
|
|
40
|
-
label: override?.label ??
|
|
41
|
-
|
|
46
|
+
Icon: base.Icon,
|
|
47
|
+
label: override?.label ??
|
|
48
|
+
t(base.labelKey, {
|
|
49
|
+
defaultValue: base.defaultLabel,
|
|
50
|
+
}),
|
|
51
|
+
description: override?.description ??
|
|
52
|
+
t(base.descriptionKey, {
|
|
53
|
+
defaultValue: base.defaultDescription,
|
|
54
|
+
}),
|
|
42
55
|
};
|
|
43
56
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
function roleOptions(t) {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
value: "viewer",
|
|
61
|
+
label: t("agentChat.share.viewer", { defaultValue: "Viewer" }),
|
|
62
|
+
description: t("agentChat.share.viewerDescription", {
|
|
63
|
+
defaultValue: "Can view",
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
value: "commenter",
|
|
68
|
+
label: t("agentChat.share.commenter", { defaultValue: "Commenter" }),
|
|
69
|
+
description: t("agentChat.share.commenterDescription", {
|
|
70
|
+
defaultValue: "Can view and add comments",
|
|
71
|
+
}),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
value: "editor",
|
|
75
|
+
label: t("agentChat.share.editor", { defaultValue: "Editor" }),
|
|
76
|
+
description: t("agentChat.share.editorDescription", {
|
|
77
|
+
defaultValue: "Can edit",
|
|
78
|
+
}),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
value: "admin",
|
|
82
|
+
label: t("agentChat.share.admin", { defaultValue: "Admin" }),
|
|
83
|
+
description: t("agentChat.share.adminDescription", {
|
|
84
|
+
defaultValue: "Can edit and manage access",
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
function roleMeta(role, t, copy) {
|
|
90
|
+
const options = roleOptions(t);
|
|
91
|
+
const base = options.find((option) => option.value === role) ?? options[0];
|
|
60
92
|
const override = copy?.[role];
|
|
61
93
|
return {
|
|
62
94
|
...base,
|
|
@@ -81,6 +113,7 @@ function handleSharePopoverInteractOutside(event) {
|
|
|
81
113
|
* dark mode in any shadcn template.
|
|
82
114
|
*/
|
|
83
115
|
export function ShareButton(props) {
|
|
116
|
+
const t = useT();
|
|
84
117
|
const controller = useShareButtonController({
|
|
85
118
|
resourceType: props.resourceType,
|
|
86
119
|
resourceId: props.resourceId,
|
|
@@ -91,24 +124,22 @@ export function ShareButton(props) {
|
|
|
91
124
|
allowedRoles: props.allowedRoles,
|
|
92
125
|
hideInSearchControl: props.hideInSearchControl,
|
|
93
126
|
});
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
? visibilityMeta(triggerVisibility, props.visibilityCopy)
|
|
97
|
-
: null;
|
|
98
|
-
const TriggerIcon = triggerMeta?.Icon ?? IconShare3;
|
|
99
|
-
const iconOnly = props.trigger === "icon";
|
|
100
|
-
const showTriggerIcon = iconOnly || props.trigger === "label-icon";
|
|
101
|
-
const triggerLabel = iconOnly && triggerMeta ? `Share (${triggerMeta.label})` : "Share";
|
|
102
|
-
return (_jsxs(Popover, { open: controller.open, onOpenChange: controller.handleOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: cn(iconOnly ? BUTTON_GHOST_ICON : BUTTON_OUTLINE_SM, props.triggerClassName), "aria-label": triggerLabel, title: triggerLabel, children: [showTriggerIcon && _jsx(TriggerIcon, { size: 16, strokeWidth: 1.75 }), !iconOnly && _jsx("span", { children: "Share" })] }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, "data-agent-native-share-overlay": "", className: cn("z-[2000] w-[min(460px,92vw)] rounded-lg p-4 shadow-lg", SHARE_POPOVER_SURFACE, props.popoverClassName), onOpenAutoFocus: (e) => e.preventDefault(), onInteractOutside: handleSharePopoverInteractOutside, children: _jsx(SharePanel, { ...props, controller: controller }) })] }));
|
|
127
|
+
const triggerLabel = t("agentChat.share.share", { defaultValue: "Share" });
|
|
128
|
+
return (_jsxs(Popover, { open: controller.open, onOpenChange: controller.handleOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(ShareTrigger, { label: triggerLabel, className: props.triggerClassName, "aria-label": triggerLabel, title: triggerLabel }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, "data-agent-native-share-overlay": "", className: cn("z-[2000] w-[min(460px,92vw)] rounded-lg p-4 shadow-lg", SHARE_POPOVER_SURFACE, props.popoverClassName), onOpenAutoFocus: (e) => e.preventDefault(), onInteractOutside: handleSharePopoverInteractOutside, children: _jsx(SharePanel, { ...props, controller: controller }) })] }));
|
|
103
129
|
}
|
|
104
130
|
function SharePanel(props) {
|
|
131
|
+
const t = useT();
|
|
105
132
|
const { controller } = props;
|
|
106
133
|
const { inviteEmail, setInviteEmail: onInviteEmailChange, activeShareTab, handleShareTabChange, data, policy, visibility, canManage, role, setRole, notifyPeople, setNotifyPeople, shareMessage, setShareMessage, messageOpen, setMessageOpen, shareError, setShareError, suggestionsOpen, setSuggestionsOpen, inFlight, memberSearch, memberSuggestions, knownMembers, shares, handleVisibility, handleHideInSearch, handleAdd, handleChangeRole, handleRemove, } = controller;
|
|
107
134
|
const hasInviteEmail = inviteEmail.trim().length > 0;
|
|
108
135
|
const isLoading = data === undefined;
|
|
109
|
-
const meta = visibilityMeta(visibility, props.visibilityCopy);
|
|
110
|
-
const peopleAccessLabel = props.peopleAccessLabel ??
|
|
111
|
-
|
|
136
|
+
const meta = visibilityMeta(visibility, t, props.visibilityCopy);
|
|
137
|
+
const peopleAccessLabel = props.peopleAccessLabel ??
|
|
138
|
+
t("agentChat.share.peopleWithAccess", {
|
|
139
|
+
defaultValue: "People with access",
|
|
140
|
+
});
|
|
141
|
+
const generalAccessLabel = props.generalAccessLabel ??
|
|
142
|
+
t("agentChat.share.generalAccess", { defaultValue: "General access" });
|
|
112
143
|
const shareLinks = (_jsxs(_Fragment, { children: [props.shareUrl ? (_jsx(CopyLinkField, { value: props.shareUrl, label: props.shareUrlLabel, description: props.shareUrlDescription })) : props.shareUrlPlaceholder ? (_jsxs("div", { className: "mb-4 rounded-md border border-dashed border-border bg-muted/20 px-3 py-2.5 text-xs text-muted-foreground", children: [props.shareUrlLabel ? (_jsx("div", { className: "mb-0.5 font-medium text-foreground", children: props.shareUrlLabel })) : null, props.shareUrlPlaceholder] })) : null, props.secondaryShareUrl ? (_jsx(CopyLinkField, { value: props.secondaryShareUrl, label: props.secondaryShareUrlLabel, description: props.secondaryShareUrlDescription })) : null] }));
|
|
113
144
|
const showShareLinks = (props.showShareLinks ?? true) &&
|
|
114
145
|
(Boolean(props.shareUrl) ||
|
|
@@ -117,7 +148,8 @@ function SharePanel(props) {
|
|
|
117
148
|
const shareUrlPlacement = props.shareUrlPlacement ?? "top";
|
|
118
149
|
const extraTabs = props.shareTabs?.tabs.filter((tab) => tab.value !== "context") ?? [];
|
|
119
150
|
const hasTabs = extraTabs.length > 0;
|
|
120
|
-
const shareTabLabel = props.shareTabs?.shareLabel ??
|
|
151
|
+
const shareTabLabel = props.shareTabs?.shareLabel ??
|
|
152
|
+
t("agentChat.share.shareLink", { defaultValue: "Share link" });
|
|
121
153
|
const sharePanel = isLoading ? (_jsxs("div", { children: [showShareLinks ? (_jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" })) : null, _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsx("div", { className: "mb-4 h-9 rounded-md bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: peopleAccessLabel }), _jsx("div", { className: "mb-4 h-7 rounded-md bg-muted animate-pulse" })] })) : (_jsxs("div", { children: [showShareLinks && shareUrlPlacement === "top" ? shareLinks : null, _jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { className: "sr-only", children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] })] }), _jsxs("div", { className: "mb-4 space-y-4", children: [_jsx("div", { className: "text-sm font-semibold", children: peopleAccessLabel }), canManage ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-stretch gap-2", children: [_jsx(MemberAutocomplete, { value: inviteEmail, open: suggestionsOpen, onOpenChange: setSuggestionsOpen, onValueChange: (next) => {
|
|
122
154
|
onInviteEmailChange(next);
|
|
123
155
|
if (shareError)
|
|
@@ -128,8 +160,28 @@ function SharePanel(props) {
|
|
|
128
160
|
if (shareError)
|
|
129
161
|
setShareError(null);
|
|
130
162
|
}, onSubmit: handleAdd, placeholder: policy.requireOrgMemberForUserShares
|
|
131
|
-
? "
|
|
132
|
-
|
|
163
|
+
? t("agentChat.share.addPeopleOrganization", {
|
|
164
|
+
defaultValue: "Add people from your organization",
|
|
165
|
+
})
|
|
166
|
+
: t("agentChat.share.addPeopleEmail", {
|
|
167
|
+
defaultValue: "Add people by email",
|
|
168
|
+
}), suggestions: memberSuggestions, search: memberSearch }), _jsx(RoleSelect, { value: role, onChange: setRole, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles }), _jsx("button", { type: "button", onClick: handleAdd, disabled: !hasInviteEmail, className: BUTTON_PRIMARY_SM, children: t("agentChat.share.add", { defaultValue: "Add" }) })] }), shareError ? (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, hasInviteEmail ? (_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-2 text-xs text-muted-foreground", children: [_jsxs("label", { className: "inline-flex items-center gap-2", children: [_jsx("input", { type: "checkbox", checked: notifyPeople, onChange: (e) => setNotifyPeople(e.target.checked), className: "h-4 w-4 rounded border-input accent-primary" }), t("agentChat.share.notifyPeople", {
|
|
169
|
+
defaultValue: "Notify people",
|
|
170
|
+
})] }), notifyPeople ? (_jsx("button", { type: "button", "aria-expanded": messageOpen, onClick: () => setMessageOpen(!messageOpen), className: "rounded-sm px-1 py-0.5 font-medium text-foreground underline decoration-border underline-offset-2 transition-colors hover:bg-accent hover:text-accent-foreground", children: messageOpen
|
|
171
|
+
? t("agentChat.share.hideMessage", {
|
|
172
|
+
defaultValue: "Hide message",
|
|
173
|
+
})
|
|
174
|
+
: t("agentChat.share.addMessage", {
|
|
175
|
+
defaultValue: "Add a message",
|
|
176
|
+
}) })) : null] })) : null, hasInviteEmail && notifyPeople && messageOpen ? (_jsx("div", { className: "rounded-md border border-border/70 bg-muted/20 p-2.5", children: _jsx("textarea", { "aria-label": t("agentChat.share.message", {
|
|
177
|
+
defaultValue: "Message",
|
|
178
|
+
}), placeholder: t("agentChat.share.messagePlaceholder", {
|
|
179
|
+
defaultValue: "Add a short note (optional)",
|
|
180
|
+
}), value: shareMessage, onChange: (event) => setShareMessage(event.target.value), maxLength: 500, rows: 3, className: "w-full resize-y rounded-md border border-input bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background" }) })) : null] })) : null, _jsxs("ul", { className: "flex list-none flex-col gap-1 p-0 m-0", children: [data?.ownerEmail ? (_jsxs("li", { className: "flex items-center gap-3 px-1 py-1.5 text-sm", children: [_jsx(Avatar, { label: displayName(data.ownerEmail, knownMembers, t) }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: displayName(data.ownerEmail, knownMembers, t) }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("agentChat.share.owner", { defaultValue: "Owner" }) })] })) : null, shares.map((s) => (_jsxs("li", { className: cn("flex items-center gap-3 px-1 py-1.5 text-sm", inFlight.has(keyOf(s)) && "opacity-60"), children: [_jsx(Avatar, { label: principalLabel(s, knownMembers, t), org: s.principalType === "org" }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: principalLabel(s, knownMembers, t) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true, roleCopy: props.roleCopy, allowedRoles: props.allowedRoles })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: roleMeta(s.role, t, props.roleCopy).label })), canManage ? (_jsx("button", { type: "button", "aria-label": t("agentChat.share.remove", {
|
|
181
|
+
defaultValue: "Remove",
|
|
182
|
+
}), onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: t("agentChat.share.noAccess", {
|
|
183
|
+
defaultValue: "No one has access yet.",
|
|
184
|
+
}) })) : null] })] }), shareError && !canManage ? (_jsx("div", { role: "alert", className: "mb-4 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: shareError })) : null, props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null, props.shareFooterContent] }));
|
|
133
185
|
if (!hasTabs)
|
|
134
186
|
return sharePanel;
|
|
135
187
|
const tabs = [
|
|
@@ -144,17 +196,30 @@ function SharePanel(props) {
|
|
|
144
196
|
const activeTab = tabs.some((tab) => tab.value === activeShareTab)
|
|
145
197
|
? activeShareTab
|
|
146
198
|
: "share";
|
|
147
|
-
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("div", { role: "tablist", "aria-label": "
|
|
199
|
+
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("div", { role: "tablist", "aria-label": t("agentChat.share.shareOptions", {
|
|
200
|
+
defaultValue: "Share options",
|
|
201
|
+
}), className: "flex gap-1 rounded-xl bg-muted/70 p-1", children: tabs.map((tab) => {
|
|
148
202
|
const active = tab.value === activeTab;
|
|
149
203
|
return (_jsx("button", { type: "button", role: "tab", "aria-selected": active, disabled: tab.disabled, onClick: () => handleShareTabChange(tab.value), className: cn("h-11 min-w-0 flex-1 rounded-lg px-3 text-sm font-medium text-muted-foreground transition-colors hover:bg-background/70 hover:text-foreground disabled:pointer-events-none disabled:opacity-50", active &&
|
|
150
204
|
"bg-background text-foreground shadow-sm ring-2 ring-primary"), children: _jsx("span", { className: "block truncate", children: tab.label }) }, tab.value));
|
|
151
205
|
}) }), _jsx("div", { role: "tabpanel", children: tabs.find((tab) => tab.value === activeTab)?.content })] }));
|
|
152
206
|
}
|
|
153
207
|
function AdvancedAccessPopover({ control, canManage, onToggle, }) {
|
|
154
|
-
|
|
155
|
-
|
|
208
|
+
const t = useT();
|
|
209
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: !canManage, className: "inline-flex items-center gap-1 rounded-sm px-1 py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", children: [t("agentChat.share.advanced", { defaultValue: "Advanced" }), _jsx(IconChevronDown, { size: 12, strokeWidth: 1.8 })] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 6, "data-agent-native-share-overlay": "", onOpenAutoFocus: (event) => event.preventDefault(), className: cn(SHARE_NESTED_OVERLAY_Z, "w-72 p-3 shadow-lg", SHARE_POPOVER_SURFACE), children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: t("agentChat.share.advancedAccess", {
|
|
210
|
+
defaultValue: "Advanced access",
|
|
211
|
+
}) }), _jsx("div", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: t("agentChat.share.advancedDescription", {
|
|
212
|
+
defaultValue: "Control how organization access appears in search.",
|
|
213
|
+
}) })] }), _jsxs("button", { type: "button", role: "switch", "aria-checked": control.checked, disabled: !canManage || control.pending, onClick: onToggle, className: cn("flex w-full items-start gap-3 rounded-md border border-border/70 bg-card px-3 py-2.5 text-start transition-colors hover:bg-accent/45 disabled:cursor-not-allowed disabled:opacity-60", control.checked && "border-border bg-accent/35 text-foreground"), children: [_jsx("span", { "aria-hidden": true, className: cn("relative mt-0.5 inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-border bg-muted-foreground/25 transition-colors", control.checked && "border-primary/70 bg-primary"), children: _jsx("span", { className: cn("ml-0.5 size-4 rounded-full bg-popover shadow-sm transition-transform", control.checked && "translate-x-4") }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-center gap-1.5 text-sm font-medium text-foreground", children: [_jsx(IconSearchOff, { size: 14, strokeWidth: 1.8 }), control.label ??
|
|
214
|
+
t("agentChat.share.hideInSearch", {
|
|
215
|
+
defaultValue: "Hide in search",
|
|
216
|
+
})] }), _jsx("span", { className: "mt-0.5 block text-xs leading-5 text-muted-foreground", children: control.description ??
|
|
217
|
+
t("agentChat.share.linkCanStillOpen", {
|
|
218
|
+
defaultValue: "People with the link can still open this.",
|
|
219
|
+
}) })] })] })] }) })] }));
|
|
156
220
|
}
|
|
157
221
|
function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelectMember, onSubmit, placeholder, suggestions, search, }) {
|
|
222
|
+
const t = useT();
|
|
158
223
|
const rawListboxId = useId();
|
|
159
224
|
const listboxId = rawListboxId.replace(/:/g, "");
|
|
160
225
|
const inputRef = useRef(null);
|
|
@@ -247,32 +312,24 @@ function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelect
|
|
|
247
312
|
return (_jsxs("div", { id: optionId(listboxId, index), role: "option", "aria-selected": active, onMouseDown: (event) => event.preventDefault(), onMouseEnter: () => setActiveIndex(index), onClick: () => chooseMember(member), className: cn("flex cursor-pointer select-none flex-col rounded-sm px-3 py-2 text-sm outline-none", active
|
|
248
313
|
? "bg-accent text-accent-foreground"
|
|
249
314
|
: "text-foreground hover:bg-accent hover:text-accent-foreground"), children: [_jsx("span", { className: "truncate font-medium", children: member.name?.trim() || member.email }), member.name?.trim() ? (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: member.email })) : null] }, member.email));
|
|
250
|
-
}), search.isLoading && suggestions.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children:
|
|
315
|
+
}), search.isLoading && suggestions.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: t("agentChat.share.searching", {
|
|
316
|
+
defaultValue: "Searching...",
|
|
317
|
+
}) })) : null, search.error ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: t("agentChat.share.loadPeopleFailed", {
|
|
318
|
+
defaultValue: "Could not load people.",
|
|
319
|
+
}) })) : null, !search.isLoading && !search.error && suggestions.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: value.trim()
|
|
320
|
+
? t("agentChat.share.noMatches", {
|
|
321
|
+
defaultValue: "No matches.",
|
|
322
|
+
})
|
|
323
|
+
: t("agentChat.share.noPeopleFound", {
|
|
324
|
+
defaultValue: "No people found.",
|
|
325
|
+
}) })) : null, search.isLoadingMore ? (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground", children: [_jsx(IconLoader2, { "aria-hidden": true, size: 14, strokeWidth: 1.8, className: "animate-spin" }), t("agentChat.share.loading", { defaultValue: "Loading..." })] })) : null, search.hasMore && !search.isLoadingMore ? (_jsx("button", { type: "button", onMouseDown: (event) => event.preventDefault(), onClick: search.loadMore, className: "mt-1 flex w-full items-center justify-center rounded-sm px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground", children: t("agentChat.share.loadMore", { defaultValue: "Load more" }) })) : null] }) })] }));
|
|
251
326
|
}
|
|
252
327
|
function optionId(baseId, index) {
|
|
253
328
|
return `${baseId}-option-${index}`;
|
|
254
329
|
}
|
|
255
|
-
function CopyLinkField({ value, label
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
useEffect(() => {
|
|
259
|
-
return () => {
|
|
260
|
-
if (resetRef.current)
|
|
261
|
-
clearTimeout(resetRef.current);
|
|
262
|
-
};
|
|
263
|
-
}, []);
|
|
264
|
-
const handleCopy = async () => {
|
|
265
|
-
if (await writeClipboardText(value)) {
|
|
266
|
-
setCopied(true);
|
|
267
|
-
if (resetRef.current)
|
|
268
|
-
clearTimeout(resetRef.current);
|
|
269
|
-
resetRef.current = setTimeout(() => setCopied(false), 1400);
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
setCopied(false);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
return (_jsxs("div", { className: "mb-4 flex items-center justify-between gap-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-semibold", children: label }), description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: description })) : null] }), _jsxs("button", { type: "button", onClick: handleCopy, "aria-label": copied ? "Link copied" : "Copy", className: "inline-flex h-9 shrink-0 items-center gap-2 whitespace-nowrap rounded-md border border-input bg-card px-3 text-sm font-medium text-foreground hover:bg-accent", children: [copied ? _jsx(IconCheck, { size: 15 }) : _jsx(IconLink, { size: 15 }), copied ? "Copied" : "Copy"] })] }));
|
|
330
|
+
function CopyLinkField({ value, label, description, }) {
|
|
331
|
+
const t = useT();
|
|
332
|
+
return (_jsx(ShareCopyRow, { value: value, label: label ?? t("agentChat.share.shareLink", { defaultValue: "Share link" }), description: description, copyLabel: t("agentChat.share.copy", { defaultValue: "Copy" }), copiedLabel: t("agentChat.share.copied", { defaultValue: "Copied" }), onCopy: writeClipboardText, className: "mb-4" }));
|
|
276
333
|
}
|
|
277
334
|
// ---------------------------------------------------------------------------
|
|
278
335
|
// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)
|
|
@@ -283,17 +340,22 @@ function SelectItems({ items }) {
|
|
|
283
340
|
return (_jsx(_Fragment, { children: items.map((it) => (_jsxs(Select.Item, { value: it.value, className: selectItemClass, children: [_jsx("span", { className: "absolute start-2 top-2 flex h-4 w-4 items-center justify-center", children: _jsx(Select.ItemIndicator, { children: _jsx(IconCheck, { size: 14 }) }) }), _jsxs("span", { className: "flex flex-col", children: [_jsx(Select.ItemText, { children: it.label }), it.description ? (_jsx("span", { className: "text-xs text-muted-foreground", children: it.description })) : null] })] }, it.value))) }));
|
|
284
341
|
}
|
|
285
342
|
function RoleSelect(props) {
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
343
|
+
const t = useT();
|
|
344
|
+
const allOptions = roleOptions(t);
|
|
345
|
+
const current = roleMeta(props.value, t, props.roleCopy);
|
|
346
|
+
const allowedRoles = props.allowedRoles ?? allOptions.map((item) => item.value);
|
|
347
|
+
const options = allOptions
|
|
348
|
+
.filter((option) => option.value === props.value || allowedRoles.includes(option.value))
|
|
349
|
+
.map((option) => roleMeta(option.value, t, props.roleCopy));
|
|
289
350
|
return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: props.plain
|
|
290
351
|
? cn(BUTTON_BASE, "h-7 px-2 bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground")
|
|
291
|
-
: cn(BUTTON_BASE, "h-9 px-3 border border-input bg-card hover:bg-accent hover:text-accent-foreground"), "aria-label": "Role", children: [_jsx(Select.Value, { children: current.label }), _jsx(Select.Icon, { children: _jsx(IconChevronDown, { size: 14 }) })] }), _jsx(Select.Portal, { children: _jsx(Select.Content, { "data-agent-native-share-overlay": "", className: selectContentClass, position: "popper", sideOffset: 4, children: _jsx(Select.Viewport, { children: _jsx(SelectItems, { items: options }) }) }) })] }));
|
|
352
|
+
: cn(BUTTON_BASE, "h-9 px-3 border border-input bg-card hover:bg-accent hover:text-accent-foreground"), "aria-label": t("agentChat.share.role", { defaultValue: "Role" }), children: [_jsx(Select.Value, { children: current.label }), _jsx(Select.Icon, { children: _jsx(IconChevronDown, { size: 14 }) })] }), _jsx(Select.Portal, { children: _jsx(Select.Content, { "data-agent-native-share-overlay": "", className: selectContentClass, position: "popper", sideOffset: 4, children: _jsx(Select.Viewport, { children: _jsx(SelectItems, { items: options }) }) }) })] }));
|
|
292
353
|
}
|
|
293
354
|
function VisibilitySelect(props) {
|
|
355
|
+
const t = useT();
|
|
294
356
|
const allowPrivate = props.allowPrivate !== false;
|
|
295
357
|
const allowPublic = props.allowPublic !== false;
|
|
296
|
-
const current = visibilityMeta(props.value, props.visibilityCopy);
|
|
358
|
+
const current = visibilityMeta(props.value, t, props.visibilityCopy);
|
|
297
359
|
const options = Object.keys(VIS_META).filter((k) => {
|
|
298
360
|
if (k === props.value)
|
|
299
361
|
return true;
|
|
@@ -303,10 +365,12 @@ function VisibilitySelect(props) {
|
|
|
303
365
|
return false;
|
|
304
366
|
return true;
|
|
305
367
|
});
|
|
306
|
-
return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: cn(BUTTON_BASE, "h-7 px-1 -ms-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground"), "aria-label": "
|
|
368
|
+
return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: cn(BUTTON_BASE, "h-7 px-1 -ms-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground"), "aria-label": t("agentChat.share.generalAccess", {
|
|
369
|
+
defaultValue: "General access",
|
|
370
|
+
}), children: [_jsx(Select.Value, { children: current.label }), _jsx(Select.Icon, { children: _jsx(IconChevronDown, { size: 14 }) })] }), _jsx(Select.Portal, { children: _jsx(Select.Content, { "data-agent-native-share-overlay": "", className: selectContentClass, position: "popper", sideOffset: 4, children: _jsx(Select.Viewport, { children: _jsx(SelectItems, { items: options.map((k) => ({
|
|
307
371
|
value: k,
|
|
308
|
-
label: visibilityMeta(k, props.visibilityCopy).label,
|
|
309
|
-
description: visibilityMeta(k, props.visibilityCopy)
|
|
372
|
+
label: visibilityMeta(k, t, props.visibilityCopy).label,
|
|
373
|
+
description: visibilityMeta(k, t, props.visibilityCopy)
|
|
310
374
|
.description,
|
|
311
375
|
})) }) }) }) })] }));
|
|
312
376
|
}
|
|
@@ -320,18 +384,24 @@ function initials(s) {
|
|
|
320
384
|
const name = s.split("@")[0] ?? s;
|
|
321
385
|
return (name[0] ?? "?").toUpperCase();
|
|
322
386
|
}
|
|
323
|
-
function principalLabel(share, members) {
|
|
387
|
+
function principalLabel(share, members, t) {
|
|
324
388
|
const serverLabel = share.displayName?.trim();
|
|
325
389
|
if (serverLabel)
|
|
326
390
|
return serverLabel;
|
|
327
391
|
if (share.principalType === "org")
|
|
328
|
-
return "
|
|
329
|
-
|
|
392
|
+
return t("agentChat.share.organization", {
|
|
393
|
+
defaultValue: "Organization",
|
|
394
|
+
});
|
|
395
|
+
return displayName(share.principalId, members, t);
|
|
330
396
|
}
|
|
331
|
-
function displayName(emailOrId, members) {
|
|
397
|
+
function displayName(emailOrId, members, t) {
|
|
332
398
|
const normalized = emailOrId.trim().toLowerCase();
|
|
333
399
|
const match = members.find((m) => m.email.toLowerCase() === normalized);
|
|
334
400
|
if (match?.name && match.name.trim())
|
|
335
401
|
return match.name;
|
|
336
|
-
return normalized.includes("@")
|
|
402
|
+
return normalized.includes("@")
|
|
403
|
+
? emailOrId
|
|
404
|
+
: t("agentChat.share.unknownPerson", {
|
|
405
|
+
defaultValue: "Unknown person",
|
|
406
|
+
});
|
|
337
407
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ActionButton, Avatar as DesignSystemAvatar, Dialog as DesignSystemDialog, IconButton, Picker, Status, TextArea,
|
|
2
|
+
import { ActionButton, Avatar as DesignSystemAvatar, Dialog as DesignSystemDialog, IconButton, Picker, Status, TextArea, } from "@agent-native/toolkit/design-system";
|
|
3
|
+
import { ShareCopyRow } from "@agent-native/toolkit/sharing";
|
|
3
4
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@agent-native/toolkit/ui";
|
|
4
5
|
import { IconCheck, IconCode, IconCopy, IconChevronDown, IconLink, IconLock, IconMail, IconTrash, IconUsersGroup, IconWorld, } from "@tabler/icons-react";
|
|
5
6
|
import { useState } from "react";
|
|
@@ -53,7 +54,7 @@ function TabTrigger({ active, onClick, icon, label, }) {
|
|
|
53
54
|
}
|
|
54
55
|
function LinkTab({ controller, extras, }) {
|
|
55
56
|
const Icon = VIS_ICONS[controller.visibility.value];
|
|
56
|
-
return (_jsxs("div", { className: "space-y-3", children: [_jsx(
|
|
57
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsx(ShareCopyRow, { label: controller.labels.shareLink, value: controller.shareUrl, copyLabel: controller.labels.copy, copiedLabel: "Copied", onCopy: (value) => controller.copy("share-link", value), className: "mb-4" }), _jsxs("div", { children: [_jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: controller.labels.generalAccess }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { controller: controller }), _jsx("div", { className: "sr-only text-xs text-muted-foreground", children: controller.visibility.description })] })] })] }), extras] }));
|
|
57
58
|
}
|
|
58
59
|
function InviteTab({ controller, showVisibility, }) {
|
|
59
60
|
const Icon = VIS_ICONS[controller.visibility.value];
|
|
@@ -71,11 +72,11 @@ function PersonRow({ person, canManage, removeLabel, onRemove, }) {
|
|
|
71
72
|
return (_jsxs("li", { className: "flex items-center gap-3 px-1 py-1.5 text-sm", children: [_jsx(DesignSystemAvatar, { name: person.label, fallback: person.principalType === "org" ? (_jsx(IconUsersGroup, { size: 14, strokeWidth: 1.75 })) : (person.avatarText), size: "compact", className: "inline-flex h-7 w-7 shrink-0 text-[11px] font-semibold" }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: person.label }), _jsx(Status, { tone: "neutral", size: "compact", className: "border-0 bg-transparent px-0 text-xs text-muted-foreground", children: person.roleLabel }), canManage && person.share ? (_jsx(IconButton, { intent: "danger", emphasis: "ghost", size: "compact", icon: _jsx(IconTrash, { size: 14 }), label: removeLabel, "aria-label": removeLabel, onPress: () => onRemove(person.share), className: cn(BUTTON_GHOST_ICON, "[&_svg]:!size-auto") })) : null] }));
|
|
72
73
|
}
|
|
73
74
|
function DefaultEmbedBody({ controller, }) {
|
|
74
|
-
return (_jsxs("div", { className: "space-y-3", children: [_jsx(
|
|
75
|
+
return (_jsxs("div", { className: "space-y-3", children: [_jsx(ShareCopyRow, { label: controller.labels.embedUrl, value: controller.embedUrl, copyLabel: controller.labels.copy, copiedLabel: "Copied", onCopy: (value) => controller.copy("embed-url", value) }), _jsx(CopyField, { field: "embed-code", label: controller.labels.embedCode, value: controller.embedCode, controller: controller, multiline: true })] }));
|
|
75
76
|
}
|
|
76
77
|
function CopyField({ field, label, value, controller, multiline, }) {
|
|
77
78
|
const copied = controller.copiedField === field;
|
|
78
|
-
return (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: label }), _jsxs("div", { className: "flex items-stretch gap-2", children: [multiline ? (_jsx(TextArea, { readOnly: true, value: value, onChange: () => undefined, "aria-label": label, className: "flex-1 h-20 text-xs font-mono" })) :
|
|
79
|
+
return (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: label }), _jsxs("div", { className: "flex items-stretch gap-2", children: [multiline ? (_jsx(TextArea, { readOnly: true, value: value, onChange: () => undefined, "aria-label": label, className: "flex-1 h-20 text-xs font-mono" })) : null, _jsx(IconButton, { emphasis: "outline", size: "compact", icon: copied ? _jsx(IconCheck, { size: 14 }) : _jsx(IconCopy, { size: 14 }), label: controller.labels.copy, onPress: () => void controller.copy(field, value), "aria-label": controller.labels.copy, className: cn(BUTTON_OUTLINE_SM, "!w-9 !px-0 [&_svg]:!size-auto") })] })] }));
|
|
79
80
|
}
|
|
80
81
|
function RoleSelect({ controller }) {
|
|
81
82
|
return (_jsx(Picker, { mode: "select", options: controller.invite.roleOptions, value: controller.invite.role, onChange: (value) => {
|
|
@@ -466,17 +466,11 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
466
466
|
// - savedId in newlyCreatedRef (we just created it this session) → keep
|
|
467
467
|
// it; the server hasn't seen it yet because there's no POST anymore,
|
|
468
468
|
// the row gets written when the user sends a message.
|
|
469
|
-
// - savedId is set but
|
|
470
|
-
//
|
|
471
|
-
//
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
// Keep it exactly as the user left it: re-register it as an optimistic
|
|
475
|
-
// empty tab rather than resurrecting an unrelated old conversation. The
|
|
476
|
-
// composer is fully functional with this id (the server writes the row
|
|
477
|
-
// on first message, same as any new tab), so there's no 404 to avoid.
|
|
478
|
-
// This is what makes "the state you left is the state you see on
|
|
479
|
-
// refresh" hold — stale (>12h) tabs are still cleared downstream.
|
|
469
|
+
// - savedId is set but not on the current page → look it up directly. A
|
|
470
|
+
// found thread stays active. An auto-creating surface replaces a confirmed
|
|
471
|
+
// 404 with a fresh local tab rather than reusing an inaccessible server id.
|
|
472
|
+
// A list-only surface keeps the saved id as an optimistic empty tab so a
|
|
473
|
+
// never-posted tab remains selectable after reload.
|
|
480
474
|
// - No savedId → synthesize a fresh local id (no POST; server creates the
|
|
481
475
|
// row on first message). The server may contain chats from another
|
|
482
476
|
// branch, preview, or project that shares the same user/database, so
|
|
@@ -505,7 +499,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
505
499
|
? loadedThreads.find((t) => t.id === restoredId)
|
|
506
500
|
: undefined;
|
|
507
501
|
// One page, so absence from it is not absence from the server — this is what
|
|
508
|
-
// separates an older real thread from
|
|
502
|
+
// separates an older real thread from an unavailable saved id below.
|
|
509
503
|
const restoredThread = lookupRestored && !restoredOnPage
|
|
510
504
|
? await fetchThreadById(apiUrl, restoredId)
|
|
511
505
|
: restoredOnPage;
|
|
@@ -515,11 +509,13 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
515
509
|
setIsLoading(false);
|
|
516
510
|
return;
|
|
517
511
|
}
|
|
512
|
+
const restoredIsUnavailable = restoredThread === null && lookupRestored && !restoredOnPage;
|
|
518
513
|
const restoredBelongsElsewhere = Boolean(restoredThread &&
|
|
519
514
|
!threadCanStayVisibleInScope(restoredThread.scope ?? null, scopeRef.current));
|
|
520
|
-
|
|
515
|
+
const restoredNeedsReplacement = restoredBelongsElsewhere || (restoredIsUnavailable && autoCreate);
|
|
516
|
+
if (restoredNeedsReplacement)
|
|
521
517
|
setActiveThreadId(null);
|
|
522
|
-
const savedId =
|
|
518
|
+
const savedId = restoredNeedsReplacement ? null : restoredId;
|
|
523
519
|
const loadedHasSavedId = Boolean(savedId &&
|
|
524
520
|
(restoredThread || loadedThreads.some((t) => t.id === savedId)));
|
|
525
521
|
const savedIdCameFromRoute = Boolean(savedId) &&
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
import crypto from "node:crypto";
|
|
32
32
|
import http from "node:http";
|
|
33
|
-
import { getRequestUserEmail } from "../server/request-context.js";
|
|
33
|
+
import { getRequestRunContext, getRequestUserEmail, } from "../server/request-context.js";
|
|
34
34
|
import { failExpiredSandboxExecution, getSandboxExecutionForOwner, } from "./sandbox/executions-store.js";
|
|
35
35
|
import { BACKGROUND_DEFAULT_TIMEOUT_MS, BACKGROUND_MAX_TIMEOUT_MS, SANDBOX_EXECUTION_REDRIVE_AFTER_MS, driveSandboxExecution, enqueueSandboxExecution, getSandboxAdapter, isQueuedSandboxAdapter, registerSandboxExecutionRunner, resolveExecutionSandboxAdapter, } from "./sandbox/index.js";
|
|
36
36
|
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
@@ -289,6 +289,7 @@ async function enqueueBackgroundRunCode(input) {
|
|
|
289
289
|
owner,
|
|
290
290
|
orgId: input.context?.orgId ?? null,
|
|
291
291
|
threadId: input.context?.threadId ?? null,
|
|
292
|
+
allowedActionNames: getRequestRunContext()?.allowedActionNames,
|
|
292
293
|
});
|
|
293
294
|
const hasGetTool = Boolean(input.getActions()["get-code-execution"]);
|
|
294
295
|
return JSON.stringify({
|
|
@@ -106,6 +106,7 @@ export async function enqueueSandboxExecution(input) {
|
|
|
106
106
|
code: input.code,
|
|
107
107
|
timeoutMs: input.timeoutMs,
|
|
108
108
|
maxOutputChars: input.maxOutputChars,
|
|
109
|
+
allowedActionNames: input.allowedActionNames,
|
|
109
110
|
});
|
|
110
111
|
let driveNote;
|
|
111
112
|
try {
|
|
@@ -201,7 +202,13 @@ export async function processQueuedSandboxExecution(executionId) {
|
|
|
201
202
|
threadId: claimed.threadId ?? undefined,
|
|
202
203
|
actionName: "run-code",
|
|
203
204
|
};
|
|
204
|
-
const output = await runWithRequestContext({
|
|
205
|
+
const output = await runWithRequestContext({
|
|
206
|
+
userEmail: claimed.owner,
|
|
207
|
+
orgId: claimed.orgId ?? undefined,
|
|
208
|
+
run: claimed.allowedActionNames === undefined
|
|
209
|
+
? undefined
|
|
210
|
+
: { allowedActionNames: claimed.allowedActionNames },
|
|
211
|
+
}, () => runner.execute({
|
|
205
212
|
code: claimed.code,
|
|
206
213
|
timeoutMs: claimed.timeoutMs,
|
|
207
214
|
context,
|
|
@@ -51,6 +51,7 @@ export interface SandboxExecutionRow {
|
|
|
51
51
|
timedOut: boolean;
|
|
52
52
|
error: string | null;
|
|
53
53
|
bridgeToolsUsed: string[];
|
|
54
|
+
allowedActionNames: string[] | undefined;
|
|
54
55
|
createdAt: number;
|
|
55
56
|
startedAt: number | null;
|
|
56
57
|
finishedAt: number | null;
|
|
@@ -65,6 +66,7 @@ export interface CreateSandboxExecutionInput {
|
|
|
65
66
|
maxOutputChars: number;
|
|
66
67
|
maxAttempts?: number;
|
|
67
68
|
runtime?: string;
|
|
69
|
+
allowedActionNames?: readonly string[];
|
|
68
70
|
}
|
|
69
71
|
export interface FinalizeSandboxExecutionInput {
|
|
70
72
|
status: Extract<SandboxExecutionStatus, "succeeded" | "failed" | "timed_out">;
|