@copilotkit/react-core
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
142 lines (140 loc) • 5.05 kB
JavaScript
import {
useAsyncCallback
} from "./chunk-N4WEHORG.mjs";
import {
useToast
} from "./chunk-EFL5OBKN.mjs";
import {
useCopilotContext
} from "./chunk-EUX2P2E7.mjs";
import {
__async,
__spreadValues
} from "./chunk-SKC7AJIV.mjs";
// src/hooks/use-copilot-action.ts
import { randomId } from "@copilotkit/shared";
import { createElement, Fragment, useEffect, useRef } from "react";
function useCopilotAction(action, dependencies) {
const { setAction, removeAction, actions, chatComponentsCache } = useCopilotContext();
const idRef = useRef(randomId());
const renderAndWaitRef = useRef(null);
const activatingMessageIdRef = useRef(null);
const { addToast } = useToast();
action = __spreadValues({}, action);
if (
// renderAndWaitForResponse is not available for catch all actions
isFrontendAction(action) && // check if renderAndWaitForResponse is set
(action.renderAndWait || action.renderAndWaitForResponse)
) {
action._isRenderAndWait = true;
const renderAndWait = action.renderAndWait || action.renderAndWaitForResponse;
action.renderAndWait = void 0;
action.renderAndWaitForResponse = void 0;
action._setActivatingMessageId = (id) => {
activatingMessageIdRef.current = id;
};
action.handler = useAsyncCallback(() => __async(this, null, function* () {
const currentActivatingId = activatingMessageIdRef.current;
let resolve;
let reject;
const promise = new Promise((resolvePromise, rejectPromise) => {
resolve = resolvePromise;
reject = rejectPromise;
});
renderAndWaitRef.current = {
promise,
resolve,
reject,
messageId: currentActivatingId
};
const result = yield promise;
return result;
}), []);
action.render = (props) => {
const currentRenderMessageId = props.messageId;
let status = props.status;
if (props.status === "executing") {
if (!renderAndWaitRef.current || !renderAndWaitRef.current.promise) {
status = "inProgress";
} else if (renderAndWaitRef.current.messageId !== currentRenderMessageId && activatingMessageIdRef.current !== currentRenderMessageId) {
status = "inProgress";
}
}
const waitProps = {
status,
args: props.args,
result: props.result,
// handler and respond should only be provided if this is the truly active instance
// and its promise infrastructure is ready.
handler: status === "executing" && renderAndWaitRef.current && renderAndWaitRef.current.messageId === currentRenderMessageId ? renderAndWaitRef.current.resolve : void 0,
respond: status === "executing" && renderAndWaitRef.current && renderAndWaitRef.current.messageId === currentRenderMessageId ? renderAndWaitRef.current.resolve : void 0
};
const isNoArgsRenderWait = (_fn) => {
var _a;
return ((_a = action.parameters) == null ? void 0 : _a.length) === 0;
};
if (renderAndWait) {
if (isNoArgsRenderWait(renderAndWait)) {
return renderAndWait(waitProps);
} else {
return renderAndWait(waitProps);
}
}
return createElement(Fragment);
};
}
if (dependencies === void 0) {
if (actions[idRef.current]) {
if (isFrontendAction(action)) {
actions[idRef.current].handler = action.handler;
}
if (typeof action.render === "function") {
if (chatComponentsCache.current !== null) {
chatComponentsCache.current.actions[action.name] = action.render;
}
}
}
}
useEffect(() => {
const hasDuplicate = Object.values(actions).some(
(otherAction) => otherAction.name === action.name && otherAction !== actions[idRef.current]
);
if (hasDuplicate) {
addToast({
type: "warning",
message: `Found an already registered action with name ${action.name}.`,
id: `dup-action-${action.name}`
});
}
}, [actions]);
useEffect(() => {
setAction(idRef.current, action);
if (chatComponentsCache.current !== null && action.render !== void 0) {
chatComponentsCache.current.actions[action.name] = action.render;
}
return () => {
removeAction(idRef.current);
};
}, [
setAction,
removeAction,
isFrontendAction(action) ? action.description : void 0,
action.name,
isFrontendAction(action) ? action.disabled : void 0,
isFrontendAction(action) ? action.available : void 0,
// This should be faster than deep equality checking
// In addition, all major JS engines guarantee the order of object keys
JSON.stringify(isFrontendAction(action) ? action.parameters : []),
// include render only if it's a string
typeof action.render === "string" ? action.render : void 0,
// dependencies set by the developer
...dependencies || []
]);
}
function isFrontendAction(action) {
return action.name !== "*";
}
export {
useCopilotAction
};
//# sourceMappingURL=chunk-T3376SZS.mjs.map