@super_studio/ecforce-ai-agent-react 1.4.0-canary.1 → 1.4.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/dist/components/ai-icon.mjs +2 -3
- package/dist/components/ai-icon.mjs.map +1 -1
- package/dist/components/chatbot-frame.mjs +1 -1
- package/dist/components/chatbot-sheet.d.mts +2 -2
- package/dist/components/chatbot-sheet.mjs +2 -2
- package/dist/components/chatbot-sheet.mjs.map +1 -1
- package/dist/components/provider/chatbot-provider.d.mts +2 -2
- package/dist/components/provider/chatbot-provider.mjs.map +1 -1
- package/dist/components/provider/use-chatbot-frame-handler.mjs.map +1 -1
- package/dist/components/sheet.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/package.json +2 -2
- package/src/components/ai-icon.tsx +7 -7
- package/src/components/chatbot-sheet.tsx +2 -2
- package/src/components/provider/chatbot-provider.tsx +1 -1
- package/src/components/provider/use-chatbot-frame-handler.tsx +1 -1
- package/src/components/sheet.tsx +3 -3
- package/src/index.ts +1 -1
|
@@ -2,10 +2,9 @@ import { PROD_CHATBOT_URL } from "../lib/constants.mjs";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/components/ai-icon.tsx
|
|
5
|
-
|
|
6
|
-
function AiIcon({ width = 24, height = 24 }) {
|
|
5
|
+
function AiIcon({ width = 24, height = 24, baseUrl = PROD_CHATBOT_URL }) {
|
|
7
6
|
return /* @__PURE__ */ jsx("img", {
|
|
8
|
-
src:
|
|
7
|
+
src: new URL("/images/ai-icon.gif", baseUrl).toString(),
|
|
9
8
|
width,
|
|
10
9
|
height,
|
|
11
10
|
alt: "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-icon.mjs","names":[],"sources":["../../src/components/ai-icon.tsx"],"sourcesContent":["import { PROD_CHATBOT_URL } from \"../lib/constants\";\n\ntype AiIconProps = {\n width?: number;\n height?: number;\n
|
|
1
|
+
{"version":3,"file":"ai-icon.mjs","names":[],"sources":["../../src/components/ai-icon.tsx"],"sourcesContent":["import { PROD_CHATBOT_URL } from \"../lib/constants\";\n\ntype AiIconProps = {\n width?: number;\n height?: number;\n baseUrl?: string;\n};\n\nexport function AiIcon({\n width = 24,\n height = 24,\n baseUrl = PROD_CHATBOT_URL,\n}: AiIconProps) {\n return (\n <img\n src={new URL(\"/images/ai-icon.gif\", baseUrl).toString()}\n width={width}\n height={height}\n alt=\"\"\n aria-hidden=\"true\"\n draggable={false}\n style={{ display: \"block\" }}\n />\n );\n}\n"],"mappings":";;;;AAQA,SAAgB,OAAO,EACrB,QAAQ,IACR,SAAS,IACT,UAAU,oBACI;AACd,QACE,oBAAC;EACC,KAAK,IAAI,IAAI,uBAAuB,QAAQ,CAAC,UAAU;EAChD;EACC;EACR,KAAI;EACJ,eAAY;EACZ,WAAW;EACX,OAAO,EAAE,SAAS,SAAS;GAC3B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useChatbot } from "./provider/chatbot-provider.mjs";
|
|
4
3
|
import { PROD_CHATBOT_URL } from "../lib/constants.mjs";
|
|
4
|
+
import { useChatbot } from "./provider/chatbot-provider.mjs";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChatbotFrameProps } from "./chatbot-frame.mjs";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import * as
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/components/chatbot-sheet.d.ts
|
|
6
6
|
type ChatbotSheetProps = ChatbotFrameProps & {
|
|
@@ -9,7 +9,7 @@ type ChatbotSheetProps = ChatbotFrameProps & {
|
|
|
9
9
|
declare function ChatbotSheet({
|
|
10
10
|
sheetStyle,
|
|
11
11
|
...props
|
|
12
|
-
}: ChatbotSheetProps):
|
|
12
|
+
}: ChatbotSheetProps): react_jsx_runtime0.JSX.Element;
|
|
13
13
|
//#endregion
|
|
14
14
|
export { ChatbotSheet };
|
|
15
15
|
//# sourceMappingURL=chatbot-sheet.d.mts.map
|
|
@@ -6,7 +6,6 @@ import { AiIcon } from "./ai-icon.mjs";
|
|
|
6
6
|
import { _objectWithoutProperties } from "../_virtual/_@oxc-project_runtime@0.103.0/helpers/objectWithoutProperties.mjs";
|
|
7
7
|
import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "./sheet.mjs";
|
|
8
8
|
import { Tooltip } from "./tooltip.mjs";
|
|
9
|
-
import React from "react";
|
|
10
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
10
|
|
|
12
11
|
//#region src/components/chatbot-sheet.tsx
|
|
@@ -19,7 +18,8 @@ function ChatbotSheet(_ref) {
|
|
|
19
18
|
content: "AIに質問してみましょう",
|
|
20
19
|
trigger: /* @__PURE__ */ jsx(SheetTrigger, { children: /* @__PURE__ */ jsx(AiIcon, {
|
|
21
20
|
width: 24,
|
|
22
|
-
height: 24
|
|
21
|
+
height: 24,
|
|
22
|
+
baseUrl: props.url
|
|
23
23
|
}) })
|
|
24
24
|
}), /* @__PURE__ */ jsxs(SheetContent, {
|
|
25
25
|
style: sheetStyle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot-sheet.mjs","names":[],"sources":["../../src/components/chatbot-sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { AiIcon } from \"./ai-icon\";\nimport { ChatbotFrame, type ChatbotFrameProps } from \"./chatbot-frame\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n SheetTrigger,\n} from \"./sheet\";\nimport { Tooltip } from \"./tooltip\";\n\ntype ChatbotSheetProps = ChatbotFrameProps & {\n sheetStyle?: React.CSSProperties;\n};\n\nexport function ChatbotSheet({ sheetStyle, ...props }: ChatbotSheetProps) {\n return (\n <Sheet>\n <Tooltip\n side=\"top\"\n align=\"end\"\n content=\"AIに質問してみましょう\"\n trigger={\n <SheetTrigger>\n <AiIcon width={24} height={24} />\n </SheetTrigger>\n }\n />\n <SheetContent style={sheetStyle}>\n <SheetTitle>AIに質問してみましょう</SheetTitle>\n <SheetDescription>AIに質問してみましょう</SheetDescription>\n <ChatbotFrame {...props} />\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"chatbot-sheet.mjs","names":[],"sources":["../../src/components/chatbot-sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { AiIcon } from \"./ai-icon\";\nimport { ChatbotFrame, type ChatbotFrameProps } from \"./chatbot-frame\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n SheetTrigger,\n} from \"./sheet\";\nimport { Tooltip } from \"./tooltip\";\n\ntype ChatbotSheetProps = ChatbotFrameProps & {\n sheetStyle?: React.CSSProperties;\n};\n\nexport function ChatbotSheet({ sheetStyle, ...props }: ChatbotSheetProps) {\n return (\n <Sheet>\n <Tooltip\n side=\"top\"\n align=\"end\"\n content=\"AIに質問してみましょう\"\n trigger={\n <SheetTrigger>\n <AiIcon width={24} height={24} baseUrl={props.url} />\n </SheetTrigger>\n }\n />\n <SheetContent style={sheetStyle}>\n <SheetTitle>AIに質問してみましょう</SheetTitle>\n <SheetDescription>AIに質問してみましょう</SheetDescription>\n <ChatbotFrame {...props} />\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":";;;;;;;;;;;mBAkB+B;AAA/B,SAAgB,aAAa,MAA6C;KAA7C,EAAE,qBAAe;AAC5C,QACE,qBAAC,oBACC,oBAAC;EACC,MAAK;EACL,OAAM;EACN,SAAQ;EACR,SACE,oBAAC,0BACC,oBAAC;GAAO,OAAO;GAAI,QAAQ;GAAI,SAAS,MAAM;IAAO,GACxC;GAEjB,EACF,qBAAC;EAAa,OAAO;;GACnB,oBAAC,wBAAW,iBAAyB;GACrC,oBAAC,8BAAiB,iBAA+B;GACjD,oBAAC,iCAAiB,OAAS;;GACd,IACT"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RegisteredClientTool } from "../../lib/client-tools.mjs";
|
|
2
2
|
import { InitProps, MCP, SendAppMessagePayload } from "./use-chatbot-frame-handler.mjs";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import * as
|
|
4
|
+
import * as react_jsx_runtime1 from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/components/provider/chatbot-provider.d.ts
|
|
7
7
|
type ChatbotContextType = {
|
|
@@ -77,7 +77,7 @@ type ChatbotProviderProps = {
|
|
|
77
77
|
};
|
|
78
78
|
declare function ChatbotProvider({
|
|
79
79
|
children
|
|
80
|
-
}: ChatbotProviderProps):
|
|
80
|
+
}: ChatbotProviderProps): react_jsx_runtime1.JSX.Element;
|
|
81
81
|
//#endregion
|
|
82
82
|
export { ChatbotProvider, useChatbot };
|
|
83
83
|
//# sourceMappingURL=chatbot-provider.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot-provider.mjs","names":[],"sources":["../../../src/components/provider/chatbot-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type { RegisteredClientTool } from \"../../lib/client-tools\";\nimport {\n
|
|
1
|
+
{"version":3,"file":"chatbot-provider.mjs","names":[],"sources":["../../../src/components/provider/chatbot-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type { RegisteredClientTool } from \"../../lib/client-tools\";\nimport {\n type InitProps,\n type MCP,\n type SendAppMessagePayload,\n useChatbotFrameHandler,\n} from \"./use-chatbot-frame-handler\";\nimport { useChatbotWindowStates } from \"./use-chatbot-window-states\";\n\ntype ChatbotContextType = {\n /** 1回チャットボットを開いたら、固定でtrueになる */\n hasOpened: boolean;\n /** チャットボットを開いているか */\n open: boolean;\n /** チャットボットを開く */\n setOpen: (open: boolean) => void;\n /** チャットボットを展開しているか */\n isExpanded: boolean;\n /** チャットボットを展開する */\n setIsExpanded: (expanded: boolean) => void;\n /** チャットボットをフルスクリーンにしているか */\n isFullScreen: boolean;\n /** チャットボットをフルスクリーンにする */\n setIsFullScreen: (fullScreen: boolean) => void;\n /** チャットボットを初期化 */\n init: (props: InitProps) => void;\n /** MCPを設定 */\n setMcps: (mcps: MCP[]) => void;\n /** アプリ名を設定 */\n setAppName: (appName: string) => void;\n /** セッショントークンを設定 */\n setSessionToken: (sessionToken: string) => void;\n /** アプリからメッセージを送信 */\n sendAppMessage: (payload: SendAppMessagePayload) => void;\n /** Client Toolを登録 */\n registerClientTool: (tool: RegisteredClientTool) => void;\n /** Client Toolを解除 */\n unregisterClientTool: (name: string) => void;\n /** チャットボットが準備できたか */\n isReady: boolean;\n /** チャットボットが初期化されたか */\n isInitialized: boolean;\n /**\n * @internal\n * チャットボットのiframe要素を設定\n */\n setIframeEl: (iframeEl: HTMLIFrameElement | null) => void;\n};\n\nconst ChatbotContext = React.createContext<ChatbotContextType | undefined>(\n undefined,\n);\n\n/**\n * `ChatbotProvider` が提供するチャットボット状態と操作 API を取得します。\n *\n * @returns チャットボットの表示状態、初期化 API、Client Tool の登録 API を含むコンテキスト値。\n *\n * @example\n * ```tsx\n * import { useChatbot } from \"@super_studio/ecforce-ai-agent-react\";\n *\n * export function OpenChatButton() {\n * const { open, setOpen, sendAppMessage } = useChatbot();\n *\n * return (\n * <button\n * type=\"button\"\n * onClick={() => {\n * setOpen(!open);\n * sendAppMessage({\n * message: \"EC Forceの注文状況を確認したいです\",\n * });\n * }}\n * >\n * Open chat\n * </button>\n * );\n * }\n * ```\n */\nexport function useChatbot() {\n const context = React.useContext(ChatbotContext);\n if (!context) {\n throw new Error(\"useChatbot must be used within a ChatbotProvider\");\n }\n return context;\n}\n\ntype ChatbotProviderProps = {\n children: React.ReactNode;\n};\n\nexport function ChatbotProvider({ children }: ChatbotProviderProps) {\n const {\n hasOpened,\n open,\n isExpanded,\n isFullScreen,\n setOpen,\n setIsExpanded,\n setIsFullScreen,\n } = useChatbotWindowStates();\n const {\n setMcps,\n setAppName,\n setSessionToken,\n sendAppMessage,\n registerClientTool,\n unregisterClientTool,\n init,\n isReady,\n isInitialized,\n setIframeEl,\n } = useChatbotFrameHandler({\n setOpen,\n setIsExpanded,\n setIsFullScreen,\n });\n\n const value = {\n hasOpened,\n open,\n setOpen,\n isExpanded,\n setIsExpanded,\n isFullScreen,\n setIsFullScreen,\n setSessionToken,\n sendAppMessage,\n registerClientTool,\n unregisterClientTool,\n init,\n setMcps,\n setAppName,\n isReady,\n isInitialized,\n setIframeEl,\n };\n\n return (\n <ChatbotContext.Provider value={value}>{children}</ChatbotContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;AAoDA,MAAM,iBAAiB,MAAM,cAC3B,OACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BD,SAAgB,aAAa;CAC3B,MAAM,UAAU,MAAM,WAAW,eAAe;AAChD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,mDAAmD;AAErE,QAAO;;AAOT,SAAgB,gBAAgB,EAAE,YAAkC;CAClE,MAAM,EACJ,WACA,MACA,YACA,cACA,SACA,eACA,oBACE,wBAAwB;CAC5B,MAAM,EACJ,SACA,YACA,iBACA,gBACA,oBACA,sBACA,MACA,SACA,eACA,gBACE,uBAAuB;EACzB;EACA;EACA;EACD,CAAC;CAEF,MAAM,QAAQ;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;AAED,QACE,oBAAC,eAAe;EAAgB;EAAQ;GAAmC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-chatbot-frame-handler.mjs","names":[],"sources":["../../../src/components/provider/use-chatbot-frame-handler.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type {\n ClientToolDefinition,\n ClientToolExecuteRequest,\n RegisteredClientTool,\n} from \"../../lib/client-tools\";\n\nexport type IframeMessage =\n | { type: \"CHATBOT_READY\" }\n | { type: \"CHATBOT_INITIALIZED\" }\n | { type: \"CLOSE_CHATBOT\" }\n | { type: \"EXPAND_CHATBOT\" }\n | { type: \"SHRINK_CHATBOT\" }\n | { type: \"FULLSCREEN_CHATBOT\" }\n | { type: \"EXIT_FULLSCREEN_CHATBOT\" }\n | { type: \"RELOAD_CHATBOT\" }\n | ({\n type: \"EXECUTE_CLIENT_TOOL\";\n } & ClientToolExecuteRequest);\n\nexport type MCP = {\n name: string;\n url: string;\n headers?: Record<string, string>;\n};\n\nexport type InitProps = {\n mcps?: MCP[];\n appName?: string;\n sessionToken?: string;\n};\n\nexport type AppMessageAttachment = {\n /** 添付ファイルの表示名です。 */\n fileName: string;\n /** 添付ファイルの MIME type です。 */\n mediaType: string;\n /** 添付ファイルを取得できる URL です。 */\n url: string;\n};\n\nexport type SendAppMessagePayload = {\n /** チャット上に表示するタイトルです。 */\n title?: string;\n /** ユーザーに表示するメッセージ本文です。 */\n message: string;\n /** UI に表示せず、裏側のコンテキストとして渡すメッセージです。 */\n hiddenMessage?: string;\n /** 新規チャットを開始してから送るかを指定します。 */\n startOnNewChat?: boolean;\n /** メッセージと一緒に渡す添付ファイル一覧です。 */\n attachments?: AppMessageAttachment[];\n /** このメッセージ送信で使用するモデルの alias key です。 */\n model?: string;\n};\n\nexport type ParentMessage =\n | {\n type: \"mcps\";\n mcps: MCP[];\n }\n | {\n type: \"appName\";\n appName: string;\n }\n | {\n type: \"sessionToken\";\n sessionToken: string;\n }\n | {\n type: \"init\";\n mcps?: MCP[];\n appName?: string;\n sessionToken?: string;\n }\n | {\n type: \"appMessage\";\n payload: SendAppMessagePayload;\n }\n | {\n type: \"registerClientTools\";\n tools: ClientToolDefinition[];\n }\n | {\n type: \"unregisterClientTools\";\n names: string[];\n }\n | {\n type: \"clientToolResult\";\n callId: string;\n result?: unknown;\n error?: string;\n };\n\nfunction serializeError(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n return \"Unknown client tool error\";\n}\n\ntype UseChatbotFrameHandlerProps = {\n /** チャットボットの開閉状態を更新します。 */\n setOpen: (open: boolean) => void;\n /** 展開状態を更新します。 */\n setIsExpanded: (expanded: boolean) => void;\n /** フルスクリーン状態を更新します。 */\n setIsFullScreen: (fullScreen: boolean) => void;\n};\n\n/**\n * iframe と親アプリ間のメッセージ送受信を管理し、チャットボット制御 API をまとめます。\n *\n * @returns iframe 初期化、メッセージ送信、Client Tool 登録に使うハンドラ一式を返します。\n *\n * @example\n * ```tsx\n * export function FrameBridge() {\n * const [open, setOpen] = React.useState(false);\n * const [isExpanded, setIsExpanded] = React.useState(false);\n * const [isFullScreen, setIsFullScreen] = React.useState(false);\n * const { setIframeEl, init, sendAppMessage, isReady } =\n * useChatbotFrameHandler({\n * setOpen,\n * setIsExpanded,\n * setIsFullScreen,\n * });\n *\n * React.useEffect(() => {\n * if (isReady) {\n * init({ appName: \"EC Force\" });\n * sendAppMessage({ message: \"在庫を確認したいです\" });\n * }\n * }, [init, isReady, sendAppMessage]);\n *\n * return <iframe ref={setIframeEl} src=\"https://example.com/embed\" />;\n * }\n * ```\n */\nexport function useChatbotFrameHandler({\n setOpen,\n setIsExpanded,\n setIsFullScreen,\n}: UseChatbotFrameHandlerProps) {\n const [iframeEl, setIframeEl] = React.useState<HTMLIFrameElement | null>(\n null,\n );\n const [isReady, setIsReady] = React.useState(false);\n const [isInitialized, setIsInitialized] = React.useState(false);\n const pendingAppMessageRef = React.useRef<SendAppMessagePayload | null>(null);\n const clientToolRegistryRef = React.useRef(\n new Map<string, RegisteredClientTool>(),\n );\n\n // helper to post message to the iframe\n const postMessage = React.useCallback(\n (message: ParentMessage) => {\n if (iframeEl?.contentWindow) {\n if (process.env.NODE_ENV === \"development\") {\n console.log(\"sending message to iframe\", message);\n }\n iframeEl.contentWindow.postMessage(message, \"*\");\n return true;\n }\n return false;\n },\n [iframeEl],\n );\n\n const init = React.useCallback(\n (props: InitProps) => {\n postMessage({\n type: \"init\",\n ...props,\n });\n },\n [postMessage],\n );\n\n const setMcps = React.useCallback(\n (mcps: MCP[]) => {\n postMessage({ type: \"mcps\", mcps });\n },\n [postMessage],\n );\n\n const setAppName = React.useCallback(\n (appName: string) => {\n postMessage({ type: \"appName\", appName });\n },\n [postMessage],\n );\n\n const setSessionToken = React.useCallback(\n (sessionToken: string) => {\n postMessage({ type: \"sessionToken\", sessionToken });\n },\n [postMessage],\n );\n\n const flushPendingAppMessage = React.useCallback(() => {\n const pendingPayload = pendingAppMessageRef.current;\n if (!pendingPayload || !isReady || !isInitialized) {\n return false;\n }\n\n const sent = postMessage({\n type: \"appMessage\",\n payload: pendingPayload,\n });\n\n if (sent) {\n pendingAppMessageRef.current = null;\n }\n\n return sent;\n }, [isInitialized, isReady, postMessage]);\n\n const sendAppMessage = React.useCallback(\n (payload: SendAppMessagePayload) => {\n pendingAppMessageRef.current = {\n ...payload,\n startOnNewChat: payload.startOnNewChat ?? true,\n };\n setOpen(true);\n flushPendingAppMessage();\n },\n [flushPendingAppMessage, setOpen],\n );\n\n React.useEffect(() => {\n flushPendingAppMessage();\n }, [flushPendingAppMessage]);\n\n const registerClientTool = React.useCallback(\n (tool: RegisteredClientTool) => {\n clientToolRegistryRef.current.set(tool.definition.name, tool);\n if (!isReady || !isInitialized) {\n return;\n }\n\n postMessage({\n type: \"registerClientTools\",\n tools: [tool.definition],\n });\n },\n [isInitialized, isReady, postMessage],\n );\n\n const unregisterClientTool = React.useCallback(\n (name: string) => {\n const deleted = clientToolRegistryRef.current.delete(name);\n if (!deleted || !isReady || !isInitialized) {\n return;\n }\n\n postMessage({\n type: \"unregisterClientTools\",\n names: [name],\n });\n },\n [isInitialized, isReady, postMessage],\n );\n\n React.useEffect(() => {\n if (!isReady || !isInitialized) {\n return;\n }\n\n const tools = [...clientToolRegistryRef.current.values()].map(\n (tool) => tool.definition,\n );\n if (tools.length === 0) {\n return;\n }\n\n postMessage({\n type: \"registerClientTools\",\n tools,\n });\n }, [isInitialized, isReady, postMessage]);\n\n // Initialize and setup listeners\n React.useEffect(() => {\n const iframe = iframeEl;\n if (!iframe) {\n return;\n }\n\n const handleMessage = (event: MessageEvent<IframeMessage>) => {\n if (event.source !== iframe.contentWindow) {\n return;\n }\n if (process.env.NODE_ENV === \"development\") {\n console.log(\"iframe message\", event.data);\n }\n // Handle iframe messages\n switch (event.data?.type) {\n case \"CHATBOT_READY\":\n setIsReady(true);\n break;\n case \"CHATBOT_INITIALIZED\":\n setIsInitialized(true);\n break;\n case \"CLOSE_CHATBOT\":\n setOpen(false);\n break;\n case \"EXPAND_CHATBOT\":\n setIsExpanded(true);\n break;\n case \"SHRINK_CHATBOT\":\n setIsExpanded(false);\n break;\n case \"FULLSCREEN_CHATBOT\":\n setIsFullScreen(true);\n break;\n case \"EXIT_FULLSCREEN_CHATBOT\":\n setIsFullScreen(false);\n break;\n case \"RELOAD_CHATBOT\":\n // reload iframe\n iframe.src = iframe.src;\n break;\n case \"EXECUTE_CLIENT_TOOL\": {\n const { callId, name, args } = event.data;\n const tool = clientToolRegistryRef.current.get(name);\n if (!tool) {\n postMessage({\n type: \"clientToolResult\",\n callId,\n error: `Client tool not found: ${name}`,\n });\n break;\n }\n\n void (async () => {\n try {\n const result = await tool.execute(args);\n postMessage({\n type: \"clientToolResult\",\n callId,\n result,\n });\n } catch (error) {\n postMessage({\n type: \"clientToolResult\",\n callId,\n error: serializeError(error),\n });\n }\n })();\n break;\n }\n }\n };\n\n const handleIframeLoad = () => {\n setIsReady(false);\n setIsInitialized(false);\n };\n\n window.addEventListener(\"message\", handleMessage);\n iframe.addEventListener(\"load\", handleIframeLoad);\n\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n iframe.removeEventListener(\"load\", handleIframeLoad);\n };\n }, [iframeEl]); // Run when iframe gets mounted\n\n return {\n init,\n setMcps,\n setAppName,\n setSessionToken,\n sendAppMessage,\n registerClientTool,\n unregisterClientTool,\n setIframeEl,\n isReady,\n isInitialized,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-chatbot-frame-handler.mjs","names":[],"sources":["../../../src/components/provider/use-chatbot-frame-handler.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type {\n ClientToolDefinition,\n ClientToolExecuteRequest,\n RegisteredClientTool,\n} from \"../../lib/client-tools\";\n\nexport type IframeMessage =\n | { type: \"CHATBOT_READY\" }\n | { type: \"CHATBOT_INITIALIZED\" }\n | { type: \"CLOSE_CHATBOT\" }\n | { type: \"EXPAND_CHATBOT\" }\n | { type: \"SHRINK_CHATBOT\" }\n | { type: \"FULLSCREEN_CHATBOT\" }\n | { type: \"EXIT_FULLSCREEN_CHATBOT\" }\n | { type: \"RELOAD_CHATBOT\" }\n | ({\n type: \"EXECUTE_CLIENT_TOOL\";\n } & ClientToolExecuteRequest);\n\nexport type MCP = {\n name: string;\n url: string;\n headers?: Record<string, string>;\n};\n\nexport type InitProps = {\n mcps?: MCP[];\n appName?: string;\n sessionToken?: string;\n};\n\nexport type AppMessageAttachment = {\n /** 添付ファイルの表示名です。 */\n fileName: string;\n /** 添付ファイルの MIME type です。 */\n mediaType: string;\n /** 添付ファイルを取得できる URL です。 */\n url: string;\n};\n\nexport type SendAppMessagePayload = {\n /** チャット上に表示するタイトルです。 */\n title?: string;\n /** ユーザーに表示するメッセージ本文です。 */\n message: string;\n /** UI に表示せず、裏側のコンテキストとして渡すメッセージです。 */\n hiddenMessage?: string;\n /** 新規チャットを開始してから送るかを指定します。 */\n startOnNewChat?: boolean;\n /** メッセージと一緒に渡す添付ファイル一覧です。 */\n attachments?: AppMessageAttachment[];\n /** このメッセージ送信で使用するモデルの alias key です。 */\n model?: string;\n};\n\nexport type ParentMessage =\n | {\n type: \"mcps\";\n mcps: MCP[];\n }\n | {\n type: \"appName\";\n appName: string;\n }\n | {\n type: \"sessionToken\";\n sessionToken: string;\n }\n | {\n type: \"init\";\n mcps?: MCP[];\n appName?: string;\n sessionToken?: string;\n }\n | {\n type: \"appMessage\";\n payload: SendAppMessagePayload;\n }\n | {\n type: \"registerClientTools\";\n tools: ClientToolDefinition[];\n }\n | {\n type: \"unregisterClientTools\";\n names: string[];\n }\n | {\n type: \"clientToolResult\";\n callId: string;\n result?: unknown;\n error?: string;\n };\n\nfunction serializeError(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n return \"Unknown client tool error\";\n}\n\ntype UseChatbotFrameHandlerProps = {\n /** チャットボットの開閉状態を更新します。 */\n setOpen: (open: boolean) => void;\n /** 展開状態を更新します。 */\n setIsExpanded: (expanded: boolean) => void;\n /** フルスクリーン状態を更新します。 */\n setIsFullScreen: (fullScreen: boolean) => void;\n};\n\n/**\n * iframe と親アプリ間のメッセージ送受信を管理し、チャットボット制御 API をまとめます。\n *\n * @returns iframe 初期化、メッセージ送信、Client Tool 登録に使うハンドラ一式を返します。\n *\n * @example\n * ```tsx\n * export function FrameBridge() {\n * const [open, setOpen] = React.useState(false);\n * const [isExpanded, setIsExpanded] = React.useState(false);\n * const [isFullScreen, setIsFullScreen] = React.useState(false);\n * const { setIframeEl, init, sendAppMessage, isReady } =\n * useChatbotFrameHandler({\n * setOpen,\n * setIsExpanded,\n * setIsFullScreen,\n * });\n *\n * React.useEffect(() => {\n * if (isReady) {\n * init({ appName: \"EC Force\" });\n * sendAppMessage({ message: \"在庫を確認したいです\" });\n * }\n * }, [init, isReady, sendAppMessage]);\n *\n * return <iframe ref={setIframeEl} src=\"https://example.com/embed\" />;\n * }\n * ```\n */\nexport function useChatbotFrameHandler({\n setOpen,\n setIsExpanded,\n setIsFullScreen,\n}: UseChatbotFrameHandlerProps) {\n const [iframeEl, setIframeEl] = React.useState<HTMLIFrameElement | null>(\n null,\n );\n const [isReady, setIsReady] = React.useState(false);\n const [isInitialized, setIsInitialized] = React.useState(false);\n const pendingAppMessageRef = React.useRef<SendAppMessagePayload | null>(null);\n const clientToolRegistryRef = React.useRef(\n new Map<string, RegisteredClientTool>(),\n );\n\n // helper to post message to the iframe\n const postMessage = React.useCallback(\n (message: ParentMessage) => {\n if (iframeEl?.contentWindow) {\n if (process.env.NODE_ENV === \"development\") {\n console.log(\"sending message to iframe\", message);\n }\n iframeEl.contentWindow.postMessage(message, \"*\");\n return true;\n }\n return false;\n },\n [iframeEl],\n );\n\n const init = React.useCallback(\n (props: InitProps) => {\n postMessage({\n type: \"init\",\n ...props,\n });\n },\n [postMessage],\n );\n\n const setMcps = React.useCallback(\n (mcps: MCP[]) => {\n postMessage({ type: \"mcps\", mcps });\n },\n [postMessage],\n );\n\n const setAppName = React.useCallback(\n (appName: string) => {\n postMessage({ type: \"appName\", appName });\n },\n [postMessage],\n );\n\n const setSessionToken = React.useCallback(\n (sessionToken: string) => {\n postMessage({ type: \"sessionToken\", sessionToken });\n },\n [postMessage],\n );\n\n const flushPendingAppMessage = React.useCallback(() => {\n const pendingPayload = pendingAppMessageRef.current;\n if (!pendingPayload || !isReady || !isInitialized) {\n return false;\n }\n\n const sent = postMessage({\n type: \"appMessage\",\n payload: pendingPayload,\n });\n\n if (sent) {\n pendingAppMessageRef.current = null;\n }\n\n return sent;\n }, [isInitialized, isReady, postMessage]);\n\n const sendAppMessage = React.useCallback(\n (payload: SendAppMessagePayload) => {\n pendingAppMessageRef.current = {\n ...payload,\n startOnNewChat: payload.startOnNewChat ?? true,\n };\n setOpen(true);\n flushPendingAppMessage();\n },\n [flushPendingAppMessage, setOpen],\n );\n\n React.useEffect(() => {\n flushPendingAppMessage();\n }, [flushPendingAppMessage]);\n\n const registerClientTool = React.useCallback(\n (tool: RegisteredClientTool) => {\n clientToolRegistryRef.current.set(tool.definition.name, tool);\n if (!isReady || !isInitialized) {\n return;\n }\n\n postMessage({\n type: \"registerClientTools\",\n tools: [tool.definition],\n });\n },\n [isInitialized, isReady, postMessage],\n );\n\n const unregisterClientTool = React.useCallback(\n (name: string) => {\n const deleted = clientToolRegistryRef.current.delete(name);\n if (!deleted || !isReady || !isInitialized) {\n return;\n }\n\n postMessage({\n type: \"unregisterClientTools\",\n names: [name],\n });\n },\n [isInitialized, isReady, postMessage],\n );\n\n React.useEffect(() => {\n if (!isReady || !isInitialized) {\n return;\n }\n\n const tools = [...clientToolRegistryRef.current.values()].map(\n (tool) => tool.definition,\n );\n if (tools.length === 0) {\n return;\n }\n\n postMessage({\n type: \"registerClientTools\",\n tools,\n });\n }, [isInitialized, isReady, postMessage]);\n\n // Initialize and setup listeners\n React.useEffect(() => {\n const iframe = iframeEl;\n if (!iframe) {\n return;\n }\n\n const handleMessage = (event: MessageEvent<IframeMessage>) => {\n if (event.source !== iframe.contentWindow) {\n return;\n }\n if (process.env.NODE_ENV === \"development\") {\n console.log(\"iframe message\", event.data);\n }\n // Handle iframe messages\n switch (event.data?.type) {\n case \"CHATBOT_READY\":\n setIsReady(true);\n break;\n case \"CHATBOT_INITIALIZED\":\n setIsInitialized(true);\n break;\n case \"CLOSE_CHATBOT\":\n setOpen(false);\n break;\n case \"EXPAND_CHATBOT\":\n setIsExpanded(true);\n break;\n case \"SHRINK_CHATBOT\":\n setIsExpanded(false);\n break;\n case \"FULLSCREEN_CHATBOT\":\n setIsFullScreen(true);\n break;\n case \"EXIT_FULLSCREEN_CHATBOT\":\n setIsFullScreen(false);\n break;\n case \"RELOAD_CHATBOT\":\n // biome-ignore lint/correctness/noSelfAssign: iframeを再読み込みするため\n iframe.src = iframe.src;\n break;\n case \"EXECUTE_CLIENT_TOOL\": {\n const { callId, name, args } = event.data;\n const tool = clientToolRegistryRef.current.get(name);\n if (!tool) {\n postMessage({\n type: \"clientToolResult\",\n callId,\n error: `Client tool not found: ${name}`,\n });\n break;\n }\n\n void (async () => {\n try {\n const result = await tool.execute(args);\n postMessage({\n type: \"clientToolResult\",\n callId,\n result,\n });\n } catch (error) {\n postMessage({\n type: \"clientToolResult\",\n callId,\n error: serializeError(error),\n });\n }\n })();\n break;\n }\n }\n };\n\n const handleIframeLoad = () => {\n setIsReady(false);\n setIsInitialized(false);\n };\n\n window.addEventListener(\"message\", handleMessage);\n iframe.addEventListener(\"load\", handleIframeLoad);\n\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n iframe.removeEventListener(\"load\", handleIframeLoad);\n };\n }, [iframeEl]); // Run when iframe gets mounted\n\n return {\n init,\n setMcps,\n setAppName,\n setSessionToken,\n sendAppMessage,\n registerClientTool,\n unregisterClientTool,\n setIframeEl,\n isReady,\n isInitialized,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.mjs","names":["React"],"sources":["../../src/components/sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { useChatbot } from \"./provider/chatbot-provider\";\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n const { open, setOpen } = useChatbot();\n return (\n <SheetPrimitive.Root\n data-slot=\"sheet\"\n modal={false}\n open={open}\n onOpenChange={setOpen}\n {...props}\n />\n );\n}\n\nconst SheetTrigger = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Trigger\n ref={ref}\n data-slot=\"sheet-trigger\"\n className={`chatbot-trigger ${className || \"\"}`}\n {...props}\n />\n));\nSheetTrigger.displayName = SheetPrimitive.Trigger.displayName;\n\nconst SheetClose = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Close>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Close>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Close\n ref={ref}\n data-slot=\"sheet-close\"\n className={`chatbot-sheet-close ${className || \"\"}`}\n {...props}\n />\n));\nSheetClose.displayName = SheetPrimitive.Close.displayName;\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />;\n}\n\nconst SheetContent = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>\n>(({ className, children, style, ...props }, ref) => {\n const { isExpanded, isFullScreen, open, hasOpened } = useChatbot();\n const width = isFullScreen ? \"100%\" : isExpanded ? \"848px\" : \"400px\";\n\n // Use transform for better performance instead of right property\n const translateX = open ? \"0\" : \"100%\";\n\n // Create style object with CSS custom property for smoother animation\n const contentStyle = {\n \"--sheet-width\": width,\n transform: `translateX(${translateX})`,\n ...style,\n } as React.CSSProperties & { \"--sheet-width\": string };\n\n const classNames = [\n \"chatbot-sheet-content\",\n isExpanded && !isFullScreen ? \"chatbot-sheet-expanded\" : \"\",\n isFullScreen ? \"chatbot-sheet-fullscreen\" : \"\",\n className || \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <SheetPortal forceMount={hasOpened || undefined}>\n <SheetPrimitive.Content\n ref={ref}\n data-slot=\"sheet-content\"\n forceMount={hasOpened || undefined}\n onInteractOutside={(e) => e.preventDefault()}\n className={classNames}\n style={contentStyle}\n {...props}\n >\n {children}\n </SheetPrimitive.Content>\n </SheetPortal>\n );\n});\nSheetContent.displayName = SheetPrimitive.Content.displayName;\n\nconst SheetHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"sheet-header\"\n className={`chatbot-sheet-header ${className || \"\"}`}\n {...props}\n />\n));\nSheetHeader.displayName = \"SheetHeader\";\n\nconst SheetFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"sheet-footer\"\n className={`chatbot-sheet-footer ${className || \"\"}`}\n {...props}\n />\n));\nSheetFooter.displayName = \"SheetFooter\";\n\nconst SheetTitle = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Title\n ref={ref}\n data-slot=\"sheet-title\"\n className={`chatbot-sheet-title ${className || \"\"}`}\n {...props}\n />\n));\nSheetTitle.displayName = SheetPrimitive.Title.displayName;\n\nconst SheetDescription = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Description\n ref={ref}\n data-slot=\"sheet-description\"\n className={`chatbot-sheet-description ${className || \"\"}`}\n {...props}\n />\n));\nSheetDescription.displayName = SheetPrimitive.Description.displayName;\n\nexport {\n Sheet,\n
|
|
1
|
+
{"version":3,"file":"sheet.mjs","names":["React"],"sources":["../../src/components/sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { useChatbot } from \"./provider/chatbot-provider\";\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n const { open, setOpen } = useChatbot();\n return (\n <SheetPrimitive.Root\n data-slot=\"sheet\"\n modal={false}\n open={open}\n onOpenChange={setOpen}\n {...props}\n />\n );\n}\n\nconst SheetTrigger = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Trigger\n ref={ref}\n data-slot=\"sheet-trigger\"\n className={`chatbot-trigger ${className || \"\"}`}\n {...props}\n />\n));\nSheetTrigger.displayName = SheetPrimitive.Trigger.displayName;\n\nconst SheetClose = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Close>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Close>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Close\n ref={ref}\n data-slot=\"sheet-close\"\n className={`chatbot-sheet-close ${className || \"\"}`}\n {...props}\n />\n));\nSheetClose.displayName = SheetPrimitive.Close.displayName;\n\nfunction SheetPortal({\n ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />;\n}\n\nconst SheetContent = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>\n>(({ className, children, style, ...props }, ref) => {\n const { isExpanded, isFullScreen, open, hasOpened } = useChatbot();\n const width = isFullScreen ? \"100%\" : isExpanded ? \"848px\" : \"400px\";\n\n // Use transform for better performance instead of right property\n const translateX = open ? \"0\" : \"100%\";\n\n // Create style object with CSS custom property for smoother animation\n const contentStyle = {\n \"--sheet-width\": width,\n transform: `translateX(${translateX})`,\n ...style,\n } as React.CSSProperties & { \"--sheet-width\": string };\n\n const classNames = [\n \"chatbot-sheet-content\",\n isExpanded && !isFullScreen ? \"chatbot-sheet-expanded\" : \"\",\n isFullScreen ? \"chatbot-sheet-fullscreen\" : \"\",\n className || \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <SheetPortal forceMount={hasOpened || undefined}>\n <SheetPrimitive.Content\n ref={ref}\n data-slot=\"sheet-content\"\n forceMount={hasOpened || undefined}\n onInteractOutside={(e) => e.preventDefault()}\n className={classNames}\n style={contentStyle}\n {...props}\n >\n {children}\n </SheetPrimitive.Content>\n </SheetPortal>\n );\n});\nSheetContent.displayName = SheetPrimitive.Content.displayName;\n\nconst SheetHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"sheet-header\"\n className={`chatbot-sheet-header ${className || \"\"}`}\n {...props}\n />\n));\nSheetHeader.displayName = \"SheetHeader\";\n\nconst SheetFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"sheet-footer\"\n className={`chatbot-sheet-footer ${className || \"\"}`}\n {...props}\n />\n));\nSheetFooter.displayName = \"SheetFooter\";\n\nconst SheetTitle = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Title\n ref={ref}\n data-slot=\"sheet-title\"\n className={`chatbot-sheet-title ${className || \"\"}`}\n {...props}\n />\n));\nSheetTitle.displayName = SheetPrimitive.Title.displayName;\n\nconst SheetDescription = React.forwardRef<\n React.ElementRef<typeof SheetPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <SheetPrimitive.Description\n ref={ref}\n data-slot=\"sheet-description\"\n className={`chatbot-sheet-description ${className || \"\"}`}\n {...props}\n />\n));\nSheetDescription.displayName = SheetPrimitive.Description.displayName;\n\nexport {\n Sheet,\n SheetClose,\n SheetContent,\n SheetDescription,\n SheetFooter,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n};\n"],"mappings":";;;;;;;;;;;;mBAsBK,4BAaA;CAmBA;CAAW;CAAU;iBA4CrB,4BAaA,4BAaA,4BAaA;AAnIL,SAAS,MAAM,MAAgE;KAA3D;CAClB,MAAM,EAAE,MAAM,YAAY,YAAY;AACtC,QACE,oBAAC,eAAe;EACd,aAAU;EACV,OAAO;EACD;EACN,cAAc;IACV,OACJ;;AAIN,MAAM,eAAeA,QAAM,YAGxB,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC,eAAe;EACT;EACL,aAAU;EACV,WAAW,mBAAmB,aAAa;IACvC,OACJ;EACF;AACF,aAAa,cAAc,eAAe,QAAQ;AAElD,MAAM,aAAaA,QAAM,YAGtB,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC,eAAe;EACT;EACL,aAAU;EACV,WAAW,uBAAuB,aAAa;IAC3C,OACJ;EACF;AACF,WAAW,cAAc,eAAe,MAAM;AAE9C,SAAS,YAAY,OAEkC;KADlD;AAEH,QAAO,oBAAC,eAAe,yBAAO,aAAU,kBAAmB,OAAS;;AAGtE,MAAM,eAAeA,QAAM,YAGxB,OAA0C,QAAQ;KAAlD,EAAE,WAAW,UAAU,iBAAU;CAClC,MAAM,EAAE,YAAY,cAAc,MAAM,cAAc,YAAY;CAClE,MAAM,QAAQ,eAAe,SAAS,aAAa,UAAU;CAG7D,MAAM,aAAa,OAAO,MAAM;CAGhC,MAAM;EACJ,iBAAiB;EACjB,WAAW,cAAc,WAAW;IACjC;CAGL,MAAM,aAAa;EACjB;EACA,cAAc,CAAC,eAAe,2BAA2B;EACzD,eAAe,6BAA6B;EAC5C,aAAa;EACd,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;AAEZ,QACE,oBAAC;EAAY,YAAY,aAAa;YACpC,oBAAC,eAAe;GACT;GACL,aAAU;GACV,YAAY,aAAa;GACzB,oBAAoB,MAAM,EAAE,gBAAgB;GAC5C,WAAW;GACX,OAAO;KACH,cAEH,YACsB;GACb;EAEhB;AACF,aAAa,cAAc,eAAe,QAAQ;AAElD,MAAM,cAAcA,QAAM,YAGvB,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC;EACM;EACL,aAAU;EACV,WAAW,wBAAwB,aAAa;IAC5C,OACJ;EACF;AACF,YAAY,cAAc;AAE1B,MAAM,cAAcA,QAAM,YAGvB,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC;EACM;EACL,aAAU;EACV,WAAW,wBAAwB,aAAa;IAC5C,OACJ;EACF;AACF,YAAY,cAAc;AAE1B,MAAM,aAAaA,QAAM,YAGtB,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC,eAAe;EACT;EACL,aAAU;EACV,WAAW,uBAAuB,aAAa;IAC3C,OACJ;EACF;AACF,WAAW,cAAc,eAAe,MAAM;AAE9C,MAAM,mBAAmBA,QAAM,YAG5B,OAAyB,QAAQ;KAAjC,EAAE,qBAAc;AAAiB,QAClC,oBAAC,eAAe;EACT;EACL,aAAU;EACV,WAAW,6BAA6B,aAAa;IACjD,OACJ;EACF;AACF,iBAAiB,cAAc,eAAe,YAAY"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ClientToolDefinition, ClientToolExecuteRequest, ClientToolJsonSchema, RegisteredClientTool, UseClientToolOptions, useClientTool } from "./lib/client-tools.mjs";
|
|
2
|
-
import { ChatbotProvider, useChatbot } from "./components/provider/chatbot-provider.mjs";
|
|
3
1
|
import { ChatbotFrame, ChatbotFrameProps, SessionData, UseSessionProps, useSession } from "./components/chatbot-frame.mjs";
|
|
4
2
|
import { ChatbotSheet } from "./components/chatbot-sheet.mjs";
|
|
3
|
+
import { ClientToolDefinition, ClientToolExecuteRequest, ClientToolJsonSchema, RegisteredClientTool, UseClientToolOptions, useClientTool } from "./lib/client-tools.mjs";
|
|
4
|
+
import { ChatbotProvider, useChatbot } from "./components/provider/chatbot-provider.mjs";
|
|
5
5
|
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "./components/sheet.mjs";
|
|
6
6
|
import { Tooltip } from "./components/tooltip.mjs";
|
|
7
7
|
export { ChatbotFrame, ChatbotFrameProps, ChatbotProvider, ChatbotSheet, ClientToolDefinition, ClientToolExecuteRequest, ClientToolJsonSchema, RegisteredClientTool, SessionData, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Tooltip, UseClientToolOptions, UseSessionProps, useChatbot, useClientTool, useSession };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@super_studio/ecforce-ai-agent-react",
|
|
3
|
-
"version": "1.4.0
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"main": "./dist/index.mjs",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.mts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@types/react-dom": "19.2.3",
|
|
40
40
|
"react": "19.2.6",
|
|
41
41
|
"react-dom": "19.2.6",
|
|
42
|
-
"zod": "4.
|
|
42
|
+
"zod": "4.4.3"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"dev": "tsdown --watch",
|
|
@@ -3,17 +3,17 @@ import { PROD_CHATBOT_URL } from "../lib/constants";
|
|
|
3
3
|
type AiIconProps = {
|
|
4
4
|
width?: number;
|
|
5
5
|
height?: number;
|
|
6
|
+
baseUrl?: string;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export function AiIcon({ width = 24, height = 24 }: AiIconProps) {
|
|
9
|
+
export function AiIcon({
|
|
10
|
+
width = 24,
|
|
11
|
+
height = 24,
|
|
12
|
+
baseUrl = PROD_CHATBOT_URL,
|
|
13
|
+
}: AiIconProps) {
|
|
14
14
|
return (
|
|
15
15
|
<img
|
|
16
|
-
src={
|
|
16
|
+
src={new URL("/images/ai-icon.gif", baseUrl).toString()}
|
|
17
17
|
width={width}
|
|
18
18
|
height={height}
|
|
19
19
|
alt=""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import React from "react";
|
|
3
|
+
import type React from "react";
|
|
4
4
|
import { AiIcon } from "./ai-icon";
|
|
5
5
|
import { ChatbotFrame, type ChatbotFrameProps } from "./chatbot-frame";
|
|
6
6
|
import {
|
|
@@ -25,7 +25,7 @@ export function ChatbotSheet({ sheetStyle, ...props }: ChatbotSheetProps) {
|
|
|
25
25
|
content="AIに質問してみましょう"
|
|
26
26
|
trigger={
|
|
27
27
|
<SheetTrigger>
|
|
28
|
-
<AiIcon width={24} height={24} />
|
|
28
|
+
<AiIcon width={24} height={24} baseUrl={props.url} />
|
|
29
29
|
</SheetTrigger>
|
|
30
30
|
}
|
|
31
31
|
/>
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import React from "react";
|
|
4
4
|
import type { RegisteredClientTool } from "../../lib/client-tools";
|
|
5
5
|
import {
|
|
6
|
-
useChatbotFrameHandler,
|
|
7
6
|
type InitProps,
|
|
8
7
|
type MCP,
|
|
9
8
|
type SendAppMessagePayload,
|
|
9
|
+
useChatbotFrameHandler,
|
|
10
10
|
} from "./use-chatbot-frame-handler";
|
|
11
11
|
import { useChatbotWindowStates } from "./use-chatbot-window-states";
|
|
12
12
|
|
|
@@ -325,7 +325,7 @@ export function useChatbotFrameHandler({
|
|
|
325
325
|
setIsFullScreen(false);
|
|
326
326
|
break;
|
|
327
327
|
case "RELOAD_CHATBOT":
|
|
328
|
-
//
|
|
328
|
+
// biome-ignore lint/correctness/noSelfAssign: iframeを再読み込みするため
|
|
329
329
|
iframe.src = iframe.src;
|
|
330
330
|
break;
|
|
331
331
|
case "EXECUTE_CLIENT_TOOL": {
|
package/src/components/sheet.tsx
CHANGED
|
@@ -147,11 +147,11 @@ SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
|
147
147
|
|
|
148
148
|
export {
|
|
149
149
|
Sheet,
|
|
150
|
-
SheetTrigger,
|
|
151
150
|
SheetClose,
|
|
152
151
|
SheetContent,
|
|
153
|
-
|
|
152
|
+
SheetDescription,
|
|
154
153
|
SheetFooter,
|
|
154
|
+
SheetHeader,
|
|
155
155
|
SheetTitle,
|
|
156
|
-
|
|
156
|
+
SheetTrigger,
|
|
157
157
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from "./components/provider/chatbot-provider";
|
|
2
1
|
export * from "./components/chatbot-frame";
|
|
3
2
|
export * from "./components/chatbot-sheet";
|
|
3
|
+
export * from "./components/provider/chatbot-provider";
|
|
4
4
|
export * from "./components/sheet";
|
|
5
5
|
export * from "./components/tooltip";
|
|
6
6
|
export * from "./lib/client-tools";
|