@agent-native/core 0.154.4 → 0.155.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/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/account-health/SKILL.md +76 -0
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
- package/corpus/templates/analytics/actions/bigquery.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
- package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/calendar/AGENTS.md +2 -0
- package/corpus/templates/calendar/DEVELOPING.md +4 -4
- package/corpus/templates/calendar/actions/get-settings.ts +4 -11
- package/corpus/templates/calendar/actions/update-availability.ts +15 -4
- package/corpus/templates/calendar/actions/update-settings.ts +15 -4
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
- package/corpus/templates/calendar/app/i18n-data.ts +30 -0
- package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
- package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
- package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
- package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
- package/corpus/templates/calendar/shared/api.ts +1 -0
- package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
- package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
- package/corpus/templates/calendar/shared/settings.ts +44 -0
- package/corpus/templates/clips/AGENTS.md +2 -0
- package/corpus/templates/clips/actions/add-comment.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
- package/corpus/templates/clips/actions/update-comment.ts +9 -2
- package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
- package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
- package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
- package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
- package/corpus/templates/clips/app/root.tsx +2 -1
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +14 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
- package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +116 -19
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
- package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
- package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
- package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
- package/corpus/templates/clips/desktop/src/styles.css +117 -0
- package/corpus/templates/clips/server/db/index.ts +10 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +3 -1
- package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
- package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
- package/corpus/templates/content/.agents/skills/content/SKILL.md +2 -2
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +20 -4
- package/corpus/templates/content/actions/_database-row-mutation.ts +1490 -0
- package/corpus/templates/content/actions/_database-utils.ts +44 -0
- package/corpus/templates/content/actions/_property-utils.ts +4 -1
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/add-database-item.ts +62 -240
- package/corpus/templates/content/actions/configure-document-property.ts +165 -1
- package/corpus/templates/content/actions/delete-document-property.ts +18 -0
- package/corpus/templates/content/actions/set-document-property.ts +78 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/actions/update-database-item.ts +62 -0
- package/corpus/templates/content/actions/upsert-database-item-by-key.ts +43 -796
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +10 -8
- package/corpus/templates/content/app/hooks/use-content-database.ts +33 -32
- package/corpus/templates/content/changelog/2026-08-10-database-row-actions-now-validate-exact-schemas-and-safe-ret.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +2 -0
- package/corpus/templates/content/server/db/schema.ts +39 -3
- package/corpus/templates/content/server/plugins/db.ts +30 -0
- package/corpus/templates/content/shared/api.ts +75 -2
- package/corpus/templates/design/actions/generate-design.ts +10 -7
- package/corpus/templates/design/actions/present-design-variants.ts +35 -6
- package/corpus/templates/design/actions/run-design-audit.ts +33 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +66 -0
- package/corpus/templates/dispatch/.env.example +5 -0
- package/corpus/templates/dispatch/AGENTS.md +24 -19
- package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
- package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +23 -0
- package/corpus/templates/factory/actions/view-screen.ts +17 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
- package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
- package/corpus/templates/factory/app/routes/factory.tsx +41 -0
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
- package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
- package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
- package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
- package/corpus/templates/mail/vite.config.ts +7 -0
- package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
- package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
- package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
- package/dist/action.d.ts +22 -0
- package/dist/action.js +27 -0
- package/dist/agent/production-agent.js +5 -1
- package/dist/agent/thread-data-builder.js +17 -1
- package/dist/cli/skills-content/help.js +6 -4
- package/dist/cli/skills.js +17 -2
- package/dist/cli/workspacify.d.ts +5 -0
- package/dist/cli/workspacify.js +65 -8
- package/dist/client/AgentPanel.d.ts +5 -0
- package/dist/client/AgentPanel.js +20 -4
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.js +66 -68
- package/dist/client/active-run-state.d.ts +14 -1
- package/dist/client/active-run-state.js +0 -0
- package/dist/client/agent-chat-adapter.js +107 -5
- package/dist/client/analytics.js +9 -2
- package/dist/client/chat/tool-call-display.js +4 -4
- package/dist/client/chat-first/apps-rail.js +9 -4
- package/dist/client/chat-first/primary-nav.d.ts +2 -1
- package/dist/client/chat-first/primary-nav.js +3 -3
- package/dist/client/chat-first/types.d.ts +5 -1
- package/dist/client/markdown/InlineMarkdown.d.ts +23 -0
- package/dist/client/markdown/InlineMarkdown.js +65 -0
- package/dist/client/markdown/index.d.ts +1 -0
- package/dist/client/markdown/index.js +1 -0
- package/dist/client/review/ReviewThreadPanel.js +2 -1
- package/dist/client/run-stream-ownership.d.ts +39 -0
- package/dist/client/run-stream-ownership.js +65 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +10 -0
- package/dist/feature-flags/store.js +112 -1
- package/dist/guards/no-env-credentials.js +4 -0
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/integrations/adapters/slack.js +5 -1
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +1 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- 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/agents.js +40 -5
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/metadata.d.ts +10 -0
- package/dist/resources/metadata.js +7 -3
- package/dist/review/actions/create-review-comment.js +1 -1
- package/dist/review/actions/reply-review-comment.js +1 -1
- package/dist/review/actions/resolve-review-thread.js +1 -1
- package/dist/server/action-routes.js +42 -8
- package/dist/server/agent-discovery.js +14 -3
- package/dist/server/core-routes-plugin.js +1 -1
- package/dist/server/identity-sso-migrations.d.ts +7 -0
- package/dist/server/identity-sso-migrations.js +36 -0
- package/dist/server/identity-sso-store.d.ts +3 -2
- package/dist/server/identity-sso-store.js +8 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/package.json +3 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconClock, IconPlus, IconPlugConnected, IconSearch, } from "@tabler/icons-react";
|
|
3
3
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
4
|
-
export function ChatFirstPrimaryNavigation({ onNewChat, onOpenIntegrations, onOpenScheduled, onSearch, activeTab, stickyNewChat = false, copy = defaultChatFirstCopy, }) {
|
|
4
|
+
export function ChatFirstPrimaryNavigation({ onNewChat, onOpenIntegrations, onOpenScheduled, onSearch, activeTab, collapsed = false, stickyNewChat = false, copy = defaultChatFirstCopy, }) {
|
|
5
5
|
const tabClassName = (tab) => `flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium transition-[background-color,color] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${activeTab === tab
|
|
6
6
|
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
7
7
|
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"}`;
|
|
8
|
-
const renderTab = (tab, content, onSelect, className) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeTab === tab, className: [tabClassName(tab), className].filter(Boolean).join(" "), onClick: onSelect, children: content }));
|
|
8
|
+
const renderTab = (tab, content, onSelect, className) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeTab === tab, "aria-label": tab === "new-chat" ? copy("newChat") : undefined, title: tab === "new-chat" && collapsed ? copy("newChat") : undefined, className: [tabClassName(tab), className].filter(Boolean).join(" "), onClick: onSelect, children: content }));
|
|
9
9
|
const newChatTab = onNewChat
|
|
10
|
-
? renderTab("new-chat", _jsxs(_Fragment, { children: [_jsx(IconPlus, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("newChat") })] }), onNewChat, "code-agents-primary-new-chat")
|
|
10
|
+
? renderTab("new-chat", _jsxs(_Fragment, { children: [_jsx(IconPlus, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: collapsed ? "sr-only" : undefined, children: copy("newChat") })] }), onNewChat, "code-agents-primary-new-chat")
|
|
11
11
|
: null;
|
|
12
12
|
const integrationsTab = renderTab("integrations", _jsxs(_Fragment, { children: [_jsx(IconPlugConnected, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("integrations") })] }), onOpenIntegrations);
|
|
13
13
|
const scheduledTab = renderTab("scheduled", _jsxs(_Fragment, { children: [_jsx(IconClock, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("scheduled") })] }), onOpenScheduled);
|
|
@@ -8,6 +8,10 @@ export interface ChatFirstAppItem {
|
|
|
8
8
|
color?: string;
|
|
9
9
|
}
|
|
10
10
|
export type ChatFirstCopy = (key: string, values?: Record<string, string>) => string;
|
|
11
|
+
export interface ChatFirstAppIconRenderOptions {
|
|
12
|
+
isActive: boolean;
|
|
13
|
+
isInactive: boolean;
|
|
14
|
+
}
|
|
11
15
|
export interface ChatFirstEmbedTarget {
|
|
12
16
|
url: string;
|
|
13
17
|
title?: string;
|
|
@@ -51,7 +55,7 @@ export interface ChatFirstAppRailProps {
|
|
|
51
55
|
onOpenAllApps?: () => void;
|
|
52
56
|
onCreateApp?: () => void;
|
|
53
57
|
createAppTrigger?: ReactNode;
|
|
54
|
-
renderIcon: (app: ChatFirstAppItem) => ReactNode;
|
|
58
|
+
renderIcon: (app: ChatFirstAppItem, options?: ChatFirstAppIconRenderOptions) => ReactNode;
|
|
55
59
|
copy?: ChatFirstCopy;
|
|
56
60
|
}
|
|
57
61
|
export interface ChatFirstBrowserPaneProps {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface InlineMarkdownProps {
|
|
3
|
+
content: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
linkClassName?: string;
|
|
6
|
+
codeClassName?: string;
|
|
7
|
+
inline?: boolean;
|
|
8
|
+
protectedSpans?: readonly InlineMarkdownProtectedSpan[];
|
|
9
|
+
renderProtectedSpan?: (span: InlineMarkdownProtectedSpan, children: ReactNode) => ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface InlineMarkdownProtectedSpan {
|
|
12
|
+
source: string;
|
|
13
|
+
label: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render user-authored Markdown for compact text surfaces.
|
|
19
|
+
*
|
|
20
|
+
* This intentionally has no block-level Markdown elements: headings, lists,
|
|
21
|
+
* quotes, and raw HTML are either flattened to their text or omitted.
|
|
22
|
+
*/
|
|
23
|
+
export declare function InlineMarkdown({ content, className, linkClassName, codeClassName, inline, protectedSpans, renderProtectedSpan, }: InlineMarkdownProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import ReactMarkdown, { defaultUrlTransform, } from "react-markdown";
|
|
3
|
+
import remarkGfm from "remark-gfm";
|
|
4
|
+
import { cn } from "../utils.js";
|
|
5
|
+
const INLINE_MARKDOWN_ELEMENTS = [
|
|
6
|
+
"a",
|
|
7
|
+
"br",
|
|
8
|
+
"code",
|
|
9
|
+
"del",
|
|
10
|
+
"em",
|
|
11
|
+
"p",
|
|
12
|
+
"s",
|
|
13
|
+
"strong",
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Render user-authored Markdown for compact text surfaces.
|
|
17
|
+
*
|
|
18
|
+
* This intentionally has no block-level Markdown elements: headings, lists,
|
|
19
|
+
* quotes, and raw HTML are either flattened to their text or omitted.
|
|
20
|
+
*/
|
|
21
|
+
export function InlineMarkdown({ content, className, linkClassName, codeClassName, inline = false, protectedSpans = [], renderProtectedSpan, }) {
|
|
22
|
+
const protectedSpanByHref = new Map(protectedSpans
|
|
23
|
+
.map((span, index) => [`${PROTECTED_SPAN_PREFIX}${index}`, span])
|
|
24
|
+
.filter(([, span]) => span.source.length > 0));
|
|
25
|
+
const renderedContent = protectInlineMarkdownSpans(content, protectedSpans);
|
|
26
|
+
const components = {
|
|
27
|
+
a: ({ children, href }) => {
|
|
28
|
+
const protectedSpan = href ? protectedSpanByHref.get(href) : undefined;
|
|
29
|
+
if (protectedSpan) {
|
|
30
|
+
return renderProtectedSpan ? (renderProtectedSpan(protectedSpan, children)) : (_jsx("span", { className: protectedSpan.className, title: protectedSpan.title, children: children }));
|
|
31
|
+
}
|
|
32
|
+
const safeHref = href
|
|
33
|
+
? defaultUrlTransform(normalizeInlineMarkdownHref(href))
|
|
34
|
+
: "";
|
|
35
|
+
if (!safeHref)
|
|
36
|
+
return _jsx(_Fragment, { children: children });
|
|
37
|
+
return (_jsx("a", { href: safeHref, target: "_blank", rel: "noopener noreferrer", className: cn("text-primary underline-offset-2 hover:underline", linkClassName), children: children }));
|
|
38
|
+
},
|
|
39
|
+
code: ({ children, className: syntaxClassName }) => (_jsx("code", { className: cn("rounded bg-muted px-1 py-0.5 font-mono text-[0.9em]", syntaxClassName, codeClassName), children: children })),
|
|
40
|
+
p: ({ children }) => inline ? _jsx("span", { children: children }) : _jsx("p", { className: "m-0", children: children }),
|
|
41
|
+
};
|
|
42
|
+
const Root = inline ? "span" : "div";
|
|
43
|
+
return (_jsx(Root, { className: cn("whitespace-pre-wrap break-words", className), children: _jsx(ReactMarkdown, { allowedElements: INLINE_MARKDOWN_ELEMENTS, components: components, remarkPlugins: [remarkGfm], skipHtml: true, unwrapDisallowed: true, children: renderedContent }) }));
|
|
44
|
+
}
|
|
45
|
+
const PROTECTED_SPAN_PREFIX = "https://inline-markdown-protected.invalid/span/";
|
|
46
|
+
function protectInlineMarkdownSpans(content, spans) {
|
|
47
|
+
return [...spans]
|
|
48
|
+
.map((span, index) => ({ span, index }))
|
|
49
|
+
.filter(({ span }) => span.source.length > 0)
|
|
50
|
+
.sort((a, b) => b.span.source.length - a.span.source.length)
|
|
51
|
+
.reduce((markdown, { span, index }) => markdown
|
|
52
|
+
.split(span.source)
|
|
53
|
+
.join(`[${escapeProtectedSpanLabel(span.label)}](${PROTECTED_SPAN_PREFIX}${index})`), content);
|
|
54
|
+
}
|
|
55
|
+
function escapeProtectedSpanLabel(label) {
|
|
56
|
+
return label.replace(/[\\[\]]/g, "\\$&");
|
|
57
|
+
}
|
|
58
|
+
function normalizeInlineMarkdownHref(href) {
|
|
59
|
+
if (/^www\./i.test(href))
|
|
60
|
+
return `https://${href}`;
|
|
61
|
+
if (/^http:\/\/www\./i.test(href)) {
|
|
62
|
+
return `https://${href.slice("http://".length)}`;
|
|
63
|
+
}
|
|
64
|
+
return href;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InlineMarkdown, type InlineMarkdownProtectedSpan, type InlineMarkdownProps, } from "./InlineMarkdown.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InlineMarkdown, } from "./InlineMarkdown.js";
|
|
@@ -8,6 +8,7 @@ import { Spinner } from "@agent-native/toolkit/ui/spinner";
|
|
|
8
8
|
import { IconCircleCheck, IconDots, IconMessageCircle, IconSend, IconTrash, IconX, } from "@tabler/icons-react";
|
|
9
9
|
import { useMemo, useState } from "react";
|
|
10
10
|
import { useFormatters } from "../i18n.js";
|
|
11
|
+
import { InlineMarkdown } from "../markdown/index.js";
|
|
11
12
|
import { cn } from "../utils.js";
|
|
12
13
|
import { ReviewCommentComposer } from "./ReviewCommentComposer.js";
|
|
13
14
|
import { ReviewStatusBadge } from "./ReviewStatusBadge.js";
|
|
@@ -126,7 +127,7 @@ function CommentBubble({ comment, compact = false, resolvedLabel, reviewerLabel,
|
|
|
126
127
|
const bodyIsResolutionNote = resolutionNote !== null &&
|
|
127
128
|
resolutionNote === comment.body.trim() &&
|
|
128
129
|
isResolutionNoteMetadata(comment.metadata);
|
|
129
|
-
return (_jsxs("div", { className: "flex min-w-0 items-start gap-2.5", children: [_jsx(Avatar, { className: compact ? "size-5" : "size-7", children: _jsx(AvatarFallback, { className: "text-[10px] font-semibold text-muted-foreground", children: authorInitials(author) }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: author }), _jsx("time", { className: "shrink-0 text-[11px] text-muted-foreground", dateTime: comment.createdAt, children: formatCommentDate(comment.createdAt, formatDate) }), comment.status === "resolved" ? (_jsx("span", { className: "hidden shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground @xs/review:inline-flex", children: resolvedLabel })) : null] }), !bodyIsResolutionNote ? (_jsx(
|
|
130
|
+
return (_jsxs("div", { className: "flex min-w-0 items-start gap-2.5", children: [_jsx(Avatar, { className: compact ? "size-5" : "size-7", children: _jsx(AvatarFallback, { className: "text-[10px] font-semibold text-muted-foreground", children: authorInitials(author) }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: author }), _jsx("time", { className: "shrink-0 text-[11px] text-muted-foreground", dateTime: comment.createdAt, children: formatCommentDate(comment.createdAt, formatDate) }), comment.status === "resolved" ? (_jsx("span", { className: "hidden shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground @xs/review:inline-flex", children: resolvedLabel })) : null] }), !bodyIsResolutionNote ? (_jsx(InlineMarkdown, { content: comment.body, className: cn("mt-1 text-foreground", compact ? "text-xs leading-5" : "text-sm leading-5") })) : null, resolutionNote ? (_jsxs("div", { className: "mt-1.5 flex min-w-0 items-start gap-1.5 rounded-md bg-muted/60 px-2 py-1.5 text-muted-foreground", "aria-label": resolvedLabel, children: [_jsx(IconCircleCheck, { className: "mt-0.5 size-3.5 shrink-0" }), _jsx(InlineMarkdown, { content: resolutionNote, className: "min-w-0 text-xs leading-4" })] })) : null] })] }));
|
|
130
131
|
}
|
|
131
132
|
function capabilityAllowsThread(capability, thread) {
|
|
132
133
|
return typeof capability === "function" ? capability(thread) : capability;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exactly one SSE reader may fold a given run into UI state.
|
|
3
|
+
*
|
|
4
|
+
* Two readers attach to the same run routinely: the chat adapter's own stream,
|
|
5
|
+
* and AssistantChat's reconnect reader for runs with no live adapter stream
|
|
6
|
+
* (page reload, tab restore). When both are attached they build two independent
|
|
7
|
+
* accumulators from the same events, and the UI renders both — duplicate tool
|
|
8
|
+
* cards (one spinning, one static) and the same assistant text streaming twice.
|
|
9
|
+
*
|
|
10
|
+
* The previous guard read a React ref (`isRuntimeRunningRef`) at attach time and
|
|
11
|
+
* re-checked it from a 1s poll. That is a race, not a lock: the ref lags a
|
|
12
|
+
* render behind, the poll is skipped while the tab is hidden, and the refs were
|
|
13
|
+
* per-component-instance while MultiTabAssistantChat mounts several instances
|
|
14
|
+
* against one run. Ownership therefore lives here — module scope, one registry
|
|
15
|
+
* per browser tab, claimed and checked synchronously.
|
|
16
|
+
*
|
|
17
|
+
* Claims are advisory in one direction only: a reader that does not hold the
|
|
18
|
+
* claim must not mutate UI state. It may still drain its socket to completion.
|
|
19
|
+
*/
|
|
20
|
+
/** Mint a token identifying one reader. Not shared between readers. */
|
|
21
|
+
export declare function createRunStreamToken(label?: string): symbol;
|
|
22
|
+
/**
|
|
23
|
+
* Take ownership of a run's UI fold. Returns false when another live reader
|
|
24
|
+
* already holds it — the caller must not attach, or must attach read-only.
|
|
25
|
+
* Re-claiming with the same token is a no-op success so retry loops are safe.
|
|
26
|
+
*/
|
|
27
|
+
export declare function claimRunStream(threadId: string, runId: string, token: symbol): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Take ownership even if another reader holds it, and return whether the claim
|
|
30
|
+
* changed hands. The adapter's own stream outranks the reconnect fallback: when
|
|
31
|
+
* the user sends a message the adapter legitimately becomes the owner, and the
|
|
32
|
+
* displaced reader learns it lost via `ownsRunStream`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function preemptRunStream(threadId: string, runId: string, token: symbol): boolean;
|
|
35
|
+
export declare function ownsRunStream(threadId: string, runId: string, token: symbol): boolean;
|
|
36
|
+
/** Release only if still held by this token, so a late unmount cannot free a successor's claim. */
|
|
37
|
+
export declare function releaseRunStream(threadId: string, runId: string, token: symbol): void;
|
|
38
|
+
/** Test seam. */
|
|
39
|
+
export declare function __resetRunStreamOwnership(): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exactly one SSE reader may fold a given run into UI state.
|
|
3
|
+
*
|
|
4
|
+
* Two readers attach to the same run routinely: the chat adapter's own stream,
|
|
5
|
+
* and AssistantChat's reconnect reader for runs with no live adapter stream
|
|
6
|
+
* (page reload, tab restore). When both are attached they build two independent
|
|
7
|
+
* accumulators from the same events, and the UI renders both — duplicate tool
|
|
8
|
+
* cards (one spinning, one static) and the same assistant text streaming twice.
|
|
9
|
+
*
|
|
10
|
+
* The previous guard read a React ref (`isRuntimeRunningRef`) at attach time and
|
|
11
|
+
* re-checked it from a 1s poll. That is a race, not a lock: the ref lags a
|
|
12
|
+
* render behind, the poll is skipped while the tab is hidden, and the refs were
|
|
13
|
+
* per-component-instance while MultiTabAssistantChat mounts several instances
|
|
14
|
+
* against one run. Ownership therefore lives here — module scope, one registry
|
|
15
|
+
* per browser tab, claimed and checked synchronously.
|
|
16
|
+
*
|
|
17
|
+
* Claims are advisory in one direction only: a reader that does not hold the
|
|
18
|
+
* claim must not mutate UI state. It may still drain its socket to completion.
|
|
19
|
+
*/
|
|
20
|
+
const owners = new Map();
|
|
21
|
+
function runKey(threadId, runId) {
|
|
22
|
+
return `${threadId} ${runId}`;
|
|
23
|
+
}
|
|
24
|
+
/** Mint a token identifying one reader. Not shared between readers. */
|
|
25
|
+
export function createRunStreamToken(label) {
|
|
26
|
+
return Symbol(label ?? "run-stream-reader");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Take ownership of a run's UI fold. Returns false when another live reader
|
|
30
|
+
* already holds it — the caller must not attach, or must attach read-only.
|
|
31
|
+
* Re-claiming with the same token is a no-op success so retry loops are safe.
|
|
32
|
+
*/
|
|
33
|
+
export function claimRunStream(threadId, runId, token) {
|
|
34
|
+
const key = runKey(threadId, runId);
|
|
35
|
+
const current = owners.get(key);
|
|
36
|
+
if (current && current !== token)
|
|
37
|
+
return false;
|
|
38
|
+
owners.set(key, token);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Take ownership even if another reader holds it, and return whether the claim
|
|
43
|
+
* changed hands. The adapter's own stream outranks the reconnect fallback: when
|
|
44
|
+
* the user sends a message the adapter legitimately becomes the owner, and the
|
|
45
|
+
* displaced reader learns it lost via `ownsRunStream`.
|
|
46
|
+
*/
|
|
47
|
+
export function preemptRunStream(threadId, runId, token) {
|
|
48
|
+
const key = runKey(threadId, runId);
|
|
49
|
+
const current = owners.get(key);
|
|
50
|
+
owners.set(key, token);
|
|
51
|
+
return current !== token;
|
|
52
|
+
}
|
|
53
|
+
export function ownsRunStream(threadId, runId, token) {
|
|
54
|
+
return owners.get(runKey(threadId, runId)) === token;
|
|
55
|
+
}
|
|
56
|
+
/** Release only if still held by this token, so a late unmount cannot free a successor's claim. */
|
|
57
|
+
export function releaseRunStream(threadId, runId, token) {
|
|
58
|
+
const key = runKey(threadId, runId);
|
|
59
|
+
if (owners.get(key) === token)
|
|
60
|
+
owners.delete(key);
|
|
61
|
+
}
|
|
62
|
+
/** Test seam. */
|
|
63
|
+
export function __resetRunStreamOwnership() {
|
|
64
|
+
owners.clear();
|
|
65
|
+
}
|
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
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, } from "./registry.js";
|
|
2
|
-
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./store.js";
|
|
2
|
+
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./store.js";
|
|
3
3
|
export { createFeatureFlagsPlugin } from "./plugin.js";
|
|
4
4
|
export { createFeatureFlagA2AActionRouteAuth } from "./a2a-action-route.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, } from "./registry.js";
|
|
2
|
-
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, } from "./store.js";
|
|
2
|
+
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, } from "./store.js";
|
|
3
3
|
export { createFeatureFlagsPlugin } from "./plugin.js";
|
|
4
4
|
export { createFeatureFlagA2AActionRouteAuth } from "./a2a-action-route.js";
|
|
@@ -19,6 +19,16 @@ export declare const FEATURE_FLAG_SETTINGS_PREFIX = "feature-flag:";
|
|
|
19
19
|
export declare function defaultFeatureFlagRules(): FeatureFlagRules;
|
|
20
20
|
export declare function normalizeFeatureFlagRules(value: unknown): FeatureFlagRules;
|
|
21
21
|
export declare function getFeatureFlagRules(key: string, scope: Pick<FeatureFlagScope, "orgId">): Promise<FeatureFlagRules>;
|
|
22
|
+
/**
|
|
23
|
+
* Anonymous discovery hint for a rollout that may be scoped to an org.
|
|
24
|
+
*
|
|
25
|
+
* This deliberately answers only whether some active rollout exists. It does
|
|
26
|
+
* not reveal the target email or organization, and callers must still run
|
|
27
|
+
* `evaluateFeatureFlag` with the authenticated scope before granting access.
|
|
28
|
+
* Without this separate hint, an org-only rollout is invisible to Desktop
|
|
29
|
+
* before the user has authenticated and the org can be resolved.
|
|
30
|
+
*/
|
|
31
|
+
export declare function hasActiveFeatureFlagRollout(key: string): Promise<boolean>;
|
|
22
32
|
/**
|
|
23
33
|
* Atomically derive one flag's scoped rules. An org's first override starts
|
|
24
34
|
* from the global fallback, then becomes independently CAS-protected.
|
|
@@ -1,10 +1,73 @@
|
|
|
1
|
+
import { getDbExec, isPostgres } from "../db/client.js";
|
|
1
2
|
import { getOrgSetting, mutateOrgSetting } from "../settings/org-settings.js";
|
|
2
3
|
import { getSetting, mutateSetting } from "../settings/store.js";
|
|
3
4
|
import { getFeatureFlagDefinition, } from "./registry.js";
|
|
4
5
|
export const FEATURE_FLAG_SETTINGS_PREFIX = "feature-flag:";
|
|
6
|
+
const FEATURE_FLAG_ROLLOUT_INDEX_PREFIX = "feature-flag-rollout-index:";
|
|
5
7
|
function settingKey(key) {
|
|
6
8
|
return `${FEATURE_FLAG_SETTINGS_PREFIX}${key}`;
|
|
7
9
|
}
|
|
10
|
+
function rolloutIndexKey(key) {
|
|
11
|
+
return `${FEATURE_FLAG_ROLLOUT_INDEX_PREFIX}${key}`;
|
|
12
|
+
}
|
|
13
|
+
function parseStoredRules(value) {
|
|
14
|
+
if (typeof value === "string")
|
|
15
|
+
return normalizeFeatureFlagRules(JSON.parse(value));
|
|
16
|
+
return normalizeFeatureFlagRules(value);
|
|
17
|
+
}
|
|
18
|
+
function hasActiveRollout(rules) {
|
|
19
|
+
return (rules.mode === "on" ||
|
|
20
|
+
(rules.mode === "rules" &&
|
|
21
|
+
(rules.emails.length > 0 ||
|
|
22
|
+
rules.orgIds.length > 0 ||
|
|
23
|
+
rules.percentage > 0)));
|
|
24
|
+
}
|
|
25
|
+
function normalizeFeatureFlagRolloutIndex(value) {
|
|
26
|
+
if (!value || typeof value !== "object")
|
|
27
|
+
return null;
|
|
28
|
+
const raw = value;
|
|
29
|
+
const orgIds = Array.isArray(raw.orgIds)
|
|
30
|
+
? [
|
|
31
|
+
...new Set(raw.orgIds.filter((item) => typeof item === "string")),
|
|
32
|
+
]
|
|
33
|
+
.map((orgId) => orgId.trim())
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
.sort()
|
|
36
|
+
: [];
|
|
37
|
+
return {
|
|
38
|
+
version: 1,
|
|
39
|
+
global: raw.global === true,
|
|
40
|
+
orgIds,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function activeFeatureFlagRolloutIndex(index) {
|
|
44
|
+
return index.global || index.orgIds.length > 0;
|
|
45
|
+
}
|
|
46
|
+
async function syncFeatureFlagRolloutIndex(key, scope, rules) {
|
|
47
|
+
const indexKey = rolloutIndexKey(key);
|
|
48
|
+
await mutateSetting(indexKey, async (current) => {
|
|
49
|
+
const next = normalizeFeatureFlagRolloutIndex(current) ?? {
|
|
50
|
+
version: 1,
|
|
51
|
+
global: false,
|
|
52
|
+
orgIds: [],
|
|
53
|
+
};
|
|
54
|
+
if (scope.orgId?.trim()) {
|
|
55
|
+
const orgId = scope.orgId.trim();
|
|
56
|
+
const active = hasActiveRollout(rules);
|
|
57
|
+
const orgIds = active
|
|
58
|
+
? [...new Set([...next.orgIds, orgId])].sort()
|
|
59
|
+
: next.orgIds.filter((value) => value !== orgId);
|
|
60
|
+
return {
|
|
61
|
+
...next,
|
|
62
|
+
orgIds,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
...next,
|
|
67
|
+
global: hasActiveRollout(rules),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
8
71
|
export function defaultFeatureFlagRules() {
|
|
9
72
|
return {
|
|
10
73
|
version: 1,
|
|
@@ -66,6 +129,52 @@ export async function getFeatureFlagRules(key, scope) {
|
|
|
66
129
|
]);
|
|
67
130
|
return normalizeFeatureFlagRules(orgStored ?? globalStored);
|
|
68
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Anonymous discovery hint for a rollout that may be scoped to an org.
|
|
134
|
+
*
|
|
135
|
+
* This deliberately answers only whether some active rollout exists. It does
|
|
136
|
+
* not reveal the target email or organization, and callers must still run
|
|
137
|
+
* `evaluateFeatureFlag` with the authenticated scope before granting access.
|
|
138
|
+
* Without this separate hint, an org-only rollout is invisible to Desktop
|
|
139
|
+
* before the user has authenticated and the org can be resolved.
|
|
140
|
+
*/
|
|
141
|
+
export async function hasActiveFeatureFlagRollout(key) {
|
|
142
|
+
if (!getFeatureFlagDefinition(key))
|
|
143
|
+
return false;
|
|
144
|
+
const indexKey = rolloutIndexKey(key);
|
|
145
|
+
const storedIndex = normalizeFeatureFlagRolloutIndex(await getSetting(indexKey));
|
|
146
|
+
if (storedIndex)
|
|
147
|
+
return activeFeatureFlagRolloutIndex(storedIndex);
|
|
148
|
+
const globalStored = await getSetting(settingKey(key));
|
|
149
|
+
const globalActive = hasActiveRollout(parseStoredRules(globalStored));
|
|
150
|
+
if (globalActive) {
|
|
151
|
+
await mutateSetting(indexKey, async () => ({
|
|
152
|
+
version: 1,
|
|
153
|
+
global: true,
|
|
154
|
+
orgIds: [],
|
|
155
|
+
}));
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
const table = isPostgres() ? "public.settings" : "settings";
|
|
159
|
+
const { rows } = await getDbExec().execute({
|
|
160
|
+
sql: `SELECT key, value FROM ${table} WHERE key LIKE ?`,
|
|
161
|
+
args: [`o:%:${settingKey(key)}`],
|
|
162
|
+
});
|
|
163
|
+
const orgIds = rows
|
|
164
|
+
.filter((row) => hasActiveRollout(parseStoredRules(row.value)))
|
|
165
|
+
.map((row) => {
|
|
166
|
+
const match = /^o:([^:]+):/.exec(row.key ?? "");
|
|
167
|
+
return match?.[1] ?? null;
|
|
168
|
+
})
|
|
169
|
+
.filter((orgId) => Boolean(orgId))
|
|
170
|
+
.sort();
|
|
171
|
+
await mutateSetting(indexKey, async () => ({
|
|
172
|
+
version: 1,
|
|
173
|
+
global: false,
|
|
174
|
+
orgIds,
|
|
175
|
+
}));
|
|
176
|
+
return orgIds.length > 0;
|
|
177
|
+
}
|
|
69
178
|
/**
|
|
70
179
|
* Atomically derive one flag's scoped rules. An org's first override starts
|
|
71
180
|
* from the global fallback, then becomes independently CAS-protected.
|
|
@@ -85,7 +194,9 @@ export async function mutateFeatureFlagRules(key, scope, updater) {
|
|
|
85
194
|
const persisted = scope.orgId?.trim()
|
|
86
195
|
? await mutateOrgSetting(scope.orgId, settingKey(key), mutate)
|
|
87
196
|
: await mutateSetting(settingKey(key), mutate);
|
|
88
|
-
|
|
197
|
+
const normalized = normalizeFeatureFlagRules(persisted);
|
|
198
|
+
await syncFeatureFlagRolloutIndex(key, scope, normalized);
|
|
199
|
+
return normalized;
|
|
89
200
|
}
|
|
90
201
|
function rolloutBucket(input) {
|
|
91
202
|
// FNV-1a is deliberately tiny, deterministic, and independent of runtime.
|
|
@@ -55,6 +55,10 @@ const ALLOWLIST_EXACT = new Set([
|
|
|
55
55
|
"AWS_LAMBDA_FUNCTION_NAME",
|
|
56
56
|
"BETTER_AUTH_SECRET",
|
|
57
57
|
"BETTER_AUTH_URL",
|
|
58
|
+
// Public deployment identity/configuration. These select the app origin and
|
|
59
|
+
// explicitly registered SSO clients; they are not user credentials.
|
|
60
|
+
"APP_URL",
|
|
61
|
+
"IDENTITY_SSO_APP_REGISTRY_JSON",
|
|
58
62
|
"NOTION_CLIENT_ID",
|
|
59
63
|
"NOTION_CLIENT_SECRET",
|
|
60
64
|
"NOTION_STATE_SECRET",
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./config.js";
|
|
|
2
2
|
export { addContextToAgentChat, appendAgentChatContextToMessage, clearAgentChatContext, formatAgentChatContextItemsForPrompt, listAgentChatContext, refreshAgentChatContext, removeAgentChatContextItem, sendToAgentChat, sendToAgentChatAndConfirm, setAgentChatContextItem, setContextToAgentChat, isEmbedMcpChatBridgeActive, useAgentChatContext, useAgentChatGenerating, useDevMode, useSendToAgentChat, AGENT_NATIVE_MCP_APP_HOST_MESSAGE_TYPES, getMcpAppHostContext, openMcpAppHostLink, requestMcpAppDisplayMode, sendMcpAppHostMessage, updateMcpAppModelContext, useMcpAppHostContext, CodeRequiredDialog, AgentNativeI18nProvider, LanguagePicker, getLocaleInitScript, localeDirection, normalizeLocaleCode, normalizeLocalePreference, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, useFormatters, useLocale, useT, DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, useDbSync, useFileWatcher, useSession, cn, ApiKeySettings, type AgentChatContextItem, type AgentChatContextMessage, type AgentChatContextMutationOptions, type AgentChatContextRemoveOptions, type AgentChatContextSetOptions, type AgentChatContextState, type AgentChatMessage, type AgentNativeMcpAppHostMessageType, type McpAppDisplayMode, type McpAppHostChatMessage, type McpAppHostCapabilities, type McpAppHostContext, type McpAppHostContextSnapshot, type McpAppModelContextContentPart, type McpAppModelContextUpdate, type CodeRequiredDialogProps, type AuthSession, type UseAgentChatContextResult, type AgentNativeI18nCatalog, type AgentNativeI18nProviderProps, type LocaleCode, type LocaleHydrationPayload, type LocaleMessages, type LocaleMetadata, type LocalePreference, type LocalizationPreference, } from "./client/index.js";
|
|
3
3
|
export { agentChat } from "./shared/index.js";
|
|
4
4
|
export { parseArgs, camelCaseArgs } from "./scripts/parse-args.js";
|
|
5
|
-
export { defineAction, AgentActionStopError, isAgentActionStopError, type ActionHttpConfig, type AgentActionStopOptions, 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";
|
|
5
|
+
export { defineAction, ActionContractError, isActionContractError, type ActionContractErrorOptions, AgentActionStopError, isAgentActionStopError, type ActionHttpConfig, type AgentActionStopOptions, 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";
|
|
6
6
|
export { normalizeUserProfileName, USER_PROFILE_SETTING_KEY, type UserProfile, } from "./user-profile/index.js";
|
|
7
7
|
export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, ACTION_CHAT_UI_WORKSPACE_FILE_RENDERER, type ActionChatUIConfig, } from "./action-ui.js";
|
|
8
8
|
export { DATA_CHART_WIDGET, DATA_INSIGHTS_WIDGET, DATA_TABLE_WIDGET, createDataChartWidgetResult, createDataInsightsWidgetResult, createDataTableWidgetResult, dataChartWidgetResultSchema, dataChartWidgetSchema, dataInsightsWidgetResultSchema, dataTableWidgetResultSchema, dataTableWidgetSchema, dataWidgetResultSchema, isDataChartWidget, isDataTableWidget, isDataWidgetResult, normalizeDataWidgetKind, normalizeDataWidgetResult, type DataChartSeriesDefinition, type DataChartWidget, type DataChartWidgetResult, type DataChartWidgetResultInput, type DataInsightsWidgetResult, type DataInsightsWidgetResultInput, type DataTableColumn, type DataTableWidget, type DataTableWidgetResult, type DataTableWidgetResultInput, type DataWidgetDisplay, type DataWidgetKind, type DataWidgetResult, type DataWidgetResultMetadata, } from "./data-widgets/index.js";
|
package/dist/index.browser.js
CHANGED
|
@@ -9,7 +9,7 @@ export { agentChat } from "./shared/index.js";
|
|
|
9
9
|
// Pure utilities (no Node.js deps — safe for browser and SSR)
|
|
10
10
|
export { parseArgs, camelCaseArgs } from "./scripts/parse-args.js";
|
|
11
11
|
// defineAction — used by template actions, no Node.js deps
|
|
12
|
-
export { defineAction, AgentActionStopError, isAgentActionStopError, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "./action.js";
|
|
12
|
+
export { defineAction, ActionContractError, isActionContractError, AgentActionStopError, isAgentActionStopError, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "./action.js";
|
|
13
13
|
export { normalizeUserProfileName, USER_PROFILE_SETTING_KEY, } from "./user-profile/index.js";
|
|
14
14
|
export { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, ACTION_CHAT_UI_WORKSPACE_FILE_RENDERER, } from "./action-ui.js";
|
|
15
15
|
export { DATA_CHART_WIDGET, DATA_INSIGHTS_WIDGET, DATA_TABLE_WIDGET, createDataChartWidgetResult, createDataInsightsWidgetResult, createDataTableWidgetResult, dataChartWidgetResultSchema, dataChartWidgetSchema, dataInsightsWidgetResultSchema, dataTableWidgetResultSchema, dataTableWidgetSchema, dataWidgetResultSchema, isDataChartWidget, isDataTableWidget, isDataWidgetResult, normalizeDataWidgetKind, normalizeDataWidgetResult, } from "./data-widgets/index.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./config.js";
|
|
2
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";
|
|
3
|
-
export { defineAction, 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";
|
|
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";
|
|
6
6
|
export { embedRoute, type EmbedRouteContext, type EmbedRouteOptions, type EmbedRoutePathBuilder, type EmbedRouteResult, } from "./mcp/embed-route.js";
|
|
@@ -11,7 +11,7 @@ export { createAgentChatPlugin, defaultAgentChatPlugin, type AgentChatPluginOpti
|
|
|
11
11
|
export { createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, type AgentNativeEmbeddedPluginOptions, } from "./server/embedded.js";
|
|
12
12
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, type AutomationCapabilities, type BuiltInChannelId, type ChannelCapabilities, type IntegrationAvailability, type IntegrationCatalogEntry, type IntegrationCategory, type IntegrationCredentialRequirement, type IntegrationIconKey, type IntegrationSupportMaturity, } from "./integrations/catalog.js";
|
|
13
13
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, type AutomationCallbackAuthentication, type AutomationCallbackInput, type AutomationCallbackResult, type AutomationInboundDefinition, type AutomationInvocation, type AutomationInvocationResult, type AutomationInvocationStatus, type AutomationOutboundDefinition, type AutomationResponseMode, type AutomationRetryPolicy, type AutomationRuntime, type AutomationRuntimeOptions, type AutomationWorkflowCapabilities, type AutomationWorkflowDefinition, type JsonSchema, } from "./automation/index.js";
|
|
14
|
-
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./feature-flags/index.js";
|
|
14
|
+
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./feature-flags/index.js";
|
|
15
15
|
export { createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, type CreateServerOptions, type SSEHandlerOptions, type AuthSession, type AuthOptions, } from "./server/index.js";
|
|
16
16
|
export { agentChat, type AgentChatCallOptions, type AgentChatResponse, } from "./shared/index.js";
|
|
17
17
|
export { EMBED_MODE_QUERY_PARAM, EMBED_SESSION_COOKIE, EMBED_START_PATH, EMBED_TOKEN_QUERY_PARAM, } from "./shared/embed-auth.js";
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export * from "./config.js";
|
|
|
5
5
|
export { createProductionAgentHandler, DEFAULT_MODEL,
|
|
6
6
|
// In-loop processors (observers/guardrails for runAgentLoop)
|
|
7
7
|
TripWire, } from "./agent/index.js";
|
|
8
|
-
export { defineAction, AgentActionStopError, isAgentActionStopError, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "./action.js";
|
|
8
|
+
export { defineAction, ActionContractError, isActionContractError, AgentActionStopError, isAgentActionStopError, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "./action.js";
|
|
9
9
|
export * from "./user-profile/index.js";
|
|
10
10
|
export { embedApp, MCP_APP_REQUEST_ORIGIN_CSP_SOURCE, } from "./mcp/embed-app.js";
|
|
11
11
|
export { embedRoute, } from "./mcp/embed-route.js";
|
|
@@ -16,7 +16,7 @@ export { createAgentChatPlugin, defaultAgentChatPlugin, } from "./server/agent-c
|
|
|
16
16
|
export { createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, } from "./server/embedded.js";
|
|
17
17
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, } from "./integrations/catalog.js";
|
|
18
18
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, } from "./automation/index.js";
|
|
19
|
-
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, } from "./feature-flags/index.js";
|
|
19
|
+
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, } from "./feature-flags/index.js";
|
|
20
20
|
// Server
|
|
21
21
|
export { createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, } from "./server/index.js";
|
|
22
22
|
// Client
|
|
@@ -858,7 +858,11 @@ function markdownToSlackMrkdwn(text) {
|
|
|
858
858
|
// pathological "**" sequence that exhibits super-linear backtracking.
|
|
859
859
|
// Newlines are allowed because `[^*]` excludes only the asterisk
|
|
860
860
|
// itself, so multi-line bold spans still match.
|
|
861
|
-
.replace(/\*\*([^*]{1,5000})\*\*/g, "*$1*")
|
|
861
|
+
.replace(/\*\*([^*]{1,5000})\*\*/g, "*$1*")
|
|
862
|
+
// Agent output sometimes uses Markdown-style bare Slack user IDs.
|
|
863
|
+
// Leave native `<@...>` mentions untouched while converting the bare
|
|
864
|
+
// user/member forms Slack expects in mrkdwn.
|
|
865
|
+
.replace(/(?<![<\w])@([UW][A-Z0-9]+)(?![A-Z0-9])/g, "<@$1>"));
|
|
862
866
|
}
|
|
863
867
|
/**
|
|
864
868
|
* Optionally set Slack's native Agent status indicator (the small "is
|
|
@@ -321,6 +321,7 @@ const messages = {
|
|
|
321
321
|
openApp: "Open app",
|
|
322
322
|
notDispatchOrWorkspaceApp: " a Dispatch tab or a workspace app in this workspace.",
|
|
323
323
|
agentsDescription: "Dispatch can delegate to the built-in app suite over A2A by default. Add extra agents here only if you want to route work to apps outside that built-in set.",
|
|
324
|
+
simpleAgentsDescription: "Create reusable agents in minutes, or import a setup you already made in Claude or another agent tool.",
|
|
324
325
|
mcpAccessUpdated: "Agent integration access updated",
|
|
325
326
|
selectAppForMcp: "Select at least one app, or expose all apps.",
|
|
326
327
|
mcpUrlCopied: "Agent integration URL copied",
|