@agentskit/chat-react 0.1.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/LICENSE +22 -0
- package/README.md +13 -0
- package/dist/index.cjs +376 -0
- package/dist/index.d.cts +46 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +355 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentsKit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @agentskit/chat-react
|
|
2
|
+
|
|
3
|
+
Accessible React application shell over `@agentskit/react`.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<AgentChat definition={definition} placeholder="Ask a question" />
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See the [React quick start](../../docs/getting-started/react.md).
|
|
10
|
+
|
|
11
|
+
The package also exports the accessible native-web `ChoiceList` renderer.
|
|
12
|
+
|
|
13
|
+
Use `theme` for semantic tokens and `slots` for native React composition. `toChatCssVariables` exposes the upstream CSS-variable mapping. See [theming and composition](../../docs/theming-and-composition.md).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.tsx
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AgentChat: () => AgentChat,
|
|
24
|
+
ChoiceList: () => ChoiceList,
|
|
25
|
+
StandardComponent: () => StandardComponent,
|
|
26
|
+
toChatCssVariables: () => toChatCssVariables
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
var import_chat = require("@agentskit/chat");
|
|
30
|
+
var import_chat_protocol = require("@agentskit/chat-protocol");
|
|
31
|
+
var import_react = require("@agentskit/react");
|
|
32
|
+
var import_react2 = require("react");
|
|
33
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
34
|
+
var toChatCssVariables = (input) => {
|
|
35
|
+
const theme = (0, import_chat.resolveChatTheme)(input);
|
|
36
|
+
return {
|
|
37
|
+
"--ak-color-bg": theme.colors.background,
|
|
38
|
+
"--ak-color-surface": theme.colors.surface,
|
|
39
|
+
"--ak-color-border": theme.colors.border,
|
|
40
|
+
"--ak-color-text": theme.colors.text,
|
|
41
|
+
"--ak-color-text-muted": theme.colors.muted,
|
|
42
|
+
"--ak-color-bubble-user": theme.colors.accent,
|
|
43
|
+
"--ak-color-bubble-user-text": theme.colors.onAccent,
|
|
44
|
+
"--ak-color-bubble-assistant": theme.colors.surface,
|
|
45
|
+
"--ak-color-bubble-assistant-text": theme.colors.text,
|
|
46
|
+
"--ak-color-input-bg": theme.colors.background,
|
|
47
|
+
"--ak-color-input-border": theme.colors.border,
|
|
48
|
+
"--ak-color-input-focus": theme.colors.accent,
|
|
49
|
+
"--ak-color-button": theme.colors.accent,
|
|
50
|
+
"--ak-color-button-text": theme.colors.onAccent,
|
|
51
|
+
"--ak-color-tool-bg": theme.colors.surface,
|
|
52
|
+
"--ak-color-tool-border": theme.colors.border,
|
|
53
|
+
"--ak-app-color-danger": theme.colors.danger,
|
|
54
|
+
"--ak-font-family": theme.fontFamily === "system" ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" : theme.fontFamily,
|
|
55
|
+
"--ak-radius": `${theme.radius.medium}px`,
|
|
56
|
+
"--ak-radius-lg": `${theme.radius.large}px`,
|
|
57
|
+
"--ak-spacing-sm": `${theme.spacing.small}px`,
|
|
58
|
+
"--ak-spacing-md": `${theme.spacing.medium}px`,
|
|
59
|
+
"--ak-spacing-lg": `${theme.spacing.large}px`
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
var coalesceTextParts = (parts) => {
|
|
63
|
+
const result = [];
|
|
64
|
+
for (const part of parts) {
|
|
65
|
+
const previous = result.at(-1);
|
|
66
|
+
if (part.kind === "text" && previous?.kind === "text") result[result.length - 1] = { kind: "text", text: previous.text + part.text };
|
|
67
|
+
else result.push(part);
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
var StandardForm = ({ frame, manifest, onInteract, disabled }) => {
|
|
72
|
+
const props = import_chat.FormPropsSchema.parse(frame.props);
|
|
73
|
+
const [values, setValues] = (0, import_react2.useState)({});
|
|
74
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { "aria-label": props.title ?? "Form", "data-ak-component": "form", onSubmit: (event) => {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
onInteract((0, import_chat.createComponentInteraction)(frame, manifest, "submit", values));
|
|
77
|
+
}, children: [
|
|
78
|
+
props.title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: props.title }) : null,
|
|
79
|
+
props.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
|
|
80
|
+
field.label,
|
|
81
|
+
field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { required: field.required, disabled, value: String(values[field.id] ?? ""), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.value })), children: [
|
|
82
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "Select" }),
|
|
83
|
+
field.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.id, children: option.label }, option.id))
|
|
84
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: field.type, required: field.required, disabled, placeholder: field.placeholder, ...field.type === "checkbox" ? { checked: Boolean(values[field.id]), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.checked })) } : { value: String(values[field.id] ?? ""), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.value })) } })
|
|
85
|
+
] }, field.id)),
|
|
86
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", disabled, children: props.submitLabel })
|
|
87
|
+
] });
|
|
88
|
+
};
|
|
89
|
+
var StandardComponent = ({ frame, manifest, onInteract, disabled = false }) => {
|
|
90
|
+
if (!(0, import_chat.resolveComponentFrame)(frame, manifest).ok || frame.componentKey === "choice-list") return null;
|
|
91
|
+
const emit = (event, value) => onInteract((0, import_chat.createComponentInteraction)(frame, manifest, event, value));
|
|
92
|
+
switch (frame.componentKey) {
|
|
93
|
+
case "button-group": {
|
|
94
|
+
const props = import_chat.ButtonGroupPropsSchema.parse(frame.props);
|
|
95
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { "aria-label": props.label, "data-ak-component": "button-group", children: [
|
|
96
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: props.label }),
|
|
97
|
+
props.buttons.map((button) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: disabled || button.disabled, onClick: () => emit("select", button.id), children: button.label }, button.id))
|
|
98
|
+
] });
|
|
99
|
+
}
|
|
100
|
+
case "form":
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StandardForm, { frame, manifest, onInteract, disabled });
|
|
102
|
+
case "confirmation": {
|
|
103
|
+
const props = import_chat.ConfirmationPropsSchema.parse(frame.props);
|
|
104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-label": props.title, "data-ak-component": "confirmation", children: [
|
|
105
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: props.title }),
|
|
106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: props.message }),
|
|
107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled, onClick: () => emit("confirm"), children: props.confirmLabel }),
|
|
108
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled, onClick: () => emit("cancel"), children: props.cancelLabel })
|
|
109
|
+
] });
|
|
110
|
+
}
|
|
111
|
+
case "progress": {
|
|
112
|
+
const props = import_chat.ProgressPropsSchema.parse(frame.props);
|
|
113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-ak-component": "progress", children: [
|
|
114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
|
|
115
|
+
props.label,
|
|
116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("progress", { max: 100, value: props.value })
|
|
117
|
+
] }),
|
|
118
|
+
props.status ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: props.status }) : null
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
case "source-list": {
|
|
122
|
+
const props = import_chat.SourceListPropsSchema.parse(frame.props);
|
|
123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "data-ak-component": "source-list", children: [
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: props.label }),
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { children: props.sources.map((source) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
|
|
126
|
+
source.url ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: source.url, onClick: (event) => {
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
emit("open", source.id);
|
|
129
|
+
}, children: source.title }) : source.title,
|
|
130
|
+
source.snippet ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: source.snippet }) : null
|
|
131
|
+
] }, source.id)) })
|
|
132
|
+
] });
|
|
133
|
+
}
|
|
134
|
+
case "link-card": {
|
|
135
|
+
const props = import_chat.LinkCardPropsSchema.parse(frame.props);
|
|
136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { "data-ak-component": "link-card", href: props.href, onClick: (event) => {
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
emit("open", props.href);
|
|
139
|
+
}, children: [
|
|
140
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: props.title }),
|
|
141
|
+
props.description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: props.description }) : null,
|
|
142
|
+
props.label ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: props.label }) : null
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
case "error-notice": {
|
|
146
|
+
const props = import_chat.ErrorNoticePropsSchema.parse(frame.props);
|
|
147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { role: "alert", "data-ak-component": "error-notice", children: [
|
|
148
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: props.title }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: props.message }),
|
|
150
|
+
props.code ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: props.code }) : null,
|
|
151
|
+
props.retryLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled, onClick: () => emit("retry"), children: props.retryLabel }) : null
|
|
152
|
+
] });
|
|
153
|
+
}
|
|
154
|
+
case "tool-call": {
|
|
155
|
+
const props = import_chat.ToolCallPropsSchema.parse(frame.props);
|
|
156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { role: "status", "data-ak-component": "tool-call", children: [
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: props.name }),
|
|
158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: props.status }),
|
|
159
|
+
props.arguments ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: JSON.stringify(props.arguments, null, 2) }) : null,
|
|
160
|
+
props.result === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: JSON.stringify(props.result, null, 2) })
|
|
161
|
+
] });
|
|
162
|
+
}
|
|
163
|
+
case "approval-request": {
|
|
164
|
+
const props = import_chat.ApprovalRequestPropsSchema.parse(frame.props);
|
|
165
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-label": props.title, "data-ak-component": "approval-request", children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: props.title }),
|
|
167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: props.description }),
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled, onClick: () => emit("approve"), children: props.approveLabel }),
|
|
169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled, onClick: () => emit("deny"), children: props.denyLabel })
|
|
170
|
+
] });
|
|
171
|
+
}
|
|
172
|
+
case "table": {
|
|
173
|
+
const props = import_chat.TablePropsSchema.parse(frame.props);
|
|
174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { "data-ak-component": "table", children: [
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("caption", { children: props.caption }),
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: props.columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: column.label }, column.key)) }) }),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: props.rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: props.columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: String(row[column.key] ?? "") }, column.key)) }, index)) })
|
|
178
|
+
] });
|
|
179
|
+
}
|
|
180
|
+
case "file-attachment": {
|
|
181
|
+
const props = import_chat.FileAttachmentPropsSchema.parse(frame.props);
|
|
182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", { "data-ak-component": "file-attachment", children: [
|
|
183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: props.name }),
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: props.mimeType }),
|
|
185
|
+
props.sizeBytes === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
186
|
+
props.sizeBytes,
|
|
187
|
+
" bytes"
|
|
188
|
+
] }),
|
|
189
|
+
props.url ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: props.url, onClick: (event) => {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
emit("open", props.url);
|
|
192
|
+
}, children: "Open" }) : null
|
|
193
|
+
] });
|
|
194
|
+
}
|
|
195
|
+
default:
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
var ChoiceList = ({ frame, manifest, onSelect, disabled = false }) => {
|
|
200
|
+
const resolved = (0, import_chat.resolveChoiceListFrame)(frame, manifest);
|
|
201
|
+
if (!resolved.ok) return null;
|
|
202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { "aria-label": resolved.props.prompt, "data-ak-component": "choice-list", children: [
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("legend", { children: resolved.props.prompt }),
|
|
204
|
+
resolved.props.choices.map((choice) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", disabled, onClick: () => onSelect((0, import_chat.selectChoice)(resolved.frame, choice.id)), children: [
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: choice.label }),
|
|
206
|
+
choice.description === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: choice.description })
|
|
207
|
+
] }, choice.id))
|
|
208
|
+
] });
|
|
209
|
+
};
|
|
210
|
+
var AgentChatSession = ({ definition, placeholder, onComponentSelect = () => void 0, onComponentInteract = () => void 0, actionConfirmationTtlMs, session: preparedSession, theme: themeInput, slots = {} }) => {
|
|
211
|
+
const theme = (0, import_chat.resolveChatTheme)(themeInput);
|
|
212
|
+
const ContainerSlot = slots.Container ?? import_react.ChatContainer;
|
|
213
|
+
const MessageSlot = slots.Message ?? import_react.Message;
|
|
214
|
+
const InputSlot = slots.Input ?? import_react.InputBar;
|
|
215
|
+
const ThinkingSlot = slots.Thinking ?? import_react.ThinkingIndicator;
|
|
216
|
+
const ConfirmationSlot = slots.Confirmation ?? import_react.ToolConfirmation;
|
|
217
|
+
const ChoiceListSlot = slots.ChoiceList ?? ChoiceList;
|
|
218
|
+
const StandardComponentSlot = slots.StandardComponent ?? StandardComponent;
|
|
219
|
+
const [session] = (0, import_react2.useState)(() => (0, import_chat.resolveChatSession)(definition, preparedSession));
|
|
220
|
+
const sessionId = session.sessionId;
|
|
221
|
+
const [actionError, setActionError] = (0, import_react2.useState)();
|
|
222
|
+
const [editDraft, setEditDraft] = (0, import_react2.useState)();
|
|
223
|
+
const [resolvedInstances, setResolvedInstances] = (0, import_react2.useState)(() => /* @__PURE__ */ new Set());
|
|
224
|
+
const resolvedInstancesRef = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
225
|
+
const config = (0, import_react2.useMemo)(() => session.updateChat(definition.chat), [definition.chat, session]);
|
|
226
|
+
const chat = (0, import_react.useChat)(config);
|
|
227
|
+
const chatRef = (0, import_react2.useRef)(chat);
|
|
228
|
+
chatRef.current = chat;
|
|
229
|
+
const [confirmation] = (0, import_react2.useState)(() => session.createConfirmation({ ...actionConfirmationTtlMs === void 0 ? {} : { ttlMs: actionConfirmationTtlMs }, chat: {
|
|
230
|
+
proposeToolCall: (proposal) => chatRef.current.proposeToolCall(proposal),
|
|
231
|
+
approve: (id) => chatRef.current.approve(id),
|
|
232
|
+
deny: (id, reason) => chatRef.current.deny(id, reason)
|
|
233
|
+
} }));
|
|
234
|
+
const selectComponent = (event, frame) => {
|
|
235
|
+
if (resolvedInstancesRef.current.has(event.instanceId)) return;
|
|
236
|
+
setActionError(void 0);
|
|
237
|
+
resolvedInstancesRef.current.add(event.instanceId);
|
|
238
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
239
|
+
try {
|
|
240
|
+
onComponentSelect(event);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
setActionError(error instanceof Error ? error : new Error("Component selection callback failed."));
|
|
243
|
+
}
|
|
244
|
+
const action = (0, import_chat.resolveChoiceAction)(frame, event.choiceId);
|
|
245
|
+
if (action) void confirmation.propose(action).catch((error) => {
|
|
246
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
247
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
248
|
+
setActionError(error instanceof Error ? error : new Error("Action proposal failed."));
|
|
249
|
+
});
|
|
250
|
+
else {
|
|
251
|
+
let submission;
|
|
252
|
+
try {
|
|
253
|
+
submission = definition.choiceSubmission?.(frame, event.choiceId, { sessionId });
|
|
254
|
+
} catch (error) {
|
|
255
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
256
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
257
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission authorization failed."));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (submission && "unavailable" in submission) {
|
|
261
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
262
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
263
|
+
setActionError(new Error("This deterministic choice expired. Select it again after asking the question once more."));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (submission) void chatRef.current.send(submission.value).then(
|
|
267
|
+
() => {
|
|
268
|
+
try {
|
|
269
|
+
submission.commit();
|
|
270
|
+
} catch (error) {
|
|
271
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission settlement failed."));
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
(error) => {
|
|
275
|
+
try {
|
|
276
|
+
submission.release();
|
|
277
|
+
} catch {
|
|
278
|
+
} finally {
|
|
279
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
280
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
281
|
+
}
|
|
282
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission failed."));
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const interactComponent = (event) => {
|
|
288
|
+
if (resolvedInstancesRef.current.has(event.instanceId)) return;
|
|
289
|
+
resolvedInstancesRef.current.add(event.instanceId);
|
|
290
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
291
|
+
try {
|
|
292
|
+
onComponentInteract(event);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
295
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
296
|
+
setActionError(error instanceof Error ? error : new Error("Component interaction callback failed."));
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
const approve = (toolCallId) => {
|
|
300
|
+
const record = confirmation.getByToolCall(toolCallId);
|
|
301
|
+
void (record ? confirmation.approve(record.token, sessionId) : chat.approve(toolCallId)).catch((error) => setActionError(error instanceof Error ? error : new Error("Action approval failed.")));
|
|
302
|
+
};
|
|
303
|
+
const deny = (toolCallId, reason) => {
|
|
304
|
+
const record = confirmation.getByToolCall(toolCallId);
|
|
305
|
+
void (record ? confirmation.reject(record.token, sessionId, reason) : chat.deny(toolCallId, reason)).catch((error) => setActionError(error instanceof Error ? error : new Error("Action rejection failed.")));
|
|
306
|
+
};
|
|
307
|
+
const targets = (0, import_chat.getLifecycleTargets)(chat.messages);
|
|
308
|
+
const runLifecycle = (operation) => {
|
|
309
|
+
setActionError(void 0);
|
|
310
|
+
void operation.catch((error) => setActionError(error instanceof Error ? error : new Error("Lifecycle operation failed.")));
|
|
311
|
+
};
|
|
312
|
+
const renderFrame = (frame, key) => {
|
|
313
|
+
const manifest = definition.components;
|
|
314
|
+
const resolved = manifest === void 0 ? void 0 : (0, import_chat.resolveComponentFrame)(frame, manifest);
|
|
315
|
+
if (resolved?.ok && slots.StandardComponent === void 0 && !import_chat.STANDARD_COMPONENT_KEYS.includes(frame.componentKey)) {
|
|
316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { "data-ak-component-fallback": "", children: (0, import_chat.formatSemanticFallback)(frame.fallback) }, key);
|
|
317
|
+
}
|
|
318
|
+
if (resolved?.ok) return frame.componentKey === "choice-list" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChoiceListSlot, { frame, manifest, disabled: resolvedInstances.has(frame.instanceId), onSelect: (event) => selectComponent(event, frame) }, key) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StandardComponentSlot, { frame, manifest, disabled: resolvedInstances.has(frame.instanceId), onInteract: interactComponent }, key);
|
|
319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { "data-ak-component-fallback": "", children: (0, import_chat.formatSemanticFallback)(frame.fallback) }, key);
|
|
320
|
+
};
|
|
321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-label": `${definition.id} chat`, "data-ak-app-chat": "", style: themeInput === void 0 ? void 0 : toChatCssVariables(theme), children: [
|
|
322
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-live": "polite", "aria-relevant": "additions text", role: "log", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContainerSlot, { children: [
|
|
323
|
+
chat.messages.map((message) => {
|
|
324
|
+
const contentCandidate = message.role === "assistant" && (0, import_chat_protocol.isAssistantContentCandidate)(message.content);
|
|
325
|
+
const content = contentCandidate ? (0, import_chat_protocol.decodeAssistantContent)(message.content) : void 0;
|
|
326
|
+
if (content?.ok) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-ak-assistant-content": "", children: coalesceTextParts(content.parts).map((part, index) => part.kind === "text" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageSlot, { message: { ...message, content: part.text } }, `${message.id}:text:${index}`) : renderFrame(part.frame, `${message.id}:component:${index}`)) }, message.id);
|
|
327
|
+
if (content && !content.ok) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", "data-ak-component-diagnostic": content.diagnostic.code, children: content.diagnostic.message }, message.id);
|
|
328
|
+
const candidate = message.role === "assistant" && (0, import_chat_protocol.isComponentFrameCandidate)(message.content);
|
|
329
|
+
const decoded = candidate ? (0, import_chat_protocol.decodeComponentFrame)(message.content) : void 0;
|
|
330
|
+
if (decoded?.ok) {
|
|
331
|
+
return renderFrame(decoded.frame, message.id);
|
|
332
|
+
}
|
|
333
|
+
if (decoded && !decoded.ok) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", "data-ak-component-diagnostic": decoded.diagnostic.code, children: decoded.diagnostic.message }, message.id);
|
|
334
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageSlot, { message }, message.id);
|
|
335
|
+
}),
|
|
336
|
+
chat.messages.flatMap((message) => message.toolCalls ?? []).map((toolCall) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfirmationSlot, { toolCall, onApprove: approve, onDeny: deny }, toolCall.id)),
|
|
337
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThinkingSlot, { visible: chat.status === "streaming" })
|
|
338
|
+
] }) }),
|
|
339
|
+
chat.error || actionError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", style: { color: theme.colors.danger }, children: chat.error?.message ?? actionError?.message }) : null,
|
|
340
|
+
chat.status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: chat.stop, children: "Stop" }) : null,
|
|
341
|
+
chat.status !== "streaming" && targets.userId ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "aria-label": "Response actions", children: [
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", "aria-label": "Retry response", onClick: () => runLifecycle(chat.retry()), children: "Retry" }),
|
|
343
|
+
targets.assistantId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", "aria-label": "Regenerate response", onClick: () => runLifecycle(chat.regenerate(targets.assistantId)), children: "Regenerate" }) : null,
|
|
344
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => setEditDraft({ messageId: targets.userId, content: chat.messages.find((message) => message.id === targets.userId)?.content ?? "" }), children: "Edit last message" }),
|
|
345
|
+
editDraft === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: (event) => {
|
|
346
|
+
event.preventDefault();
|
|
347
|
+
if (editDraft.content.trim() === "") return;
|
|
348
|
+
runLifecycle(chat.edit(editDraft.messageId, editDraft.content));
|
|
349
|
+
setEditDraft(void 0);
|
|
350
|
+
}, children: [
|
|
351
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
|
|
352
|
+
"Edit message",
|
|
353
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": "Edit message", value: editDraft.content, onChange: (event) => setEditDraft({ ...editDraft, content: event.target.value }) })
|
|
354
|
+
] }),
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", "aria-label": "Save edit", children: "Save edit" }),
|
|
356
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => setEditDraft(void 0), children: "Cancel edit" })
|
|
357
|
+
] })
|
|
358
|
+
] }) : null,
|
|
359
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
360
|
+
InputSlot,
|
|
361
|
+
{
|
|
362
|
+
chat,
|
|
363
|
+
disabled: chat.status === "streaming",
|
|
364
|
+
...placeholder === void 0 ? {} : { placeholder }
|
|
365
|
+
}
|
|
366
|
+
)
|
|
367
|
+
] });
|
|
368
|
+
};
|
|
369
|
+
var AgentChat = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentChatSession, { ...props }, `${props.definition.id}:${props.definition.revision ?? 1}:${props.session?.sessionId ?? "new"}`);
|
|
370
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
371
|
+
0 && (module.exports = {
|
|
372
|
+
AgentChat,
|
|
373
|
+
ChoiceList,
|
|
374
|
+
StandardComponent,
|
|
375
|
+
toChatCssVariables
|
|
376
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ChatDefinition, ChatSession, ChatThemeInput, ComponentManifest } from '@agentskit/chat';
|
|
2
|
+
export { ChatDefinition } from '@agentskit/chat';
|
|
3
|
+
import { ComponentSelectionEvent, ComponentInteractionEvent, ComponentRenderFrame } from '@agentskit/chat-protocol';
|
|
4
|
+
import { ChatContainer, Message, InputBar, ThinkingIndicator, ToolConfirmation } from '@agentskit/react';
|
|
5
|
+
import { ComponentType, ComponentProps, ReactElement, CSSProperties } from 'react';
|
|
6
|
+
|
|
7
|
+
type ChatCssVariables = CSSProperties & {
|
|
8
|
+
readonly [key: `--ak-${string}`]: string | number;
|
|
9
|
+
};
|
|
10
|
+
declare const toChatCssVariables: (input?: ChatThemeInput) => ChatCssVariables;
|
|
11
|
+
interface AgentChatSlots {
|
|
12
|
+
readonly Container?: ComponentType<ComponentProps<typeof ChatContainer>>;
|
|
13
|
+
readonly Message?: ComponentType<ComponentProps<typeof Message>>;
|
|
14
|
+
readonly Input?: ComponentType<ComponentProps<typeof InputBar>>;
|
|
15
|
+
readonly Thinking?: ComponentType<ComponentProps<typeof ThinkingIndicator>>;
|
|
16
|
+
readonly Confirmation?: ComponentType<ComponentProps<typeof ToolConfirmation>>;
|
|
17
|
+
readonly ChoiceList?: ComponentType<ChoiceListProps>;
|
|
18
|
+
readonly StandardComponent?: ComponentType<StandardComponentProps>;
|
|
19
|
+
}
|
|
20
|
+
interface AgentChatProps {
|
|
21
|
+
readonly definition: ChatDefinition;
|
|
22
|
+
readonly placeholder?: string;
|
|
23
|
+
readonly onComponentSelect?: (event: ComponentSelectionEvent) => void;
|
|
24
|
+
readonly onComponentInteract?: (event: ComponentInteractionEvent) => void;
|
|
25
|
+
readonly actionConfirmationTtlMs?: number;
|
|
26
|
+
readonly session?: ChatSession;
|
|
27
|
+
readonly theme?: ChatThemeInput;
|
|
28
|
+
readonly slots?: AgentChatSlots;
|
|
29
|
+
}
|
|
30
|
+
interface StandardComponentProps {
|
|
31
|
+
readonly frame: ComponentRenderFrame;
|
|
32
|
+
readonly manifest: ComponentManifest;
|
|
33
|
+
readonly onInteract: (event: ComponentInteractionEvent) => void;
|
|
34
|
+
readonly disabled?: boolean;
|
|
35
|
+
}
|
|
36
|
+
declare const StandardComponent: ({ frame, manifest, onInteract, disabled }: StandardComponentProps) => ReactElement | null;
|
|
37
|
+
interface ChoiceListProps {
|
|
38
|
+
readonly frame: unknown;
|
|
39
|
+
readonly manifest: ComponentManifest;
|
|
40
|
+
readonly onSelect: (event: ComponentSelectionEvent) => void;
|
|
41
|
+
readonly disabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
declare const ChoiceList: ({ frame, manifest, onSelect, disabled }: ChoiceListProps) => ReactElement | null;
|
|
44
|
+
declare const AgentChat: (props: AgentChatProps) => ReactElement;
|
|
45
|
+
|
|
46
|
+
export { AgentChat, type AgentChatProps, type AgentChatSlots, type ChatCssVariables, ChoiceList, type ChoiceListProps, StandardComponent, type StandardComponentProps, toChatCssVariables };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ChatDefinition, ChatSession, ChatThemeInput, ComponentManifest } from '@agentskit/chat';
|
|
2
|
+
export { ChatDefinition } from '@agentskit/chat';
|
|
3
|
+
import { ComponentSelectionEvent, ComponentInteractionEvent, ComponentRenderFrame } from '@agentskit/chat-protocol';
|
|
4
|
+
import { ChatContainer, Message, InputBar, ThinkingIndicator, ToolConfirmation } from '@agentskit/react';
|
|
5
|
+
import { ComponentType, ComponentProps, ReactElement, CSSProperties } from 'react';
|
|
6
|
+
|
|
7
|
+
type ChatCssVariables = CSSProperties & {
|
|
8
|
+
readonly [key: `--ak-${string}`]: string | number;
|
|
9
|
+
};
|
|
10
|
+
declare const toChatCssVariables: (input?: ChatThemeInput) => ChatCssVariables;
|
|
11
|
+
interface AgentChatSlots {
|
|
12
|
+
readonly Container?: ComponentType<ComponentProps<typeof ChatContainer>>;
|
|
13
|
+
readonly Message?: ComponentType<ComponentProps<typeof Message>>;
|
|
14
|
+
readonly Input?: ComponentType<ComponentProps<typeof InputBar>>;
|
|
15
|
+
readonly Thinking?: ComponentType<ComponentProps<typeof ThinkingIndicator>>;
|
|
16
|
+
readonly Confirmation?: ComponentType<ComponentProps<typeof ToolConfirmation>>;
|
|
17
|
+
readonly ChoiceList?: ComponentType<ChoiceListProps>;
|
|
18
|
+
readonly StandardComponent?: ComponentType<StandardComponentProps>;
|
|
19
|
+
}
|
|
20
|
+
interface AgentChatProps {
|
|
21
|
+
readonly definition: ChatDefinition;
|
|
22
|
+
readonly placeholder?: string;
|
|
23
|
+
readonly onComponentSelect?: (event: ComponentSelectionEvent) => void;
|
|
24
|
+
readonly onComponentInteract?: (event: ComponentInteractionEvent) => void;
|
|
25
|
+
readonly actionConfirmationTtlMs?: number;
|
|
26
|
+
readonly session?: ChatSession;
|
|
27
|
+
readonly theme?: ChatThemeInput;
|
|
28
|
+
readonly slots?: AgentChatSlots;
|
|
29
|
+
}
|
|
30
|
+
interface StandardComponentProps {
|
|
31
|
+
readonly frame: ComponentRenderFrame;
|
|
32
|
+
readonly manifest: ComponentManifest;
|
|
33
|
+
readonly onInteract: (event: ComponentInteractionEvent) => void;
|
|
34
|
+
readonly disabled?: boolean;
|
|
35
|
+
}
|
|
36
|
+
declare const StandardComponent: ({ frame, manifest, onInteract, disabled }: StandardComponentProps) => ReactElement | null;
|
|
37
|
+
interface ChoiceListProps {
|
|
38
|
+
readonly frame: unknown;
|
|
39
|
+
readonly manifest: ComponentManifest;
|
|
40
|
+
readonly onSelect: (event: ComponentSelectionEvent) => void;
|
|
41
|
+
readonly disabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
declare const ChoiceList: ({ frame, manifest, onSelect, disabled }: ChoiceListProps) => ReactElement | null;
|
|
44
|
+
declare const AgentChat: (props: AgentChatProps) => ReactElement;
|
|
45
|
+
|
|
46
|
+
export { AgentChat, type AgentChatProps, type AgentChatSlots, type ChatCssVariables, ChoiceList, type ChoiceListProps, StandardComponent, type StandardComponentProps, toChatCssVariables };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// src/index.tsx
|
|
2
|
+
import { ApprovalRequestPropsSchema, ButtonGroupPropsSchema, ConfirmationPropsSchema, ErrorNoticePropsSchema, FileAttachmentPropsSchema, FormPropsSchema, LinkCardPropsSchema, ProgressPropsSchema, SourceListPropsSchema, STANDARD_COMPONENT_KEYS, TablePropsSchema, ToolCallPropsSchema, createComponentInteraction, formatSemanticFallback, getLifecycleTargets, resolveChatSession, resolveChatTheme, resolveChoiceAction, resolveChoiceListFrame, resolveComponentFrame, selectChoice } from "@agentskit/chat";
|
|
3
|
+
import { decodeAssistantContent, decodeComponentFrame, isAssistantContentCandidate, isComponentFrameCandidate } from "@agentskit/chat-protocol";
|
|
4
|
+
import {
|
|
5
|
+
ChatContainer,
|
|
6
|
+
InputBar,
|
|
7
|
+
Message,
|
|
8
|
+
ThinkingIndicator,
|
|
9
|
+
ToolConfirmation,
|
|
10
|
+
useChat
|
|
11
|
+
} from "@agentskit/react";
|
|
12
|
+
import { useMemo, useRef, useState } from "react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
var toChatCssVariables = (input) => {
|
|
15
|
+
const theme = resolveChatTheme(input);
|
|
16
|
+
return {
|
|
17
|
+
"--ak-color-bg": theme.colors.background,
|
|
18
|
+
"--ak-color-surface": theme.colors.surface,
|
|
19
|
+
"--ak-color-border": theme.colors.border,
|
|
20
|
+
"--ak-color-text": theme.colors.text,
|
|
21
|
+
"--ak-color-text-muted": theme.colors.muted,
|
|
22
|
+
"--ak-color-bubble-user": theme.colors.accent,
|
|
23
|
+
"--ak-color-bubble-user-text": theme.colors.onAccent,
|
|
24
|
+
"--ak-color-bubble-assistant": theme.colors.surface,
|
|
25
|
+
"--ak-color-bubble-assistant-text": theme.colors.text,
|
|
26
|
+
"--ak-color-input-bg": theme.colors.background,
|
|
27
|
+
"--ak-color-input-border": theme.colors.border,
|
|
28
|
+
"--ak-color-input-focus": theme.colors.accent,
|
|
29
|
+
"--ak-color-button": theme.colors.accent,
|
|
30
|
+
"--ak-color-button-text": theme.colors.onAccent,
|
|
31
|
+
"--ak-color-tool-bg": theme.colors.surface,
|
|
32
|
+
"--ak-color-tool-border": theme.colors.border,
|
|
33
|
+
"--ak-app-color-danger": theme.colors.danger,
|
|
34
|
+
"--ak-font-family": theme.fontFamily === "system" ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" : theme.fontFamily,
|
|
35
|
+
"--ak-radius": `${theme.radius.medium}px`,
|
|
36
|
+
"--ak-radius-lg": `${theme.radius.large}px`,
|
|
37
|
+
"--ak-spacing-sm": `${theme.spacing.small}px`,
|
|
38
|
+
"--ak-spacing-md": `${theme.spacing.medium}px`,
|
|
39
|
+
"--ak-spacing-lg": `${theme.spacing.large}px`
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
var coalesceTextParts = (parts) => {
|
|
43
|
+
const result = [];
|
|
44
|
+
for (const part of parts) {
|
|
45
|
+
const previous = result.at(-1);
|
|
46
|
+
if (part.kind === "text" && previous?.kind === "text") result[result.length - 1] = { kind: "text", text: previous.text + part.text };
|
|
47
|
+
else result.push(part);
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
var StandardForm = ({ frame, manifest, onInteract, disabled }) => {
|
|
52
|
+
const props = FormPropsSchema.parse(frame.props);
|
|
53
|
+
const [values, setValues] = useState({});
|
|
54
|
+
return /* @__PURE__ */ jsxs("form", { "aria-label": props.title ?? "Form", "data-ak-component": "form", onSubmit: (event) => {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
onInteract(createComponentInteraction(frame, manifest, "submit", values));
|
|
57
|
+
}, children: [
|
|
58
|
+
props.title ? /* @__PURE__ */ jsx("h3", { children: props.title }) : null,
|
|
59
|
+
props.fields.map((field) => /* @__PURE__ */ jsxs("label", { children: [
|
|
60
|
+
field.label,
|
|
61
|
+
field.type === "select" ? /* @__PURE__ */ jsxs("select", { required: field.required, disabled, value: String(values[field.id] ?? ""), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.value })), children: [
|
|
62
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select" }),
|
|
63
|
+
field.options?.map((option) => /* @__PURE__ */ jsx("option", { value: option.id, children: option.label }, option.id))
|
|
64
|
+
] }) : /* @__PURE__ */ jsx("input", { type: field.type, required: field.required, disabled, placeholder: field.placeholder, ...field.type === "checkbox" ? { checked: Boolean(values[field.id]), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.checked })) } : { value: String(values[field.id] ?? ""), onChange: (event) => setValues((current) => ({ ...current, [field.id]: event.target.value })) } })
|
|
65
|
+
] }, field.id)),
|
|
66
|
+
/* @__PURE__ */ jsx("button", { type: "submit", disabled, children: props.submitLabel })
|
|
67
|
+
] });
|
|
68
|
+
};
|
|
69
|
+
var StandardComponent = ({ frame, manifest, onInteract, disabled = false }) => {
|
|
70
|
+
if (!resolveComponentFrame(frame, manifest).ok || frame.componentKey === "choice-list") return null;
|
|
71
|
+
const emit = (event, value) => onInteract(createComponentInteraction(frame, manifest, event, value));
|
|
72
|
+
switch (frame.componentKey) {
|
|
73
|
+
case "button-group": {
|
|
74
|
+
const props = ButtonGroupPropsSchema.parse(frame.props);
|
|
75
|
+
return /* @__PURE__ */ jsxs("fieldset", { "aria-label": props.label, "data-ak-component": "button-group", children: [
|
|
76
|
+
/* @__PURE__ */ jsx("legend", { children: props.label }),
|
|
77
|
+
props.buttons.map((button) => /* @__PURE__ */ jsx("button", { type: "button", disabled: disabled || button.disabled, onClick: () => emit("select", button.id), children: button.label }, button.id))
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
case "form":
|
|
81
|
+
return /* @__PURE__ */ jsx(StandardForm, { frame, manifest, onInteract, disabled });
|
|
82
|
+
case "confirmation": {
|
|
83
|
+
const props = ConfirmationPropsSchema.parse(frame.props);
|
|
84
|
+
return /* @__PURE__ */ jsxs("section", { "aria-label": props.title, "data-ak-component": "confirmation", children: [
|
|
85
|
+
/* @__PURE__ */ jsx("h3", { children: props.title }),
|
|
86
|
+
/* @__PURE__ */ jsx("p", { children: props.message }),
|
|
87
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled, onClick: () => emit("confirm"), children: props.confirmLabel }),
|
|
88
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled, onClick: () => emit("cancel"), children: props.cancelLabel })
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
case "progress": {
|
|
92
|
+
const props = ProgressPropsSchema.parse(frame.props);
|
|
93
|
+
return /* @__PURE__ */ jsxs("div", { "data-ak-component": "progress", children: [
|
|
94
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
95
|
+
props.label,
|
|
96
|
+
/* @__PURE__ */ jsx("progress", { max: 100, value: props.value })
|
|
97
|
+
] }),
|
|
98
|
+
props.status ? /* @__PURE__ */ jsx("p", { children: props.status }) : null
|
|
99
|
+
] });
|
|
100
|
+
}
|
|
101
|
+
case "source-list": {
|
|
102
|
+
const props = SourceListPropsSchema.parse(frame.props);
|
|
103
|
+
return /* @__PURE__ */ jsxs("section", { "data-ak-component": "source-list", children: [
|
|
104
|
+
/* @__PURE__ */ jsx("h3", { children: props.label }),
|
|
105
|
+
/* @__PURE__ */ jsx("ul", { children: props.sources.map((source) => /* @__PURE__ */ jsxs("li", { children: [
|
|
106
|
+
source.url ? /* @__PURE__ */ jsx("a", { href: source.url, onClick: (event) => {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
emit("open", source.id);
|
|
109
|
+
}, children: source.title }) : source.title,
|
|
110
|
+
source.snippet ? /* @__PURE__ */ jsx("p", { children: source.snippet }) : null
|
|
111
|
+
] }, source.id)) })
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
case "link-card": {
|
|
115
|
+
const props = LinkCardPropsSchema.parse(frame.props);
|
|
116
|
+
return /* @__PURE__ */ jsxs("a", { "data-ak-component": "link-card", href: props.href, onClick: (event) => {
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
emit("open", props.href);
|
|
119
|
+
}, children: [
|
|
120
|
+
/* @__PURE__ */ jsx("strong", { children: props.title }),
|
|
121
|
+
props.description ? /* @__PURE__ */ jsx("span", { children: props.description }) : null,
|
|
122
|
+
props.label ? /* @__PURE__ */ jsx("span", { children: props.label }) : null
|
|
123
|
+
] });
|
|
124
|
+
}
|
|
125
|
+
case "error-notice": {
|
|
126
|
+
const props = ErrorNoticePropsSchema.parse(frame.props);
|
|
127
|
+
return /* @__PURE__ */ jsxs("section", { role: "alert", "data-ak-component": "error-notice", children: [
|
|
128
|
+
/* @__PURE__ */ jsx("strong", { children: props.title }),
|
|
129
|
+
/* @__PURE__ */ jsx("p", { children: props.message }),
|
|
130
|
+
props.code ? /* @__PURE__ */ jsx("code", { children: props.code }) : null,
|
|
131
|
+
props.retryLabel ? /* @__PURE__ */ jsx("button", { type: "button", disabled, onClick: () => emit("retry"), children: props.retryLabel }) : null
|
|
132
|
+
] });
|
|
133
|
+
}
|
|
134
|
+
case "tool-call": {
|
|
135
|
+
const props = ToolCallPropsSchema.parse(frame.props);
|
|
136
|
+
return /* @__PURE__ */ jsxs("section", { role: "status", "data-ak-component": "tool-call", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("strong", { children: props.name }),
|
|
138
|
+
/* @__PURE__ */ jsx("span", { children: props.status }),
|
|
139
|
+
props.arguments ? /* @__PURE__ */ jsx("pre", { children: JSON.stringify(props.arguments, null, 2) }) : null,
|
|
140
|
+
props.result === void 0 ? null : /* @__PURE__ */ jsx("pre", { children: JSON.stringify(props.result, null, 2) })
|
|
141
|
+
] });
|
|
142
|
+
}
|
|
143
|
+
case "approval-request": {
|
|
144
|
+
const props = ApprovalRequestPropsSchema.parse(frame.props);
|
|
145
|
+
return /* @__PURE__ */ jsxs("section", { "aria-label": props.title, "data-ak-component": "approval-request", children: [
|
|
146
|
+
/* @__PURE__ */ jsx("h3", { children: props.title }),
|
|
147
|
+
/* @__PURE__ */ jsx("p", { children: props.description }),
|
|
148
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled, onClick: () => emit("approve"), children: props.approveLabel }),
|
|
149
|
+
/* @__PURE__ */ jsx("button", { type: "button", disabled, onClick: () => emit("deny"), children: props.denyLabel })
|
|
150
|
+
] });
|
|
151
|
+
}
|
|
152
|
+
case "table": {
|
|
153
|
+
const props = TablePropsSchema.parse(frame.props);
|
|
154
|
+
return /* @__PURE__ */ jsxs("table", { "data-ak-component": "table", children: [
|
|
155
|
+
/* @__PURE__ */ jsx("caption", { children: props.caption }),
|
|
156
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: props.columns.map((column) => /* @__PURE__ */ jsx("th", { scope: "col", children: column.label }, column.key)) }) }),
|
|
157
|
+
/* @__PURE__ */ jsx("tbody", { children: props.rows.map((row, index) => /* @__PURE__ */ jsx("tr", { children: props.columns.map((column) => /* @__PURE__ */ jsx("td", { children: String(row[column.key] ?? "") }, column.key)) }, index)) })
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
case "file-attachment": {
|
|
161
|
+
const props = FileAttachmentPropsSchema.parse(frame.props);
|
|
162
|
+
return /* @__PURE__ */ jsxs("article", { "data-ak-component": "file-attachment", children: [
|
|
163
|
+
/* @__PURE__ */ jsx("strong", { children: props.name }),
|
|
164
|
+
/* @__PURE__ */ jsx("span", { children: props.mimeType }),
|
|
165
|
+
props.sizeBytes === void 0 ? null : /* @__PURE__ */ jsxs("span", { children: [
|
|
166
|
+
props.sizeBytes,
|
|
167
|
+
" bytes"
|
|
168
|
+
] }),
|
|
169
|
+
props.url ? /* @__PURE__ */ jsx("a", { href: props.url, onClick: (event) => {
|
|
170
|
+
event.preventDefault();
|
|
171
|
+
emit("open", props.url);
|
|
172
|
+
}, children: "Open" }) : null
|
|
173
|
+
] });
|
|
174
|
+
}
|
|
175
|
+
default:
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
var ChoiceList = ({ frame, manifest, onSelect, disabled = false }) => {
|
|
180
|
+
const resolved = resolveChoiceListFrame(frame, manifest);
|
|
181
|
+
if (!resolved.ok) return null;
|
|
182
|
+
return /* @__PURE__ */ jsxs("fieldset", { "aria-label": resolved.props.prompt, "data-ak-component": "choice-list", children: [
|
|
183
|
+
/* @__PURE__ */ jsx("legend", { children: resolved.props.prompt }),
|
|
184
|
+
resolved.props.choices.map((choice) => /* @__PURE__ */ jsxs("button", { type: "button", disabled, onClick: () => onSelect(selectChoice(resolved.frame, choice.id)), children: [
|
|
185
|
+
/* @__PURE__ */ jsx("span", { children: choice.label }),
|
|
186
|
+
choice.description === void 0 ? null : /* @__PURE__ */ jsx("small", { children: choice.description })
|
|
187
|
+
] }, choice.id))
|
|
188
|
+
] });
|
|
189
|
+
};
|
|
190
|
+
var AgentChatSession = ({ definition, placeholder, onComponentSelect = () => void 0, onComponentInteract = () => void 0, actionConfirmationTtlMs, session: preparedSession, theme: themeInput, slots = {} }) => {
|
|
191
|
+
const theme = resolveChatTheme(themeInput);
|
|
192
|
+
const ContainerSlot = slots.Container ?? ChatContainer;
|
|
193
|
+
const MessageSlot = slots.Message ?? Message;
|
|
194
|
+
const InputSlot = slots.Input ?? InputBar;
|
|
195
|
+
const ThinkingSlot = slots.Thinking ?? ThinkingIndicator;
|
|
196
|
+
const ConfirmationSlot = slots.Confirmation ?? ToolConfirmation;
|
|
197
|
+
const ChoiceListSlot = slots.ChoiceList ?? ChoiceList;
|
|
198
|
+
const StandardComponentSlot = slots.StandardComponent ?? StandardComponent;
|
|
199
|
+
const [session] = useState(() => resolveChatSession(definition, preparedSession));
|
|
200
|
+
const sessionId = session.sessionId;
|
|
201
|
+
const [actionError, setActionError] = useState();
|
|
202
|
+
const [editDraft, setEditDraft] = useState();
|
|
203
|
+
const [resolvedInstances, setResolvedInstances] = useState(() => /* @__PURE__ */ new Set());
|
|
204
|
+
const resolvedInstancesRef = useRef(/* @__PURE__ */ new Set());
|
|
205
|
+
const config = useMemo(() => session.updateChat(definition.chat), [definition.chat, session]);
|
|
206
|
+
const chat = useChat(config);
|
|
207
|
+
const chatRef = useRef(chat);
|
|
208
|
+
chatRef.current = chat;
|
|
209
|
+
const [confirmation] = useState(() => session.createConfirmation({ ...actionConfirmationTtlMs === void 0 ? {} : { ttlMs: actionConfirmationTtlMs }, chat: {
|
|
210
|
+
proposeToolCall: (proposal) => chatRef.current.proposeToolCall(proposal),
|
|
211
|
+
approve: (id) => chatRef.current.approve(id),
|
|
212
|
+
deny: (id, reason) => chatRef.current.deny(id, reason)
|
|
213
|
+
} }));
|
|
214
|
+
const selectComponent = (event, frame) => {
|
|
215
|
+
if (resolvedInstancesRef.current.has(event.instanceId)) return;
|
|
216
|
+
setActionError(void 0);
|
|
217
|
+
resolvedInstancesRef.current.add(event.instanceId);
|
|
218
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
219
|
+
try {
|
|
220
|
+
onComponentSelect(event);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
setActionError(error instanceof Error ? error : new Error("Component selection callback failed."));
|
|
223
|
+
}
|
|
224
|
+
const action = resolveChoiceAction(frame, event.choiceId);
|
|
225
|
+
if (action) void confirmation.propose(action).catch((error) => {
|
|
226
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
227
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
228
|
+
setActionError(error instanceof Error ? error : new Error("Action proposal failed."));
|
|
229
|
+
});
|
|
230
|
+
else {
|
|
231
|
+
let submission;
|
|
232
|
+
try {
|
|
233
|
+
submission = definition.choiceSubmission?.(frame, event.choiceId, { sessionId });
|
|
234
|
+
} catch (error) {
|
|
235
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
236
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
237
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission authorization failed."));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (submission && "unavailable" in submission) {
|
|
241
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
242
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
243
|
+
setActionError(new Error("This deterministic choice expired. Select it again after asking the question once more."));
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (submission) void chatRef.current.send(submission.value).then(
|
|
247
|
+
() => {
|
|
248
|
+
try {
|
|
249
|
+
submission.commit();
|
|
250
|
+
} catch (error) {
|
|
251
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission settlement failed."));
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
(error) => {
|
|
255
|
+
try {
|
|
256
|
+
submission.release();
|
|
257
|
+
} catch {
|
|
258
|
+
} finally {
|
|
259
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
260
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
261
|
+
}
|
|
262
|
+
setActionError(error instanceof Error ? error : new Error("Choice submission failed."));
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
const interactComponent = (event) => {
|
|
268
|
+
if (resolvedInstancesRef.current.has(event.instanceId)) return;
|
|
269
|
+
resolvedInstancesRef.current.add(event.instanceId);
|
|
270
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
271
|
+
try {
|
|
272
|
+
onComponentInteract(event);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
resolvedInstancesRef.current.delete(event.instanceId);
|
|
275
|
+
setResolvedInstances(new Set(resolvedInstancesRef.current));
|
|
276
|
+
setActionError(error instanceof Error ? error : new Error("Component interaction callback failed."));
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
const approve = (toolCallId) => {
|
|
280
|
+
const record = confirmation.getByToolCall(toolCallId);
|
|
281
|
+
void (record ? confirmation.approve(record.token, sessionId) : chat.approve(toolCallId)).catch((error) => setActionError(error instanceof Error ? error : new Error("Action approval failed.")));
|
|
282
|
+
};
|
|
283
|
+
const deny = (toolCallId, reason) => {
|
|
284
|
+
const record = confirmation.getByToolCall(toolCallId);
|
|
285
|
+
void (record ? confirmation.reject(record.token, sessionId, reason) : chat.deny(toolCallId, reason)).catch((error) => setActionError(error instanceof Error ? error : new Error("Action rejection failed.")));
|
|
286
|
+
};
|
|
287
|
+
const targets = getLifecycleTargets(chat.messages);
|
|
288
|
+
const runLifecycle = (operation) => {
|
|
289
|
+
setActionError(void 0);
|
|
290
|
+
void operation.catch((error) => setActionError(error instanceof Error ? error : new Error("Lifecycle operation failed.")));
|
|
291
|
+
};
|
|
292
|
+
const renderFrame = (frame, key) => {
|
|
293
|
+
const manifest = definition.components;
|
|
294
|
+
const resolved = manifest === void 0 ? void 0 : resolveComponentFrame(frame, manifest);
|
|
295
|
+
if (resolved?.ok && slots.StandardComponent === void 0 && !STANDARD_COMPONENT_KEYS.includes(frame.componentKey)) {
|
|
296
|
+
return /* @__PURE__ */ jsx("p", { "data-ak-component-fallback": "", children: formatSemanticFallback(frame.fallback) }, key);
|
|
297
|
+
}
|
|
298
|
+
if (resolved?.ok) return frame.componentKey === "choice-list" ? /* @__PURE__ */ jsx(ChoiceListSlot, { frame, manifest, disabled: resolvedInstances.has(frame.instanceId), onSelect: (event) => selectComponent(event, frame) }, key) : /* @__PURE__ */ jsx(StandardComponentSlot, { frame, manifest, disabled: resolvedInstances.has(frame.instanceId), onInteract: interactComponent }, key);
|
|
299
|
+
return /* @__PURE__ */ jsx("p", { "data-ak-component-fallback": "", children: formatSemanticFallback(frame.fallback) }, key);
|
|
300
|
+
};
|
|
301
|
+
return /* @__PURE__ */ jsxs("section", { "aria-label": `${definition.id} chat`, "data-ak-app-chat": "", style: themeInput === void 0 ? void 0 : toChatCssVariables(theme), children: [
|
|
302
|
+
/* @__PURE__ */ jsx("div", { "aria-live": "polite", "aria-relevant": "additions text", role: "log", children: /* @__PURE__ */ jsxs(ContainerSlot, { children: [
|
|
303
|
+
chat.messages.map((message) => {
|
|
304
|
+
const contentCandidate = message.role === "assistant" && isAssistantContentCandidate(message.content);
|
|
305
|
+
const content = contentCandidate ? decodeAssistantContent(message.content) : void 0;
|
|
306
|
+
if (content?.ok) return /* @__PURE__ */ jsx("div", { "data-ak-assistant-content": "", children: coalesceTextParts(content.parts).map((part, index) => part.kind === "text" ? /* @__PURE__ */ jsx(MessageSlot, { message: { ...message, content: part.text } }, `${message.id}:text:${index}`) : renderFrame(part.frame, `${message.id}:component:${index}`)) }, message.id);
|
|
307
|
+
if (content && !content.ok) return /* @__PURE__ */ jsx("p", { role: "alert", "data-ak-component-diagnostic": content.diagnostic.code, children: content.diagnostic.message }, message.id);
|
|
308
|
+
const candidate = message.role === "assistant" && isComponentFrameCandidate(message.content);
|
|
309
|
+
const decoded = candidate ? decodeComponentFrame(message.content) : void 0;
|
|
310
|
+
if (decoded?.ok) {
|
|
311
|
+
return renderFrame(decoded.frame, message.id);
|
|
312
|
+
}
|
|
313
|
+
if (decoded && !decoded.ok) return /* @__PURE__ */ jsx("p", { role: "alert", "data-ak-component-diagnostic": decoded.diagnostic.code, children: decoded.diagnostic.message }, message.id);
|
|
314
|
+
return /* @__PURE__ */ jsx(MessageSlot, { message }, message.id);
|
|
315
|
+
}),
|
|
316
|
+
chat.messages.flatMap((message) => message.toolCalls ?? []).map((toolCall) => /* @__PURE__ */ jsx(ConfirmationSlot, { toolCall, onApprove: approve, onDeny: deny }, toolCall.id)),
|
|
317
|
+
/* @__PURE__ */ jsx(ThinkingSlot, { visible: chat.status === "streaming" })
|
|
318
|
+
] }) }),
|
|
319
|
+
chat.error || actionError ? /* @__PURE__ */ jsx("p", { role: "alert", style: { color: theme.colors.danger }, children: chat.error?.message ?? actionError?.message }) : null,
|
|
320
|
+
chat.status === "streaming" ? /* @__PURE__ */ jsx("button", { type: "button", onClick: chat.stop, children: "Stop" }) : null,
|
|
321
|
+
chat.status !== "streaming" && targets.userId ? /* @__PURE__ */ jsxs("div", { "aria-label": "Response actions", children: [
|
|
322
|
+
/* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Retry response", onClick: () => runLifecycle(chat.retry()), children: "Retry" }),
|
|
323
|
+
targets.assistantId ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Regenerate response", onClick: () => runLifecycle(chat.regenerate(targets.assistantId)), children: "Regenerate" }) : null,
|
|
324
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setEditDraft({ messageId: targets.userId, content: chat.messages.find((message) => message.id === targets.userId)?.content ?? "" }), children: "Edit last message" }),
|
|
325
|
+
editDraft === void 0 ? null : /* @__PURE__ */ jsxs("form", { onSubmit: (event) => {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
if (editDraft.content.trim() === "") return;
|
|
328
|
+
runLifecycle(chat.edit(editDraft.messageId, editDraft.content));
|
|
329
|
+
setEditDraft(void 0);
|
|
330
|
+
}, children: [
|
|
331
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
332
|
+
"Edit message",
|
|
333
|
+
/* @__PURE__ */ jsx("input", { "aria-label": "Edit message", value: editDraft.content, onChange: (event) => setEditDraft({ ...editDraft, content: event.target.value }) })
|
|
334
|
+
] }),
|
|
335
|
+
/* @__PURE__ */ jsx("button", { type: "submit", "aria-label": "Save edit", children: "Save edit" }),
|
|
336
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setEditDraft(void 0), children: "Cancel edit" })
|
|
337
|
+
] })
|
|
338
|
+
] }) : null,
|
|
339
|
+
/* @__PURE__ */ jsx(
|
|
340
|
+
InputSlot,
|
|
341
|
+
{
|
|
342
|
+
chat,
|
|
343
|
+
disabled: chat.status === "streaming",
|
|
344
|
+
...placeholder === void 0 ? {} : { placeholder }
|
|
345
|
+
}
|
|
346
|
+
)
|
|
347
|
+
] });
|
|
348
|
+
};
|
|
349
|
+
var AgentChat = (props) => /* @__PURE__ */ jsx(AgentChatSession, { ...props }, `${props.definition.id}:${props.definition.revision ?? 1}:${props.session?.sessionId ?? "new"}`);
|
|
350
|
+
export {
|
|
351
|
+
AgentChat,
|
|
352
|
+
ChoiceList,
|
|
353
|
+
StandardComponent,
|
|
354
|
+
toChatCssVariables
|
|
355
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentskit/chat-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React application shell for AgentsKit Chat.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/AgentsKit-io/agentskit-chat.git",
|
|
9
|
+
"directory": "packages/react"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/AgentsKit-io/agentskit-chat#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/AgentsKit-io/agentskit-chat/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.cjs",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"require": "./dist/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@agentskit/chat": "0.1.0",
|
|
31
|
+
"@agentskit/chat-protocol": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@agentskit/react": "^0.7.1",
|
|
35
|
+
"react": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@agentskit/core": "^1.12.2",
|
|
39
|
+
"@agentskit/react": "^0.7.1",
|
|
40
|
+
"@testing-library/react": "^16.3.2",
|
|
41
|
+
"@types/react": "^19.2.17",
|
|
42
|
+
"happy-dom": "^20.10.3",
|
|
43
|
+
"react": "^19.2.7",
|
|
44
|
+
"react-dom": "^19.2.7",
|
|
45
|
+
"tsup": "^8.5.1"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public",
|
|
49
|
+
"provenance": true
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsup src/index.tsx --format esm,cjs --dts --clean --external react --external @agentskit/react",
|
|
53
|
+
"lint": "tsc --noEmit",
|
|
54
|
+
"test": "pnpm --filter @agentskit/chat-protocol build && pnpm --filter @agentskit/chat build && vitest run --environment happy-dom"
|
|
55
|
+
}
|
|
56
|
+
}
|