@btst/stack 4.1.0 → 4.2.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/README.md +2 -2
- package/dist/packages/stack/src/plugins/ai-chat/api/operations.cjs +15 -9
- package/dist/packages/stack/src/plugins/ai-chat/api/operations.mjs +16 -10
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +28 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +29 -2
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +5 -0
- package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +5 -0
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +91 -8
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +91 -8
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +76 -3
- package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +80 -7
- package/dist/packages/stack/src/plugins/ai-chat/client/components/tool-call-display.cjs +17 -0
- package/dist/packages/stack/src/plugins/ai-chat/client/components/tool-call-display.mjs +18 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/context/chat-analytics.cjs +42 -0
- package/dist/packages/stack/src/plugins/ai-chat/client/context/chat-analytics.mjs +39 -0
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +2 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +2 -1
- package/dist/plugins/ai-chat/api/index.d.cts +2 -2
- package/dist/plugins/ai-chat/api/index.d.mts +2 -2
- package/dist/plugins/ai-chat/api/index.d.ts +2 -2
- package/dist/plugins/ai-chat/client/components/index.d.cts +2 -1
- package/dist/plugins/ai-chat/client/components/index.d.mts +2 -1
- package/dist/plugins/ai-chat/client/components/index.d.ts +2 -1
- package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +4 -0
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +6 -2
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +6 -2
- package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +6 -2
- package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +4 -1
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +2 -2
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +2 -2
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +2 -2
- package/dist/plugins/ai-chat/client/index.d.cts +7 -3
- package/dist/plugins/ai-chat/client/index.d.mts +7 -3
- package/dist/plugins/ai-chat/client/index.d.ts +7 -3
- package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
- package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
- package/dist/plugins/blog/api/index.d.cts +2 -2
- package/dist/plugins/blog/api/index.d.mts +2 -2
- package/dist/plugins/blog/api/index.d.ts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +2 -2
- package/dist/plugins/blog/client/index.d.mts +2 -2
- package/dist/plugins/blog/client/index.d.ts +2 -2
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/shared/{stack.CjCSDfWy.d.mts → stack.94kN3pEK.d.mts} +5 -5
- package/dist/shared/{stack.B5yPgHsp.d.mts → stack.B7Mj74BQ.d.mts} +18 -2
- package/dist/shared/{stack.BGzgFx3R.d.cts → stack.BTStHVTy.d.cts} +5 -5
- package/dist/shared/{stack.rVF0f509.d.mts → stack.C-eQN_Jt.d.ts} +60 -4
- package/dist/shared/{stack.rVF0f509.d.ts → stack.C5FZr-jJ.d.mts} +60 -4
- package/dist/shared/{stack.Dvy7FmaA.d.mts → stack.CTneIW0u.d.mts} +37 -37
- package/dist/shared/{stack.BOZRaVpu.d.cts → stack.Ce6V7eDj.d.cts} +37 -37
- package/dist/shared/{stack.DlBoNqYu.d.ts → stack.D5b9l24t.d.ts} +37 -37
- package/dist/shared/{stack.3Sr6qRtT.d.ts → stack.DBH1Bjko.d.ts} +18 -2
- package/dist/shared/{stack.Dpg_JjIo.d.ts → stack.DfrRYOIl.d.ts} +5 -5
- package/dist/shared/{stack.C4oVW2qK.d.cts → stack.Dgt3MCtW.d.cts} +18 -2
- package/dist/shared/{stack.rVF0f509.d.cts → stack.xAiy2VtO.d.cts} +60 -4
- package/package.json +1 -1
- package/src/plugins/ai-chat/__tests__/authorization.test.ts +106 -1
- package/src/plugins/ai-chat/__tests__/classnames-overrides.test.tsx +4 -1
- package/src/plugins/ai-chat/__tests__/page-content.test.ts +177 -0
- package/src/plugins/ai-chat/__tests__/page-widget.test.tsx +573 -0
- package/src/plugins/ai-chat/api/operations.ts +29 -13
- package/src/plugins/ai-chat/api/page-tools.ts +56 -2
- package/src/plugins/ai-chat/api/plugin.ts +13 -0
- package/src/plugins/ai-chat/client/analytics.ts +35 -0
- package/src/plugins/ai-chat/client/components/chat-interface.tsx +113 -10
- package/src/plugins/ai-chat/client/components/chat-layout.tsx +118 -7
- package/src/plugins/ai-chat/client/components/tool-call-display.tsx +29 -1
- package/src/plugins/ai-chat/client/context/chat-analytics.tsx +46 -0
- package/src/plugins/ai-chat/client/context/page-ai-context.tsx +9 -1
- package/src/plugins/ai-chat/client/index.ts +2 -0
- package/src/plugins/ai-chat/client/localization/index.ts +8 -0
- package/src/plugins/ai-chat/client/overrides.ts +5 -0
- package/src/plugins/ai-chat/client/plugin.tsx +3 -0
- package/dist/shared/{stack.Csi-4Mgz.d.cts → stack.CKc_Bais.d.cts} +7 -7
- package/dist/shared/{stack.Csi-4Mgz.d.mts → stack.CKc_Bais.d.mts} +7 -7
- package/dist/shared/{stack.Csi-4Mgz.d.ts → stack.CKc_Bais.d.ts} +7 -7
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useCallback, useContext, useRef } from "react";
|
|
4
|
+
import { usePluginOverrides, useStack } from "@btst/stack/context";
|
|
5
|
+
import { usePageAIContext } from "./page-ai-context";
|
|
6
|
+
import { resolveAiChatMode, type AiChatPluginOverrides } from "../overrides";
|
|
7
|
+
import type { AiChatAnalyticsEvent } from "../analytics";
|
|
8
|
+
|
|
9
|
+
export const ChatAnalyticsPageKey = createContext<string | undefined>(
|
|
10
|
+
undefined,
|
|
11
|
+
);
|
|
12
|
+
type EventDetails<T> = T extends unknown
|
|
13
|
+
? Omit<T, "pageKey" | "routeName" | "mode">
|
|
14
|
+
: never;
|
|
15
|
+
|
|
16
|
+
export function useChatAnalytics() {
|
|
17
|
+
const { onAnalyticsEvent } = usePluginOverrides<
|
|
18
|
+
AiChatPluginOverrides,
|
|
19
|
+
Partial<AiChatPluginOverrides>
|
|
20
|
+
>("aiChat", {});
|
|
21
|
+
const { plugins } = useStack();
|
|
22
|
+
const pageKey = useContext(ChatAnalyticsPageKey);
|
|
23
|
+
const routeName = usePageAIContext()?.routeName;
|
|
24
|
+
const latest = useRef({
|
|
25
|
+
onAnalyticsEvent,
|
|
26
|
+
pageKey,
|
|
27
|
+
routeName,
|
|
28
|
+
mode: resolveAiChatMode(plugins?.aiChat?.config),
|
|
29
|
+
});
|
|
30
|
+
latest.current = {
|
|
31
|
+
onAnalyticsEvent,
|
|
32
|
+
pageKey,
|
|
33
|
+
routeName,
|
|
34
|
+
mode: resolveAiChatMode(plugins?.aiChat?.config),
|
|
35
|
+
};
|
|
36
|
+
return useCallback((event: EventDetails<AiChatAnalyticsEvent>) => {
|
|
37
|
+
const { onAnalyticsEvent: callback, ...context } = latest.current;
|
|
38
|
+
try {
|
|
39
|
+
void Promise.resolve(callback?.({ ...context, ...event })).catch(
|
|
40
|
+
() => {},
|
|
41
|
+
);
|
|
42
|
+
} catch {
|
|
43
|
+
// Optional instrumentation must never interrupt chat interactions.
|
|
44
|
+
}
|
|
45
|
+
}, []);
|
|
46
|
+
}
|
|
@@ -33,7 +33,8 @@ export interface PageAIContextConfig {
|
|
|
33
33
|
/**
|
|
34
34
|
* Human-readable description of the current page and its content.
|
|
35
35
|
* Injected into the AI system prompt so it understands what the user is looking at.
|
|
36
|
-
*
|
|
36
|
+
* Limited to 16,000 characters server-side. For longer content, pass a page
|
|
37
|
+
* path and configure the backend pageContent resolver.
|
|
37
38
|
*/
|
|
38
39
|
pageDescription: string;
|
|
39
40
|
|
|
@@ -74,6 +75,11 @@ const PageAIAPIContext = createContext<PageAIAPIContextValue | null>(null);
|
|
|
74
75
|
*/
|
|
75
76
|
const PageAIVersionContext = createContext<number>(0);
|
|
76
77
|
|
|
78
|
+
/** Instance-local context used by ChatLayout; undefined inherits page registrations. */
|
|
79
|
+
export const PageAIContextScope = createContext<
|
|
80
|
+
PageAIContextConfig | null | undefined
|
|
81
|
+
>(undefined);
|
|
82
|
+
|
|
77
83
|
/**
|
|
78
84
|
* Provider that enables route-aware AI context across the app.
|
|
79
85
|
*
|
|
@@ -235,6 +241,8 @@ export function usePageAIContext(): PageAIContextConfig | null {
|
|
|
235
241
|
// registers or unregisters context, then read the latest active config.
|
|
236
242
|
useContext(PageAIVersionContext);
|
|
237
243
|
const ctx = useContext(PageAIAPIContext);
|
|
244
|
+
const scoped = useContext(PageAIContextScope);
|
|
245
|
+
if (scoped !== undefined) return scoped;
|
|
238
246
|
if (!ctx) return null;
|
|
239
247
|
return ctx.getActive();
|
|
240
248
|
}
|
|
@@ -87,6 +87,10 @@ export interface AiChatLocalization {
|
|
|
87
87
|
A11Y_CLEAR_CHAT: string;
|
|
88
88
|
A11Y_CLOSE_CHAT: string;
|
|
89
89
|
A11Y_OPEN_CHAT: string;
|
|
90
|
+
A11Y_DISMISS_CHAT_TIP: string;
|
|
91
|
+
PAGE_CONTENT_READING: string;
|
|
92
|
+
PAGE_CONTENT_READ: string;
|
|
93
|
+
PAGE_CONTENT_ERROR: string;
|
|
90
94
|
A11Y_OPEN_MENU: string;
|
|
91
95
|
A11Y_CLOSE_SIDEBAR: string;
|
|
92
96
|
A11Y_OPEN_SIDEBAR: string;
|
|
@@ -191,6 +195,10 @@ export const AI_CHAT_LOCALIZATION: AiChatLocalization = {
|
|
|
191
195
|
A11Y_CLEAR_CHAT: "Clear chat",
|
|
192
196
|
A11Y_CLOSE_CHAT: "Close chat",
|
|
193
197
|
A11Y_OPEN_CHAT: "Open chat",
|
|
198
|
+
A11Y_DISMISS_CHAT_TIP: "Dismiss chat tip",
|
|
199
|
+
PAGE_CONTENT_READING: "Reading page content…",
|
|
200
|
+
PAGE_CONTENT_READ: "Read page content",
|
|
201
|
+
PAGE_CONTENT_ERROR: "Unable to read this page.",
|
|
194
202
|
A11Y_OPEN_MENU: "Open menu",
|
|
195
203
|
A11Y_CLOSE_SIDEBAR: "Close sidebar",
|
|
196
204
|
A11Y_OPEN_SIDEBAR: "Open sidebar",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AiChatAnalyticsEvent } from "./analytics";
|
|
1
2
|
import type { ComponentType } from "react";
|
|
2
3
|
import { normalizePath } from "@btst/stack/client";
|
|
3
4
|
import type { AiChatLocalization } from "./localization";
|
|
@@ -13,6 +14,8 @@ export type AiChatMode = "authenticated" | "public";
|
|
|
13
14
|
export interface AiChatProviderConfig {
|
|
14
15
|
/** Conversation behavior selected by `aiChatClientPlugin()`. */
|
|
15
16
|
readonly mode: AiChatMode;
|
|
17
|
+
/** Whether built-in page reader permission checks and status UI are enabled. */
|
|
18
|
+
readonly pageContent?: boolean;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
/** Resolve the registered AI Chat client factory mode. */
|
|
@@ -143,6 +146,8 @@ export interface RouteContext {
|
|
|
143
146
|
* plugin-specific components and behavior.
|
|
144
147
|
*/
|
|
145
148
|
export interface AiChatPluginOverrides {
|
|
149
|
+
/** Optional content-free usage telemetry. Exceptions and rejections are isolated from chat. */
|
|
150
|
+
onAnalyticsEvent?: (event: AiChatAnalyticsEvent) => void | Promise<void>;
|
|
146
151
|
/**
|
|
147
152
|
* Function used to upload a file and return its URL.
|
|
148
153
|
* Called for images, PDFs, text files, and other supported file types.
|
|
@@ -67,6 +67,8 @@ export interface AiChatClientConfig {
|
|
|
67
67
|
* @default 'authenticated'
|
|
68
68
|
*/
|
|
69
69
|
mode?: AiChatMode;
|
|
70
|
+
/** Enable built-in readPage permission checks and compact status alongside backend pageContent. */
|
|
71
|
+
pageContent?: boolean;
|
|
70
72
|
|
|
71
73
|
/** Optional SEO configuration for meta tags */
|
|
72
74
|
seo?: {
|
|
@@ -560,6 +562,7 @@ export const aiChatClientPlugin = (config: AiChatClientConfig = {}) =>
|
|
|
560
562
|
id: "aiChat",
|
|
561
563
|
providerConfig: {
|
|
562
564
|
mode: config.mode ?? "authenticated",
|
|
565
|
+
...(config.pageContent ? { pageContent: true } : {}),
|
|
563
566
|
} satisfies AiChatProviderConfig,
|
|
564
567
|
resolve: (runtime) => resolveAiChatClientPlugin({ ...config, runtime }),
|
|
565
568
|
});
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const createPostSchema: z.ZodObject<{
|
|
4
|
-
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
5
|
-
name: z.ZodString;
|
|
6
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
7
|
-
id: z.ZodString;
|
|
8
|
-
name: z.ZodString;
|
|
9
|
-
slug: z.ZodString;
|
|
10
|
-
}, z.core.$strip>]>>>>;
|
|
11
4
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
5
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
13
6
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -17,6 +10,13 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
17
10
|
excerpt: z.ZodString;
|
|
18
11
|
image: z.ZodOptional<z.ZodString>;
|
|
19
12
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
13
|
+
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
14
|
+
name: z.ZodString;
|
|
15
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
slug: z.ZodString;
|
|
19
|
+
}, z.core.$strip>]>>>>;
|
|
20
20
|
}, z.core.$strip>;
|
|
21
21
|
declare const updatePostSchema: z.ZodObject<{
|
|
22
22
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const createPostSchema: z.ZodObject<{
|
|
4
|
-
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
5
|
-
name: z.ZodString;
|
|
6
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
7
|
-
id: z.ZodString;
|
|
8
|
-
name: z.ZodString;
|
|
9
|
-
slug: z.ZodString;
|
|
10
|
-
}, z.core.$strip>]>>>>;
|
|
11
4
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
5
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
13
6
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -17,6 +10,13 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
17
10
|
excerpt: z.ZodString;
|
|
18
11
|
image: z.ZodOptional<z.ZodString>;
|
|
19
12
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
13
|
+
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
14
|
+
name: z.ZodString;
|
|
15
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
slug: z.ZodString;
|
|
19
|
+
}, z.core.$strip>]>>>>;
|
|
20
20
|
}, z.core.$strip>;
|
|
21
21
|
declare const updatePostSchema: z.ZodObject<{
|
|
22
22
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
declare const createPostSchema: z.ZodObject<{
|
|
4
|
-
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
5
|
-
name: z.ZodString;
|
|
6
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
7
|
-
id: z.ZodString;
|
|
8
|
-
name: z.ZodString;
|
|
9
|
-
slug: z.ZodString;
|
|
10
|
-
}, z.core.$strip>]>>>>;
|
|
11
4
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
5
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
13
6
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
@@ -17,6 +10,13 @@ declare const createPostSchema: z.ZodObject<{
|
|
|
17
10
|
excerpt: z.ZodString;
|
|
18
11
|
image: z.ZodOptional<z.ZodString>;
|
|
19
12
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
13
|
+
tags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
14
|
+
name: z.ZodString;
|
|
15
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
slug: z.ZodString;
|
|
19
|
+
}, z.core.$strip>]>>>>;
|
|
20
20
|
}, z.core.$strip>;
|
|
21
21
|
declare const updatePostSchema: z.ZodObject<{
|
|
22
22
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|