@agent-native/core 0.155.0 → 0.157.0
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/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +17 -13
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +102 -59
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +15 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +16 -2
- 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/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +42 -2
- 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/pages/DeckEditor.tsx +130 -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.js +12 -9
- package/dist/client/AssistantChat.d.ts +15 -1
- package/dist/client/AssistantChat.js +110 -43
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/chat/markdown-renderer.js +4 -2
- 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/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/sharing/ShareButton.js +160 -54
- 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/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 +2 -0
- package/dist/localization/default-messages.js +2 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- 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/index.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +2 -2
|
@@ -3,14 +3,16 @@ import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
|
3
3
|
import { IconThumbUp, IconThumbDown } from "@tabler/icons-react";
|
|
4
4
|
import { useState, useCallback } from "react";
|
|
5
5
|
import { agentNativePath } from "../api-path.js";
|
|
6
|
+
import { useT } from "../i18n.js";
|
|
6
7
|
import { cn } from "../utils.js";
|
|
7
8
|
const THUMBS_DOWN_CATEGORIES = [
|
|
8
|
-
"Inaccurate",
|
|
9
|
-
"Not helpful",
|
|
10
|
-
"Wrong tool",
|
|
11
|
-
"Too slow",
|
|
9
|
+
{ value: "Inaccurate", key: "agentChat.feedback.inaccurate" },
|
|
10
|
+
{ value: "Not helpful", key: "agentChat.feedback.notHelpful" },
|
|
11
|
+
{ value: "Wrong tool", key: "agentChat.feedback.wrongTool" },
|
|
12
|
+
{ value: "Too slow", key: "agentChat.feedback.tooSlow" },
|
|
12
13
|
];
|
|
13
14
|
export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
15
|
+
const t = useT();
|
|
14
16
|
const [selection, setSelection] = useState(null);
|
|
15
17
|
const [categoryOpen, setCategoryOpen] = useState(false);
|
|
16
18
|
const [submittedCategory, setSubmittedCategory] = useState(null);
|
|
@@ -54,11 +56,11 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
54
56
|
setCategoryOpen(false);
|
|
55
57
|
sendFeedback("category", category);
|
|
56
58
|
}, [sendFeedback]);
|
|
57
|
-
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": "
|
|
59
|
+
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "up"
|
|
58
60
|
? "text-foreground"
|
|
59
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: categoryOpen, onOpenChange: setCategoryOpen, children: [_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "
|
|
61
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: categoryOpen, onOpenChange: setCategoryOpen, children: [_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsDown"), onClick: handleThumbsDown, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "down"
|
|
60
62
|
? "text-foreground"
|
|
61
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, className: "z-[300] overflow-hidden rounded-lg border border-border bg-popover p-1 shadow-lg outline-none", children: _jsx("div", { className: "flex flex-col gap-0.5", children: THUMBS_DOWN_CATEGORIES.map((category) => (_jsx("button", { type: "button", onClick: () => handleCategory(category), className: cn("rounded-md px-3 py-1.5 text-
|
|
63
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, className: "z-[300] overflow-hidden rounded-lg border border-border bg-popover p-1 shadow-lg outline-none", children: _jsx("div", { className: "flex flex-col gap-0.5", children: THUMBS_DOWN_CATEGORIES.map((category) => (_jsx("button", { type: "button", onClick: () => handleCategory(category.value), className: cn("rounded-md px-3 py-1.5 text-start text-xs", submittedCategory === category.value
|
|
62
64
|
? "bg-accent text-foreground font-medium"
|
|
63
|
-
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: category }, category))) }) }) })] })] }));
|
|
65
|
+
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: t(category.key) }, category.value))) }) }) })] })] }));
|
|
64
66
|
}
|
|
@@ -4,6 +4,7 @@ import { IconLock, IconWorld, IconTrash, IconCheck, IconChevronDown, IconLoader2
|
|
|
4
4
|
import { useEffect, useId, useRef, useState, } from "react";
|
|
5
5
|
import { writeClipboardText } from "../clipboard.js";
|
|
6
6
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
7
|
+
import { useT } from "../i18n.js";
|
|
7
8
|
import { cn } from "../utils.js";
|
|
8
9
|
import { useShareButtonController, } from "./useShareButtonController.js";
|
|
9
10
|
// Match shadcn's <Button size="sm" variant="outline"> sizing so the trigger
|
|
@@ -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,
|
|
@@ -93,22 +126,32 @@ export function ShareButton(props) {
|
|
|
93
126
|
});
|
|
94
127
|
const triggerVisibility = controller.triggerVisibility;
|
|
95
128
|
const triggerMeta = triggerVisibility
|
|
96
|
-
? visibilityMeta(triggerVisibility, props.visibilityCopy)
|
|
129
|
+
? visibilityMeta(triggerVisibility, t, props.visibilityCopy)
|
|
97
130
|
: null;
|
|
98
131
|
const TriggerIcon = triggerMeta?.Icon ?? IconShare3;
|
|
99
132
|
const iconOnly = props.trigger === "icon";
|
|
100
133
|
const showTriggerIcon = iconOnly || props.trigger === "label-icon";
|
|
101
|
-
const triggerLabel = iconOnly && triggerMeta
|
|
102
|
-
|
|
134
|
+
const triggerLabel = iconOnly && triggerMeta
|
|
135
|
+
? t("agentChat.share.triggerWithVisibility", {
|
|
136
|
+
defaultValue: "Share ({{visibility}})",
|
|
137
|
+
visibility: triggerMeta.label,
|
|
138
|
+
})
|
|
139
|
+
: t("agentChat.share.share", { defaultValue: "Share" });
|
|
140
|
+
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: t("agentChat.share.share", { defaultValue: "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 }) })] }));
|
|
103
141
|
}
|
|
104
142
|
function SharePanel(props) {
|
|
143
|
+
const t = useT();
|
|
105
144
|
const { controller } = props;
|
|
106
145
|
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
146
|
const hasInviteEmail = inviteEmail.trim().length > 0;
|
|
108
147
|
const isLoading = data === undefined;
|
|
109
|
-
const meta = visibilityMeta(visibility, props.visibilityCopy);
|
|
110
|
-
const peopleAccessLabel = props.peopleAccessLabel ??
|
|
111
|
-
|
|
148
|
+
const meta = visibilityMeta(visibility, t, props.visibilityCopy);
|
|
149
|
+
const peopleAccessLabel = props.peopleAccessLabel ??
|
|
150
|
+
t("agentChat.share.peopleWithAccess", {
|
|
151
|
+
defaultValue: "People with access",
|
|
152
|
+
});
|
|
153
|
+
const generalAccessLabel = props.generalAccessLabel ??
|
|
154
|
+
t("agentChat.share.generalAccess", { defaultValue: "General access" });
|
|
112
155
|
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
156
|
const showShareLinks = (props.showShareLinks ?? true) &&
|
|
114
157
|
(Boolean(props.shareUrl) ||
|
|
@@ -117,7 +160,8 @@ function SharePanel(props) {
|
|
|
117
160
|
const shareUrlPlacement = props.shareUrlPlacement ?? "top";
|
|
118
161
|
const extraTabs = props.shareTabs?.tabs.filter((tab) => tab.value !== "context") ?? [];
|
|
119
162
|
const hasTabs = extraTabs.length > 0;
|
|
120
|
-
const shareTabLabel = props.shareTabs?.shareLabel ??
|
|
163
|
+
const shareTabLabel = props.shareTabs?.shareLabel ??
|
|
164
|
+
t("agentChat.share.shareLink", { defaultValue: "Share link" });
|
|
121
165
|
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
166
|
onInviteEmailChange(next);
|
|
123
167
|
if (shareError)
|
|
@@ -128,8 +172,28 @@ function SharePanel(props) {
|
|
|
128
172
|
if (shareError)
|
|
129
173
|
setShareError(null);
|
|
130
174
|
}, onSubmit: handleAdd, placeholder: policy.requireOrgMemberForUserShares
|
|
131
|
-
? "
|
|
132
|
-
|
|
175
|
+
? t("agentChat.share.addPeopleOrganization", {
|
|
176
|
+
defaultValue: "Add people from your organization",
|
|
177
|
+
})
|
|
178
|
+
: t("agentChat.share.addPeopleEmail", {
|
|
179
|
+
defaultValue: "Add people by email",
|
|
180
|
+
}), 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", {
|
|
181
|
+
defaultValue: "Notify people",
|
|
182
|
+
})] }), 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
|
|
183
|
+
? t("agentChat.share.hideMessage", {
|
|
184
|
+
defaultValue: "Hide message",
|
|
185
|
+
})
|
|
186
|
+
: t("agentChat.share.addMessage", {
|
|
187
|
+
defaultValue: "Add a message",
|
|
188
|
+
}) })) : 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", {
|
|
189
|
+
defaultValue: "Message",
|
|
190
|
+
}), placeholder: t("agentChat.share.messagePlaceholder", {
|
|
191
|
+
defaultValue: "Add a short note (optional)",
|
|
192
|
+
}), 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", {
|
|
193
|
+
defaultValue: "Remove",
|
|
194
|
+
}), 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", {
|
|
195
|
+
defaultValue: "No one has access yet.",
|
|
196
|
+
}) })) : 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
197
|
if (!hasTabs)
|
|
134
198
|
return sharePanel;
|
|
135
199
|
const tabs = [
|
|
@@ -144,17 +208,30 @@ function SharePanel(props) {
|
|
|
144
208
|
const activeTab = tabs.some((tab) => tab.value === activeShareTab)
|
|
145
209
|
? activeShareTab
|
|
146
210
|
: "share";
|
|
147
|
-
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("div", { role: "tablist", "aria-label": "
|
|
211
|
+
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("div", { role: "tablist", "aria-label": t("agentChat.share.shareOptions", {
|
|
212
|
+
defaultValue: "Share options",
|
|
213
|
+
}), className: "flex gap-1 rounded-xl bg-muted/70 p-1", children: tabs.map((tab) => {
|
|
148
214
|
const active = tab.value === activeTab;
|
|
149
215
|
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
216
|
"bg-background text-foreground shadow-sm ring-2 ring-primary"), children: _jsx("span", { className: "block truncate", children: tab.label }) }, tab.value));
|
|
151
217
|
}) }), _jsx("div", { role: "tabpanel", children: tabs.find((tab) => tab.value === activeTab)?.content })] }));
|
|
152
218
|
}
|
|
153
219
|
function AdvancedAccessPopover({ control, canManage, onToggle, }) {
|
|
154
|
-
|
|
155
|
-
|
|
220
|
+
const t = useT();
|
|
221
|
+
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", {
|
|
222
|
+
defaultValue: "Advanced access",
|
|
223
|
+
}) }), _jsx("div", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: t("agentChat.share.advancedDescription", {
|
|
224
|
+
defaultValue: "Control how organization access appears in search.",
|
|
225
|
+
}) })] }), _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 ??
|
|
226
|
+
t("agentChat.share.hideInSearch", {
|
|
227
|
+
defaultValue: "Hide in search",
|
|
228
|
+
})] }), _jsx("span", { className: "mt-0.5 block text-xs leading-5 text-muted-foreground", children: control.description ??
|
|
229
|
+
t("agentChat.share.linkCanStillOpen", {
|
|
230
|
+
defaultValue: "People with the link can still open this.",
|
|
231
|
+
}) })] })] })] }) })] }));
|
|
156
232
|
}
|
|
157
233
|
function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelectMember, onSubmit, placeholder, suggestions, search, }) {
|
|
234
|
+
const t = useT();
|
|
158
235
|
const rawListboxId = useId();
|
|
159
236
|
const listboxId = rawListboxId.replace(/:/g, "");
|
|
160
237
|
const inputRef = useRef(null);
|
|
@@ -247,12 +324,23 @@ function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelect
|
|
|
247
324
|
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
325
|
? "bg-accent text-accent-foreground"
|
|
249
326
|
: "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:
|
|
327
|
+
}), search.isLoading && suggestions.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: t("agentChat.share.searching", {
|
|
328
|
+
defaultValue: "Searching...",
|
|
329
|
+
}) })) : null, search.error ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: t("agentChat.share.loadPeopleFailed", {
|
|
330
|
+
defaultValue: "Could not load people.",
|
|
331
|
+
}) })) : null, !search.isLoading && !search.error && suggestions.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: value.trim()
|
|
332
|
+
? t("agentChat.share.noMatches", {
|
|
333
|
+
defaultValue: "No matches.",
|
|
334
|
+
})
|
|
335
|
+
: t("agentChat.share.noPeopleFound", {
|
|
336
|
+
defaultValue: "No people found.",
|
|
337
|
+
}) })) : 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
338
|
}
|
|
252
339
|
function optionId(baseId, index) {
|
|
253
340
|
return `${baseId}-option-${index}`;
|
|
254
341
|
}
|
|
255
|
-
function CopyLinkField({ value, label
|
|
342
|
+
function CopyLinkField({ value, label, description, }) {
|
|
343
|
+
const t = useT();
|
|
256
344
|
const [copied, setCopied] = useState(false);
|
|
257
345
|
const resetRef = useRef(undefined);
|
|
258
346
|
useEffect(() => {
|
|
@@ -272,7 +360,12 @@ function CopyLinkField({ value, label = "Share link", description, }) {
|
|
|
272
360
|
setCopied(false);
|
|
273
361
|
}
|
|
274
362
|
};
|
|
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
|
|
363
|
+
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 ??
|
|
364
|
+
t("agentChat.share.shareLink", { defaultValue: "Share link" }) }), description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: description })) : null] }), _jsxs("button", { type: "button", onClick: handleCopy, "aria-label": copied
|
|
365
|
+
? t("agentChat.share.copied", { defaultValue: "Copied" })
|
|
366
|
+
: t("agentChat.share.copy", { defaultValue: "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
|
|
367
|
+
? t("agentChat.share.copied", { defaultValue: "Copied" })
|
|
368
|
+
: t("agentChat.share.copy", { defaultValue: "Copy" })] })] }));
|
|
276
369
|
}
|
|
277
370
|
// ---------------------------------------------------------------------------
|
|
278
371
|
// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)
|
|
@@ -283,17 +376,22 @@ function SelectItems({ items }) {
|
|
|
283
376
|
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
377
|
}
|
|
285
378
|
function RoleSelect(props) {
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
379
|
+
const t = useT();
|
|
380
|
+
const allOptions = roleOptions(t);
|
|
381
|
+
const current = roleMeta(props.value, t, props.roleCopy);
|
|
382
|
+
const allowedRoles = props.allowedRoles ?? allOptions.map((item) => item.value);
|
|
383
|
+
const options = allOptions
|
|
384
|
+
.filter((option) => option.value === props.value || allowedRoles.includes(option.value))
|
|
385
|
+
.map((option) => roleMeta(option.value, t, props.roleCopy));
|
|
289
386
|
return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: props.plain
|
|
290
387
|
? 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 }) }) }) })] }));
|
|
388
|
+
: 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
389
|
}
|
|
293
390
|
function VisibilitySelect(props) {
|
|
391
|
+
const t = useT();
|
|
294
392
|
const allowPrivate = props.allowPrivate !== false;
|
|
295
393
|
const allowPublic = props.allowPublic !== false;
|
|
296
|
-
const current = visibilityMeta(props.value, props.visibilityCopy);
|
|
394
|
+
const current = visibilityMeta(props.value, t, props.visibilityCopy);
|
|
297
395
|
const options = Object.keys(VIS_META).filter((k) => {
|
|
298
396
|
if (k === props.value)
|
|
299
397
|
return true;
|
|
@@ -303,10 +401,12 @@ function VisibilitySelect(props) {
|
|
|
303
401
|
return false;
|
|
304
402
|
return true;
|
|
305
403
|
});
|
|
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": "
|
|
404
|
+
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", {
|
|
405
|
+
defaultValue: "General access",
|
|
406
|
+
}), 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
407
|
value: k,
|
|
308
|
-
label: visibilityMeta(k, props.visibilityCopy).label,
|
|
309
|
-
description: visibilityMeta(k, props.visibilityCopy)
|
|
408
|
+
label: visibilityMeta(k, t, props.visibilityCopy).label,
|
|
409
|
+
description: visibilityMeta(k, t, props.visibilityCopy)
|
|
310
410
|
.description,
|
|
311
411
|
})) }) }) }) })] }));
|
|
312
412
|
}
|
|
@@ -320,18 +420,24 @@ function initials(s) {
|
|
|
320
420
|
const name = s.split("@")[0] ?? s;
|
|
321
421
|
return (name[0] ?? "?").toUpperCase();
|
|
322
422
|
}
|
|
323
|
-
function principalLabel(share, members) {
|
|
423
|
+
function principalLabel(share, members, t) {
|
|
324
424
|
const serverLabel = share.displayName?.trim();
|
|
325
425
|
if (serverLabel)
|
|
326
426
|
return serverLabel;
|
|
327
427
|
if (share.principalType === "org")
|
|
328
|
-
return "
|
|
329
|
-
|
|
428
|
+
return t("agentChat.share.organization", {
|
|
429
|
+
defaultValue: "Organization",
|
|
430
|
+
});
|
|
431
|
+
return displayName(share.principalId, members, t);
|
|
330
432
|
}
|
|
331
|
-
function displayName(emailOrId, members) {
|
|
433
|
+
function displayName(emailOrId, members, t) {
|
|
332
434
|
const normalized = emailOrId.trim().toLowerCase();
|
|
333
435
|
const match = members.find((m) => m.email.toLowerCase() === normalized);
|
|
334
436
|
if (match?.name && match.name.trim())
|
|
335
437
|
return match.name;
|
|
336
|
-
return normalized.includes("@")
|
|
438
|
+
return normalized.includes("@")
|
|
439
|
+
? emailOrId
|
|
440
|
+
: t("agentChat.share.unknownPerson", {
|
|
441
|
+
defaultValue: "Unknown person",
|
|
442
|
+
});
|
|
337
443
|
}
|
|
@@ -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">;
|
|
@@ -79,6 +79,7 @@ async function _doEnsureTable() {
|
|
|
79
79
|
timed_out ${intType()} NOT NULL DEFAULT 0,
|
|
80
80
|
error TEXT,
|
|
81
81
|
bridge_tools_used TEXT,
|
|
82
|
+
allowed_action_names TEXT,
|
|
82
83
|
created_at ${intType()} NOT NULL,
|
|
83
84
|
started_at ${intType()},
|
|
84
85
|
finished_at ${intType()},
|
|
@@ -94,7 +95,10 @@ async function _doEnsureTable() {
|
|
|
94
95
|
await ensureTableExists(TABLE, createSql);
|
|
95
96
|
// Additive-column guard: keeps older deployments (created before a column
|
|
96
97
|
// was added) self-healing without destructive migrations.
|
|
97
|
-
const pgColumns = [
|
|
98
|
+
const pgColumns = [
|
|
99
|
+
["bridge_tools_used", "TEXT"],
|
|
100
|
+
["allowed_action_names", "TEXT"],
|
|
101
|
+
];
|
|
98
102
|
for (const [col, def] of pgColumns) {
|
|
99
103
|
await ensureColumnExists(TABLE, col, `ALTER TABLE ${TABLE} ADD COLUMN IF NOT EXISTS ${col} ${def}`);
|
|
100
104
|
}
|
|
@@ -103,6 +107,15 @@ async function _doEnsureTable() {
|
|
|
103
107
|
}
|
|
104
108
|
else {
|
|
105
109
|
await retryOnDdlRace(() => client.execute(createSql));
|
|
110
|
+
try {
|
|
111
|
+
await retryOnDdlRace(() => client.execute(`ALTER TABLE ${TABLE} ADD COLUMN allowed_action_names TEXT`));
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
const message = String(error?.message ?? error);
|
|
115
|
+
if (!/duplicate column name|column .* already exists/i.test(message)) {
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
106
119
|
await retryOnDdlRace(() => client.execute(ownerIdxSql));
|
|
107
120
|
await retryOnDdlRace(() => client.execute(dueIdxSql));
|
|
108
121
|
}
|
|
@@ -136,6 +149,27 @@ function rowFromDb(raw) {
|
|
|
136
149
|
bridgeToolsUsed = [];
|
|
137
150
|
}
|
|
138
151
|
}
|
|
152
|
+
let allowedActionNames;
|
|
153
|
+
if (raw.allowed_action_names !== null &&
|
|
154
|
+
raw.allowed_action_names !== undefined) {
|
|
155
|
+
if (typeof raw.allowed_action_names !== "string") {
|
|
156
|
+
allowedActionNames = [];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
try {
|
|
160
|
+
const parsed = JSON.parse(raw.allowed_action_names);
|
|
161
|
+
allowedActionNames =
|
|
162
|
+
Array.isArray(parsed) &&
|
|
163
|
+
parsed.every((item) => typeof item === "string")
|
|
164
|
+
? [...new Set(parsed)]
|
|
165
|
+
: [];
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// A malformed persisted surface must never restore the full registry.
|
|
169
|
+
allowedActionNames = [];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
139
173
|
return {
|
|
140
174
|
id: String(raw.id),
|
|
141
175
|
owner: String(raw.owner),
|
|
@@ -165,6 +199,7 @@ function rowFromDb(raw) {
|
|
|
165
199
|
timedOut: toBool(raw.timed_out),
|
|
166
200
|
error: raw.error === null || raw.error === undefined ? null : String(raw.error),
|
|
167
201
|
bridgeToolsUsed,
|
|
202
|
+
allowedActionNames,
|
|
168
203
|
createdAt: toNumberOrNull(raw.created_at) ?? 0,
|
|
169
204
|
startedAt: toNumberOrNull(raw.started_at),
|
|
170
205
|
finishedAt: toNumberOrNull(raw.finished_at),
|
|
@@ -180,8 +215,8 @@ export async function createSandboxExecution(input) {
|
|
|
180
215
|
const maxAttempts = Math.max(1, Math.min(input.maxAttempts ?? SANDBOX_EXECUTION_DEFAULT_MAX_ATTEMPTS, 5));
|
|
181
216
|
await client.execute({
|
|
182
217
|
sql: `INSERT INTO ${TABLE}
|
|
183
|
-
(id, owner, org_id, thread_id, runtime, code, status, timeout_ms, max_output_chars, attempt_count, max_attempts, created_at, updated_at)
|
|
184
|
-
VALUES (?, ?, ?, ?, ?, ?, 'queued', ?, ?, 0, ?, ?, ?)`,
|
|
218
|
+
(id, owner, org_id, thread_id, runtime, code, status, timeout_ms, max_output_chars, attempt_count, max_attempts, allowed_action_names, created_at, updated_at)
|
|
219
|
+
VALUES (?, ?, ?, ?, ?, ?, 'queued', ?, ?, 0, ?, ?, ?, ?)`,
|
|
185
220
|
args: [
|
|
186
221
|
id,
|
|
187
222
|
input.owner,
|
|
@@ -192,6 +227,9 @@ export async function createSandboxExecution(input) {
|
|
|
192
227
|
input.timeoutMs,
|
|
193
228
|
input.maxOutputChars,
|
|
194
229
|
maxAttempts,
|
|
230
|
+
input.allowedActionNames === undefined
|
|
231
|
+
? null
|
|
232
|
+
: JSON.stringify([...new Set(input.allowedActionNames)]),
|
|
195
233
|
now,
|
|
196
234
|
now,
|
|
197
235
|
],
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./config.js";
|
|
2
|
-
export { createProductionAgentHandler, type ActionEntry, type ScriptEntry, type ProductionAgentOptions, type ActionTool, type ScriptTool, type AgentMessage, type AgentChatRequest, type AgentChatEvent, type AgentChatAttachment, DEFAULT_MODEL, TripWire, type Processor, type ProcessorState, type ProcessorAbort, } from "./agent/index.js";
|
|
2
|
+
export { createProductionAgentHandler, type ActionEntry, type ScriptEntry, type ProductionAgentOptions, type AgentActionSurface, type AgentActionSurfaceDetails, type ActionTool, type ScriptTool, type AgentMessage, type AgentChatRequest, type AgentChatEvent, type AgentChatAttachment, DEFAULT_MODEL, TripWire, type Processor, type ProcessorState, type ProcessorAbort, } from "./agent/index.js";
|
|
3
3
|
export { defineAction, ActionContractError, isActionContractError, type ActionContractErrorOptions, AgentActionStopError, isAgentActionStopError, type ActionDefinition, type ActionHttpConfig, type AgentActionStopOptions, type PublicAgentActionConfig, type ActionDeepLink, type ActionLinkBuilder, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, type ActionMcpAppConfig, type ActionMcpAppCsp, type ActionMcpAppCspBuilder, type ActionMcpAppHtmlBuilder, type ActionMcpAppPermissions, type ActionMcpAppResourceConfig, type ActionMcpAppResourceMeta, } from "./action.js";
|
|
4
4
|
export * from "./user-profile/index.js";
|
|
5
5
|
export { embedApp, MCP_APP_REQUEST_ORIGIN_CSP_SOURCE, type EmbedAppOptions, } from "./mcp/embed-app.js";
|