@pgege/kaboo-react 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -3
- package/CHANGELOG.md +36 -3
- package/README.md +58 -0
- package/dist/{chunk-RXZWOBSI.js → chunk-4TDUEMK5.js} +175 -2
- package/dist/chunk-4TDUEMK5.js.map +1 -0
- package/dist/copilotkit.cjs +158 -26
- package/dist/copilotkit.cjs.map +1 -1
- package/dist/copilotkit.d.cts +17 -2
- package/dist/copilotkit.d.ts +17 -2
- package/dist/copilotkit.js +118 -7
- package/dist/copilotkit.js.map +1 -1
- package/dist/index.cjs +1110 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +324 -4
- package/dist/index.d.ts +324 -4
- package/dist/index.js +951 -30
- package/dist/index.js.map +1 -1
- package/dist/styles.css +319 -0
- package/llms-full.txt +93 -5
- package/package.json +1 -1
- package/dist/chunk-RXZWOBSI.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -25,11 +25,11 @@ yarn examples:typecheck # type-check examples/ against built types
|
|
|
25
25
|
- **Two barrels.**
|
|
26
26
|
- `kaboo-react` (`src/index.ts`) — framework-agnostic contexts, hooks,
|
|
27
27
|
components, utils, formatters, types.
|
|
28
|
-
-
|
|
28
|
+
- `kaboo-react/copilotkit` (`src/copilotkit.ts`) — integrations coupled to
|
|
29
29
|
CopilotKit. **Put any CopilotKit-dependent code here, never in the main
|
|
30
30
|
barrel.**
|
|
31
31
|
- **Stylesheet.** `src/styles.css` is copied to `dist/styles.css` by tsup and
|
|
32
|
-
exported as
|
|
32
|
+
exported as `kaboo-react/styles.css`. Theming is via CSS variables only
|
|
33
33
|
(`--background`/`--foreground`/`--card`/`--muted`/`--border` + `--kaboo-*`
|
|
34
34
|
overrides). Do not add a CSS-in-JS dependency.
|
|
35
35
|
- **Peer deps.** `react`, `react-dom`, `@copilotkit/react-core`. Do not add
|
|
@@ -96,6 +96,6 @@ yarn examples:typecheck # type-check examples/ against built types
|
|
|
96
96
|
|
|
97
97
|
- [kaboo-workflows](https://github.com/gl-pgege/kaboo-workflows)
|
|
98
98
|
- [kaboo-runtime](https://github.com/gl-pgege/kaboo-runtime)
|
|
99
|
-
- [kaboo-workflows-demo](https://github.com/gl-pgege/kaboo-
|
|
99
|
+
- [kaboo-workflows-demo](https://github.com/gl-pgege/kaboo-workflows-demo) — the
|
|
100
100
|
runnable, end-to-end reference that consumes this library.
|
|
101
101
|
- [The kaboo stack](https://gl-pgege.github.io/kaboo-docs/) — umbrella landing.
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **References & attachments.** A pluggable `@`/`+` reference system for the chat
|
|
15
|
+
composer:
|
|
16
|
+
- `KabooReferenceInput` — a drop-in `<CopilotChat input={…}>` slot that keeps
|
|
17
|
+
CopilotKit's native input chrome but renders each reference as an interactive
|
|
18
|
+
inline chip, with a shared searchable popover for both `+` and `@`.
|
|
19
|
+
- `ReferencesProvider` / `ReferenceStateSync` / `useReferences` — register
|
|
20
|
+
providers, stage pending references, and sync object references onto
|
|
21
|
+
`agent.state`.
|
|
22
|
+
- `uploadProvider` (+ `isUploadProvider`, `buildAttachmentsConfig`,
|
|
23
|
+
`uploadFileToReference`, `UPLOAD_MARKER`) — the built-in file-attachment
|
|
24
|
+
provider, with URL or base64 upload.
|
|
25
|
+
- Serialization helpers (`mintReferenceId`, `referenceMarker`,
|
|
26
|
+
`attachmentToInputContent`, `objectToStateEntry`, `serializeReferences`,
|
|
27
|
+
`withReferenceState`, `buildUserContent`).
|
|
28
|
+
- Public types/constants: `ReferenceProvider`, `ReferenceItem`,
|
|
29
|
+
`PendingReference`, `ReferenceTransport`, `REFERENCE_METADATA_KEYS`,
|
|
30
|
+
`REFERENCES_STATE_KEY`.
|
|
31
|
+
- `kaboo-react/copilotkit`: `KabooUserMessage` — renders sent references as
|
|
32
|
+
non-interactive chips (inline `@` mentions and a file/object chip row) in the
|
|
33
|
+
user bubble.
|
|
34
|
+
- "References & providers" guide (`docs/references.md`) documenting the provider
|
|
35
|
+
contract, both transports, and searchable vs action-only providers.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- `KabooMessageView` now wires `KabooUserMessage` so references sent with a
|
|
40
|
+
message render as chips instead of raw text.
|
|
41
|
+
|
|
10
42
|
## [0.1.0]
|
|
11
43
|
|
|
12
44
|
Initial release.
|
|
@@ -20,10 +52,11 @@ Initial release.
|
|
|
20
52
|
`MiniTable`, `GlassTabs`, `DrillDetailView`, `MarkdownContent`,
|
|
21
53
|
`InterruptRenderer`), group helpers (`topLevelGroups`, `directChildren`) and
|
|
22
54
|
formatters (`formatToolInput`, `formatToolResult`, `normalizeResult`).
|
|
23
|
-
-
|
|
55
|
+
- `kaboo-react/copilotkit` subpath: CopilotKit-coupled integrations
|
|
24
56
|
(`KabooMessageView`, `KabooAssistantMessage`, `KabooInlineCards`,
|
|
25
57
|
`KabooInterruptHandler`, `KabooAskUser`, `KabooToolRender`).
|
|
26
|
-
-
|
|
58
|
+
- `kaboo-react/styles.css` stylesheet with themeable `--kaboo-*` design tokens.
|
|
27
59
|
|
|
28
|
-
[Unreleased]: https://github.com/gl-pgege/kaboo-react/compare/v0.
|
|
60
|
+
[Unreleased]: https://github.com/gl-pgege/kaboo-react/compare/v0.2.0...HEAD
|
|
61
|
+
[0.2.0]: https://github.com/gl-pgege/kaboo-react/compare/v0.1.0...v0.2.0
|
|
29
62
|
[0.1.0]: https://github.com/gl-pgege/kaboo-react/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ endpoint to wire up: kaboo-react is a batteries-included CopilotKit plugin.
|
|
|
23
23
|
- **Human-in-the-loop** — approval gates and forms, with N parallel interrupts
|
|
24
24
|
resolved independently.
|
|
25
25
|
- **Structured renderers** — plug custom UI for schema-shaped agent output.
|
|
26
|
+
- **References & attachments** — files and your own objects (tables, dashboards,
|
|
27
|
+
…) as interactive inline chips, added from one shared **+** / **@** popover.
|
|
26
28
|
- **Batteries included** — one `KabooProvider` renders `<CopilotKit>` and mounts
|
|
27
29
|
every context and handler for you.
|
|
28
30
|
- **Themeable** — styled with CSS variables and `--kaboo-*` tokens.
|
|
@@ -86,9 +88,65 @@ props via `copilotKitProps`.
|
|
|
86
88
|
- **Theming via CSS variables.** Components read standard design-system tokens and
|
|
87
89
|
accept `--kaboo-*` overrides.
|
|
88
90
|
|
|
91
|
+
## References & attachments
|
|
92
|
+
|
|
93
|
+
Let users attach things to a message. Everything is driven by **reference
|
|
94
|
+
providers** registered on `<KabooProvider references={…}>` and rendered by the
|
|
95
|
+
`KabooReferenceInput` slot. There are two transports:
|
|
96
|
+
|
|
97
|
+
- **Attachment** — a file/blob. Register the built-in `uploadProvider({ onUpload })`;
|
|
98
|
+
choosing "Attach a file" (from **+** or **@**) opens the picker, uploads, and
|
|
99
|
+
drops a file chip inline. Files ride the message as parts stamped with
|
|
100
|
+
`kaboo_id` / `kaboo_kind` / `kaboo_name`.
|
|
101
|
+
- **Object** — a pointer to one of *your* entities (`table`, `dashboard`, …).
|
|
102
|
+
Register a `ReferenceProvider`; selected objects sync into
|
|
103
|
+
`state.kaboo_references` for the backend to resolve, and appear inline as
|
|
104
|
+
`@name`.
|
|
105
|
+
|
|
106
|
+
```tsx no-verify
|
|
107
|
+
import {
|
|
108
|
+
KabooProvider,
|
|
109
|
+
KabooReferenceInput,
|
|
110
|
+
uploadProvider,
|
|
111
|
+
type ReferenceProvider,
|
|
112
|
+
} from "@pgege/kaboo-react";
|
|
113
|
+
|
|
114
|
+
// A custom object reference: three fields make it work.
|
|
115
|
+
const tableProvider: ReferenceProvider = {
|
|
116
|
+
id: "table",
|
|
117
|
+
label: "Tables",
|
|
118
|
+
icon: <Table2 size={16} />,
|
|
119
|
+
search: (q) => TABLES.filter((t) => t.label.includes(q)), // items under @
|
|
120
|
+
toReference: (item) => ({ transport: "object", kind: "table", id: item.id, name: item.label }),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
<KabooProvider
|
|
124
|
+
runtimeUrl="/api/copilotkit"
|
|
125
|
+
agent={agent}
|
|
126
|
+
references={[uploadProvider({ accept: "image/*,.pdf", onUpload }), tableProvider]}
|
|
127
|
+
>
|
|
128
|
+
<CopilotChat input={KabooReferenceInput} messageView={KabooMessageView} />
|
|
129
|
+
</KabooProvider>;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`KabooReferenceInput` is a drop-in `<CopilotChat input={…}>` slot. It keeps
|
|
133
|
+
CopilotKit's native input chrome (send button, disclaimer, theme) but swaps the
|
|
134
|
+
plain textarea for a lightweight editor where every reference renders as an
|
|
135
|
+
**interactive inline chip**: click a chip to swap it for another, or its `×` to
|
|
136
|
+
remove it. The **+** button and the **@** key open the *same* searchable
|
|
137
|
+
popover; it dismisses on outside-click / `Escape`. On submit the editor builds
|
|
138
|
+
the multimodal message (files as attachment parts, objects on
|
|
139
|
+
`state.kaboo_references`, cleared only after the run starts) and runs the agent.
|
|
140
|
+
`onUpload` should return a fetchable URL (not base64) so the transport and
|
|
141
|
+
persisted event log stay small. See [References & providers](./docs/references.md)
|
|
142
|
+
for the full provider contract (both transports, searchable vs action-only,
|
|
143
|
+
`toReference`), and kaboo-workflows' *Attachments & Multimodal* chapter for how
|
|
144
|
+
references reach each agent.
|
|
145
|
+
|
|
89
146
|
## Guides
|
|
90
147
|
|
|
91
148
|
- [Getting started](./docs/getting-started.md)
|
|
149
|
+
- [References & providers](./docs/references.md)
|
|
92
150
|
- [Theming](./docs/theming.md)
|
|
93
151
|
- [Structured renderers](./docs/structured-renderers.md)
|
|
94
152
|
- [Human-in-the-loop](./docs/hitl.md)
|
|
@@ -1144,6 +1144,167 @@ function InlineCardRenderer({
|
|
|
1144
1144
|
);
|
|
1145
1145
|
}
|
|
1146
1146
|
|
|
1147
|
+
// src/references/types.ts
|
|
1148
|
+
var REFERENCE_METADATA_KEYS = {
|
|
1149
|
+
/** Metadata key carrying the reference id. */
|
|
1150
|
+
id: "kaboo_id",
|
|
1151
|
+
/** Metadata key carrying the reference kind. */
|
|
1152
|
+
kind: "kaboo_kind",
|
|
1153
|
+
/** Metadata key carrying the reference display name. */
|
|
1154
|
+
name: "kaboo_name"
|
|
1155
|
+
};
|
|
1156
|
+
var REFERENCES_STATE_KEY = "kaboo_references";
|
|
1157
|
+
|
|
1158
|
+
// src/references/serialize.ts
|
|
1159
|
+
function mintReferenceId(kind) {
|
|
1160
|
+
const rand = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
1161
|
+
return `${kind}_${rand}`;
|
|
1162
|
+
}
|
|
1163
|
+
function referenceMarker(ref) {
|
|
1164
|
+
return `[${ref.kind}:${ref.id}]`;
|
|
1165
|
+
}
|
|
1166
|
+
function modalityFor(mimeType) {
|
|
1167
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
1168
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
1169
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
1170
|
+
return "document";
|
|
1171
|
+
}
|
|
1172
|
+
function attachmentToInputContent(ref) {
|
|
1173
|
+
const source = "url" in ref.source ? { type: "url", value: ref.source.url, mimeType: ref.mimeType } : { type: "data", value: ref.source.data, mimeType: ref.mimeType };
|
|
1174
|
+
return {
|
|
1175
|
+
type: modalityFor(ref.mimeType),
|
|
1176
|
+
source,
|
|
1177
|
+
metadata: {
|
|
1178
|
+
[REFERENCE_METADATA_KEYS.id]: ref.id,
|
|
1179
|
+
[REFERENCE_METADATA_KEYS.kind]: ref.kind,
|
|
1180
|
+
[REFERENCE_METADATA_KEYS.name]: ref.name,
|
|
1181
|
+
filename: ref.name
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
function objectToStateEntry(ref) {
|
|
1186
|
+
return { kind: ref.kind, id: ref.id, name: ref.name, meta: ref.meta };
|
|
1187
|
+
}
|
|
1188
|
+
function serializeReferences(refs) {
|
|
1189
|
+
const attachmentParts = [];
|
|
1190
|
+
const objectReferences = [];
|
|
1191
|
+
for (const ref of refs) {
|
|
1192
|
+
if (ref.transport === "attachment") {
|
|
1193
|
+
attachmentParts.push(attachmentToInputContent(ref));
|
|
1194
|
+
} else {
|
|
1195
|
+
objectReferences.push(objectToStateEntry(ref));
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return { attachmentParts, objectReferences };
|
|
1199
|
+
}
|
|
1200
|
+
function withReferenceState(state, objectReferences) {
|
|
1201
|
+
const next = { ...state ?? {} };
|
|
1202
|
+
if (objectReferences.length > 0) {
|
|
1203
|
+
next[REFERENCES_STATE_KEY] = objectReferences;
|
|
1204
|
+
} else {
|
|
1205
|
+
delete next[REFERENCES_STATE_KEY];
|
|
1206
|
+
}
|
|
1207
|
+
return next;
|
|
1208
|
+
}
|
|
1209
|
+
function buildUserContent(text, attachmentParts) {
|
|
1210
|
+
const parts = [];
|
|
1211
|
+
if (text.length > 0) parts.push({ type: "text", text });
|
|
1212
|
+
parts.push(...attachmentParts);
|
|
1213
|
+
return parts;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// src/references/ReferencesProvider.tsx
|
|
1217
|
+
import {
|
|
1218
|
+
createContext as createContext4,
|
|
1219
|
+
useCallback as useCallback3,
|
|
1220
|
+
useContext as useContext5,
|
|
1221
|
+
useEffect as useEffect4,
|
|
1222
|
+
useMemo,
|
|
1223
|
+
useState as useState7
|
|
1224
|
+
} from "react";
|
|
1225
|
+
import { useAgent as useAgent2 } from "@copilotkit/react-core/v2";
|
|
1226
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1227
|
+
var ReferencesContext = createContext4({
|
|
1228
|
+
providers: [],
|
|
1229
|
+
pending: [],
|
|
1230
|
+
addReference: () => {
|
|
1231
|
+
},
|
|
1232
|
+
removeReference: () => {
|
|
1233
|
+
},
|
|
1234
|
+
clearReferences: () => {
|
|
1235
|
+
},
|
|
1236
|
+
messageReferences: {},
|
|
1237
|
+
recordMessageReferences: () => {
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
function ReferencesProvider({
|
|
1241
|
+
providers = [],
|
|
1242
|
+
syncObjectStateTo = false,
|
|
1243
|
+
children
|
|
1244
|
+
}) {
|
|
1245
|
+
const [pending, setPending] = useState7([]);
|
|
1246
|
+
const [messageReferences, setMessageReferences] = useState7({});
|
|
1247
|
+
const addReference = useCallback3((ref) => {
|
|
1248
|
+
setPending(
|
|
1249
|
+
(prev) => prev.some((r) => r.id === ref.id) ? prev : [...prev, ref]
|
|
1250
|
+
);
|
|
1251
|
+
}, []);
|
|
1252
|
+
const removeReference = useCallback3((id) => {
|
|
1253
|
+
setPending((prev) => prev.filter((r) => r.id !== id));
|
|
1254
|
+
}, []);
|
|
1255
|
+
const clearReferences = useCallback3(() => setPending([]), []);
|
|
1256
|
+
const recordMessageReferences = useCallback3(
|
|
1257
|
+
(messageId, refs) => {
|
|
1258
|
+
if (refs.length === 0) return;
|
|
1259
|
+
setMessageReferences((prev) => ({ ...prev, [messageId]: refs }));
|
|
1260
|
+
},
|
|
1261
|
+
[]
|
|
1262
|
+
);
|
|
1263
|
+
const value = useMemo(
|
|
1264
|
+
() => ({
|
|
1265
|
+
providers,
|
|
1266
|
+
pending,
|
|
1267
|
+
addReference,
|
|
1268
|
+
removeReference,
|
|
1269
|
+
clearReferences,
|
|
1270
|
+
messageReferences,
|
|
1271
|
+
recordMessageReferences
|
|
1272
|
+
}),
|
|
1273
|
+
[
|
|
1274
|
+
providers,
|
|
1275
|
+
pending,
|
|
1276
|
+
addReference,
|
|
1277
|
+
removeReference,
|
|
1278
|
+
clearReferences,
|
|
1279
|
+
messageReferences,
|
|
1280
|
+
recordMessageReferences
|
|
1281
|
+
]
|
|
1282
|
+
);
|
|
1283
|
+
return /* @__PURE__ */ jsxs9(ReferencesContext.Provider, { value, children: [
|
|
1284
|
+
syncObjectStateTo !== false && /* @__PURE__ */ jsx15(ReferenceStateSync, { agentId: syncObjectStateTo, pending }),
|
|
1285
|
+
children
|
|
1286
|
+
] });
|
|
1287
|
+
}
|
|
1288
|
+
function ReferenceStateSync({
|
|
1289
|
+
agentId,
|
|
1290
|
+
pending
|
|
1291
|
+
}) {
|
|
1292
|
+
const { agent } = useAgent2(agentId ? { agentId } : void 0);
|
|
1293
|
+
const objectRefs = useMemo(
|
|
1294
|
+
() => pending.filter((r) => r.transport === "object").map(objectToStateEntry),
|
|
1295
|
+
[pending]
|
|
1296
|
+
);
|
|
1297
|
+
const key = JSON.stringify(objectRefs);
|
|
1298
|
+
useEffect4(() => {
|
|
1299
|
+
if (!agent || typeof agent.setState !== "function") return;
|
|
1300
|
+
agent.setState(withReferenceState(agent.state, objectRefs));
|
|
1301
|
+
}, [agent, key]);
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
function useReferences() {
|
|
1305
|
+
return useContext5(ReferencesContext);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1147
1308
|
export {
|
|
1148
1309
|
StructuredRenderersContext,
|
|
1149
1310
|
KabooActivityProvider,
|
|
@@ -1172,6 +1333,18 @@ export {
|
|
|
1172
1333
|
useDrill,
|
|
1173
1334
|
AgentCard,
|
|
1174
1335
|
KabooToolRender,
|
|
1175
|
-
KabooInlineCards
|
|
1336
|
+
KabooInlineCards,
|
|
1337
|
+
REFERENCE_METADATA_KEYS,
|
|
1338
|
+
REFERENCES_STATE_KEY,
|
|
1339
|
+
mintReferenceId,
|
|
1340
|
+
referenceMarker,
|
|
1341
|
+
attachmentToInputContent,
|
|
1342
|
+
objectToStateEntry,
|
|
1343
|
+
serializeReferences,
|
|
1344
|
+
withReferenceState,
|
|
1345
|
+
buildUserContent,
|
|
1346
|
+
ReferencesProvider,
|
|
1347
|
+
ReferenceStateSync,
|
|
1348
|
+
useReferences
|
|
1176
1349
|
};
|
|
1177
|
-
//# sourceMappingURL=chunk-
|
|
1350
|
+
//# sourceMappingURL=chunk-4TDUEMK5.js.map
|