@kognitivedev/ui 0.2.11
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/.turbo/turbo-build.log +2 -0
- package/CHANGELOG.md +19 -0
- package/README.md +264 -0
- package/dist/__tests__/context-provider.test.d.ts +1 -0
- package/dist/__tests__/context-provider.test.js +38 -0
- package/dist/__tests__/event-emitter.test.d.ts +1 -0
- package/dist/__tests__/event-emitter.test.js +62 -0
- package/dist/__tests__/keyboard-shortcuts.test.d.ts +1 -0
- package/dist/__tests__/keyboard-shortcuts.test.js +36 -0
- package/dist/__tests__/kognitive-runtime.test.d.ts +1 -0
- package/dist/__tests__/kognitive-runtime.test.js +58 -0
- package/dist/__tests__/kognitive-transport.test.d.ts +1 -0
- package/dist/__tests__/kognitive-transport.test.js +96 -0
- package/dist/__tests__/make-tool-ui.test.d.ts +1 -0
- package/dist/__tests__/make-tool-ui.test.js +50 -0
- package/dist/__tests__/message-helpers.test.d.ts +1 -0
- package/dist/__tests__/message-helpers.test.js +80 -0
- package/dist/__tests__/thread-manager.test.d.ts +1 -0
- package/dist/__tests__/thread-manager.test.js +84 -0
- package/dist/__tests__/tool-ui-registry.test.d.ts +1 -0
- package/dist/__tests__/tool-ui-registry.test.js +68 -0
- package/dist/__tests__/toolkit.test.d.ts +1 -0
- package/dist/__tests__/toolkit.test.js +33 -0
- package/dist/components/attachment-preview.d.ts +8 -0
- package/dist/components/attachment-preview.js +10 -0
- package/dist/components/composer.d.ts +6 -0
- package/dist/components/composer.js +10 -0
- package/dist/components/error-banner.d.ts +6 -0
- package/dist/components/error-banner.js +8 -0
- package/dist/components/markdown-content.d.ts +13 -0
- package/dist/components/markdown-content.js +31 -0
- package/dist/components/message.d.ts +7 -0
- package/dist/components/message.js +28 -0
- package/dist/components/status-indicator.d.ts +6 -0
- package/dist/components/status-indicator.js +16 -0
- package/dist/components/suggestions.d.ts +4 -0
- package/dist/components/suggestions.js +12 -0
- package/dist/components/thread-list.d.ts +4 -0
- package/dist/components/thread-list.js +20 -0
- package/dist/components/thread.d.ts +15 -0
- package/dist/components/thread.js +19 -0
- package/dist/components/tool-approval.d.ts +7 -0
- package/dist/components/tool-approval.js +12 -0
- package/dist/components/tool-invocation.d.ts +5 -0
- package/dist/components/tool-invocation.js +33 -0
- package/dist/context/kognitive-context.d.ts +2 -0
- package/dist/context/kognitive-context.js +6 -0
- package/dist/context/types.d.ts +44 -0
- package/dist/context/types.js +2 -0
- package/dist/context/use-kognitive.d.ts +1 -0
- package/dist/context/use-kognitive.js +7 -0
- package/dist/hooks/use-auto-scroll.d.ts +2 -0
- package/dist/hooks/use-auto-scroll.js +18 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +4 -0
- package/dist/hooks/use-copy-to-clipboard.js +13 -0
- package/dist/hooks/use-keyboard-shortcuts.d.ts +8 -0
- package/dist/hooks/use-keyboard-shortcuts.js +24 -0
- package/dist/hooks/use-kognitive-chat.d.ts +38 -0
- package/dist/hooks/use-kognitive-chat.js +35 -0
- package/dist/hooks/use-kognitive-event.d.ts +12 -0
- package/dist/hooks/use-kognitive-event.js +47 -0
- package/dist/hooks/use-streaming-status.d.ts +2 -0
- package/dist/hooks/use-streaming-status.js +8 -0
- package/dist/hooks/use-thread-manager.d.ts +20 -0
- package/dist/hooks/use-thread-manager.js +83 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +92 -0
- package/dist/kognitive-ui.d.ts +48 -0
- package/dist/kognitive-ui.js +130 -0
- package/dist/primitives/action-bar/action-bar-copy.d.ts +6 -0
- package/dist/primitives/action-bar/action-bar-copy.js +16 -0
- package/dist/primitives/action-bar/action-bar-edit.d.ts +6 -0
- package/dist/primitives/action-bar/action-bar-edit.js +11 -0
- package/dist/primitives/action-bar/action-bar-feedback.d.ts +10 -0
- package/dist/primitives/action-bar/action-bar-feedback.js +30 -0
- package/dist/primitives/action-bar/action-bar-retry.d.ts +6 -0
- package/dist/primitives/action-bar/action-bar-retry.js +25 -0
- package/dist/primitives/action-bar/action-bar-root.d.ts +6 -0
- package/dist/primitives/action-bar/action-bar-root.js +7 -0
- package/dist/primitives/action-bar/action-bar-stop.d.ts +6 -0
- package/dist/primitives/action-bar/action-bar-stop.js +11 -0
- package/dist/primitives/action-bar/index.d.ts +14 -0
- package/dist/primitives/action-bar/index.js +17 -0
- package/dist/primitives/composer/composer-attachment-trigger.d.ts +7 -0
- package/dist/primitives/composer/composer-attachment-trigger.js +33 -0
- package/dist/primitives/composer/composer-attachments.d.ts +7 -0
- package/dist/primitives/composer/composer-attachments.js +16 -0
- package/dist/primitives/composer/composer-input.d.ts +6 -0
- package/dist/primitives/composer/composer-input.js +19 -0
- package/dist/primitives/composer/composer-root.d.ts +6 -0
- package/dist/primitives/composer/composer-root.js +91 -0
- package/dist/primitives/composer/composer-send.d.ts +6 -0
- package/dist/primitives/composer/composer-send.js +10 -0
- package/dist/primitives/composer/edit-composer-root.d.ts +11 -0
- package/dist/primitives/composer/edit-composer-root.js +24 -0
- package/dist/primitives/composer/index.d.ts +15 -0
- package/dist/primitives/composer/index.js +19 -0
- package/dist/primitives/composer/use-composer.d.ts +12 -0
- package/dist/primitives/composer/use-composer.js +6 -0
- package/dist/primitives/message/index.d.ts +9 -0
- package/dist/primitives/message/index.js +13 -0
- package/dist/primitives/message/message-content.d.ts +25 -0
- package/dist/primitives/message/message-content.js +70 -0
- package/dist/primitives/message/message-role.d.ts +6 -0
- package/dist/primitives/message/message-role.js +11 -0
- package/dist/primitives/message/message-root.d.ts +9 -0
- package/dist/primitives/message/message-root.js +38 -0
- package/dist/primitives/message/use-message.d.ts +10 -0
- package/dist/primitives/message/use-message.js +6 -0
- package/dist/primitives/thread/index.d.ts +17 -0
- package/dist/primitives/thread/index.js +21 -0
- package/dist/primitives/thread/thread-empty.d.ts +5 -0
- package/dist/primitives/thread/thread-empty.js +11 -0
- package/dist/primitives/thread/thread-error.d.ts +6 -0
- package/dist/primitives/thread/thread-error.js +11 -0
- package/dist/primitives/thread/thread-loading.d.ts +5 -0
- package/dist/primitives/thread/thread-loading.js +11 -0
- package/dist/primitives/thread/thread-messages.d.ts +6 -0
- package/dist/primitives/thread/thread-messages.js +9 -0
- package/dist/primitives/thread/thread-root.d.ts +6 -0
- package/dist/primitives/thread/thread-root.js +12 -0
- package/dist/primitives/thread/thread-scroll-to-bottom.d.ts +6 -0
- package/dist/primitives/thread/thread-scroll-to-bottom.js +14 -0
- package/dist/primitives/thread/thread-suggestions.d.ts +6 -0
- package/dist/primitives/thread/thread-suggestions.js +14 -0
- package/dist/primitives/thread/use-thread.d.ts +9 -0
- package/dist/primitives/thread/use-thread.js +6 -0
- package/dist/primitives/thread-list/index.d.ts +11 -0
- package/dist/primitives/thread-list/index.js +15 -0
- package/dist/primitives/thread-list/thread-list-item.d.ts +9 -0
- package/dist/primitives/thread-list/thread-list-item.js +13 -0
- package/dist/primitives/thread-list/thread-list-items.d.ts +6 -0
- package/dist/primitives/thread-list/thread-list-items.js +9 -0
- package/dist/primitives/thread-list/thread-list-new.d.ts +6 -0
- package/dist/primitives/thread-list/thread-list-new.js +13 -0
- package/dist/primitives/thread-list/thread-list-root.d.ts +6 -0
- package/dist/primitives/thread-list/thread-list-root.js +16 -0
- package/dist/primitives/thread-list/use-thread-list.d.ts +9 -0
- package/dist/primitives/thread-list/use-thread-list.js +6 -0
- package/dist/primitives/tool-ui/index.d.ts +7 -0
- package/dist/primitives/tool-ui/index.js +11 -0
- package/dist/primitives/tool-ui/tool-ui-fallback.d.ts +5 -0
- package/dist/primitives/tool-ui/tool-ui-fallback.js +20 -0
- package/dist/primitives/tool-ui/tool-ui-root.d.ts +5 -0
- package/dist/primitives/tool-ui/tool-ui-root.js +20 -0
- package/dist/primitives/tool-ui/use-tool-ui.d.ts +2 -0
- package/dist/primitives/tool-ui/use-tool-ui.js +8 -0
- package/dist/runtime/kognitive-runtime.d.ts +30 -0
- package/dist/runtime/kognitive-runtime.js +32 -0
- package/dist/runtime/kognitive-transport.d.ts +26 -0
- package/dist/runtime/kognitive-transport.js +42 -0
- package/dist/runtime/thread-manager.d.ts +17 -0
- package/dist/runtime/thread-manager.js +62 -0
- package/dist/runtime/types.d.ts +58 -0
- package/dist/runtime/types.js +2 -0
- package/dist/tool-ui/make-tool-ui.d.ts +59 -0
- package/dist/tool-ui/make-tool-ui.js +10 -0
- package/dist/tool-ui/registry.d.ts +9 -0
- package/dist/tool-ui/registry.js +26 -0
- package/dist/tool-ui/tool-ui-context.d.ts +2 -0
- package/dist/tool-ui/tool-ui-context.js +6 -0
- package/dist/tool-ui/toolkit.d.ts +31 -0
- package/dist/tool-ui/toolkit.js +33 -0
- package/dist/tool-ui/types.d.ts +19 -0
- package/dist/tool-ui/types.js +2 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +8 -0
- package/dist/utils/create-context.d.ts +1 -0
- package/dist/utils/create-context.js +16 -0
- package/dist/utils/message-helpers.d.ts +6 -0
- package/dist/utils/message-helpers.js +46 -0
- package/package.json +56 -0
- package/src/__tests__/context-provider.test.ts +43 -0
- package/src/__tests__/event-emitter.test.ts +69 -0
- package/src/__tests__/keyboard-shortcuts.test.ts +55 -0
- package/src/__tests__/kognitive-runtime.test.ts +62 -0
- package/src/__tests__/kognitive-transport.test.ts +113 -0
- package/src/__tests__/make-tool-ui.test.ts +60 -0
- package/src/__tests__/message-helpers.test.ts +101 -0
- package/src/__tests__/thread-manager.test.ts +118 -0
- package/src/__tests__/tool-ui-registry.test.ts +80 -0
- package/src/__tests__/toolkit.test.ts +37 -0
- package/src/components/attachment-preview.tsx +46 -0
- package/src/components/composer.tsx +59 -0
- package/src/components/error-banner.tsx +33 -0
- package/src/components/markdown-content.tsx +64 -0
- package/src/components/message.tsx +145 -0
- package/src/components/status-indicator.tsx +26 -0
- package/src/components/suggestions.tsx +27 -0
- package/src/components/thread-list.tsx +69 -0
- package/src/components/thread.tsx +89 -0
- package/src/components/tool-approval.tsx +54 -0
- package/src/components/tool-invocation.tsx +94 -0
- package/src/context/kognitive-context.tsx +8 -0
- package/src/context/types.ts +43 -0
- package/src/context/use-kognitive.ts +5 -0
- package/src/hooks/use-auto-scroll.ts +19 -0
- package/src/hooks/use-copy-to-clipboard.ts +16 -0
- package/src/hooks/use-keyboard-shortcuts.ts +34 -0
- package/src/hooks/use-kognitive-chat.ts +73 -0
- package/src/hooks/use-kognitive-event.ts +56 -0
- package/src/hooks/use-streaming-status.ts +7 -0
- package/src/hooks/use-thread-manager.ts +114 -0
- package/src/index.ts +56 -0
- package/src/kognitive-ui.tsx +216 -0
- package/src/primitives/action-bar/action-bar-copy.tsx +30 -0
- package/src/primitives/action-bar/action-bar-edit.tsx +24 -0
- package/src/primitives/action-bar/action-bar-feedback.tsx +59 -0
- package/src/primitives/action-bar/action-bar-retry.tsx +38 -0
- package/src/primitives/action-bar/action-bar-root.tsx +14 -0
- package/src/primitives/action-bar/action-bar-stop.tsx +24 -0
- package/src/primitives/action-bar/index.ts +15 -0
- package/src/primitives/composer/composer-attachment-trigger.tsx +70 -0
- package/src/primitives/composer/composer-attachments.tsx +36 -0
- package/src/primitives/composer/composer-input.tsx +46 -0
- package/src/primitives/composer/composer-root.tsx +130 -0
- package/src/primitives/composer/composer-send.tsx +23 -0
- package/src/primitives/composer/edit-composer-root.tsx +52 -0
- package/src/primitives/composer/index.ts +17 -0
- package/src/primitives/composer/use-composer.ts +19 -0
- package/src/primitives/message/index.ts +11 -0
- package/src/primitives/message/message-content.tsx +117 -0
- package/src/primitives/message/message-role.tsx +13 -0
- package/src/primitives/message/message-root.tsx +64 -0
- package/src/primitives/message/use-message.ts +17 -0
- package/src/primitives/thread/index.ts +19 -0
- package/src/primitives/thread/thread-empty.tsx +12 -0
- package/src/primitives/thread/thread-error.tsx +18 -0
- package/src/primitives/thread/thread-loading.tsx +12 -0
- package/src/primitives/thread/thread-messages.tsx +12 -0
- package/src/primitives/thread/thread-root.tsx +28 -0
- package/src/primitives/thread/thread-scroll-to-bottom.tsx +26 -0
- package/src/primitives/thread/thread-suggestions.tsx +31 -0
- package/src/primitives/thread/use-thread.ts +16 -0
- package/src/primitives/thread-list/index.ts +13 -0
- package/src/primitives/thread-list/thread-list-item.tsx +37 -0
- package/src/primitives/thread-list/thread-list-items.tsx +19 -0
- package/src/primitives/thread-list/thread-list-new.tsx +26 -0
- package/src/primitives/thread-list/thread-list-root.tsx +29 -0
- package/src/primitives/thread-list/use-thread-list.ts +16 -0
- package/src/primitives/tool-ui/index.ts +9 -0
- package/src/primitives/tool-ui/tool-ui-fallback.tsx +63 -0
- package/src/primitives/tool-ui/tool-ui-root.tsx +26 -0
- package/src/primitives/tool-ui/use-tool-ui.ts +7 -0
- package/src/runtime/kognitive-runtime.ts +56 -0
- package/src/runtime/kognitive-transport.ts +56 -0
- package/src/runtime/thread-manager.ts +92 -0
- package/src/runtime/types.ts +63 -0
- package/src/tool-ui/make-tool-ui.ts +71 -0
- package/src/tool-ui/registry.ts +27 -0
- package/src/tool-ui/tool-ui-context.tsx +8 -0
- package/src/tool-ui/toolkit.ts +40 -0
- package/src/tool-ui/types.ts +29 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/create-context.ts +18 -0
- package/src/utils/message-helpers.ts +42 -0
- package/tsconfig.json +15 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const message_helpers_1 = require("../utils/message-helpers");
|
|
5
|
+
function makeMessage(parts, role = "assistant") {
|
|
6
|
+
return {
|
|
7
|
+
id: "msg-1",
|
|
8
|
+
role,
|
|
9
|
+
parts,
|
|
10
|
+
createdAt: new Date(),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
(0, vitest_1.describe)("extractTextContent", () => {
|
|
14
|
+
(0, vitest_1.it)("returns string content as-is", () => {
|
|
15
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)("hello")).toBe("hello");
|
|
16
|
+
});
|
|
17
|
+
(0, vitest_1.it)("extracts text from an array of parts", () => {
|
|
18
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)([
|
|
19
|
+
{ text: "hello" },
|
|
20
|
+
{ text: "world" },
|
|
21
|
+
])).toBe("hello\nworld");
|
|
22
|
+
});
|
|
23
|
+
(0, vitest_1.it)("returns empty string for non-string non-array input", () => {
|
|
24
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)(42)).toBe("");
|
|
25
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)(null)).toBe("");
|
|
26
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)(undefined)).toBe("");
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.it)("skips non-text parts", () => {
|
|
29
|
+
(0, vitest_1.expect)((0, message_helpers_1.extractTextContent)([
|
|
30
|
+
{ text: "keep" },
|
|
31
|
+
{ type: "image" },
|
|
32
|
+
{ text: "this" },
|
|
33
|
+
])).toBe("keep\nthis");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.describe)("getMessageText", () => {
|
|
37
|
+
(0, vitest_1.it)("extracts text from message parts", () => {
|
|
38
|
+
const msg = makeMessage([
|
|
39
|
+
{ type: "text", text: "Hello " },
|
|
40
|
+
{ type: "text", text: "world" },
|
|
41
|
+
]);
|
|
42
|
+
(0, vitest_1.expect)((0, message_helpers_1.getMessageText)(msg)).toBe("Hello \nworld");
|
|
43
|
+
});
|
|
44
|
+
(0, vitest_1.it)("skips non-text parts", () => {
|
|
45
|
+
const msg = makeMessage([
|
|
46
|
+
{ type: "text", text: "before" },
|
|
47
|
+
{ type: "text", text: "after" },
|
|
48
|
+
]);
|
|
49
|
+
(0, vitest_1.expect)((0, message_helpers_1.getMessageText)(msg)).toBe("before\nafter");
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.it)("returns empty string for message with no text parts", () => {
|
|
52
|
+
const msg = makeMessage([]);
|
|
53
|
+
(0, vitest_1.expect)((0, message_helpers_1.getMessageText)(msg)).toBe("");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
(0, vitest_1.describe)("getMessagePreview", () => {
|
|
57
|
+
(0, vitest_1.it)("returns full text when under maxLength", () => {
|
|
58
|
+
const msg = makeMessage([{ type: "text", text: "Short" }]);
|
|
59
|
+
(0, vitest_1.expect)((0, message_helpers_1.getMessagePreview)(msg)).toBe("Short");
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)("truncates and adds ellipsis when over maxLength", () => {
|
|
62
|
+
const longText = "A".repeat(100);
|
|
63
|
+
const msg = makeMessage([{ type: "text", text: longText }]);
|
|
64
|
+
const preview = (0, message_helpers_1.getMessagePreview)(msg, 50);
|
|
65
|
+
(0, vitest_1.expect)(preview.length).toBeLessThanOrEqual(53); // 50 + "..."
|
|
66
|
+
(0, vitest_1.expect)(preview.endsWith("...")).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
(0, vitest_1.describe)("getToolInvocations", () => {
|
|
70
|
+
(0, vitest_1.it)("returns empty array when no tool invocations", () => {
|
|
71
|
+
const msg = makeMessage([{ type: "text", text: "hello" }]);
|
|
72
|
+
(0, vitest_1.expect)((0, message_helpers_1.getToolInvocations)(msg)).toHaveLength(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
(0, vitest_1.describe)("hasToolInvocations", () => {
|
|
76
|
+
(0, vitest_1.it)("returns false when message has no tool invocations", () => {
|
|
77
|
+
const msg = makeMessage([{ type: "text", text: "hello" }]);
|
|
78
|
+
(0, vitest_1.expect)((0, message_helpers_1.hasToolInvocations)(msg)).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const thread_manager_1 = require("../runtime/thread-manager");
|
|
5
|
+
(0, vitest_1.describe)("ThreadManager", () => {
|
|
6
|
+
const mockFetch = vitest_1.vi.fn();
|
|
7
|
+
(0, vitest_1.beforeEach)(() => {
|
|
8
|
+
vitest_1.vi.stubGlobal("fetch", mockFetch);
|
|
9
|
+
mockFetch.mockReset();
|
|
10
|
+
});
|
|
11
|
+
const manager = new thread_manager_1.ThreadManager({
|
|
12
|
+
baseUrl: "http://localhost:3001/api/agents/my-agent/threads",
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.it)("list() fetches threads", async () => {
|
|
15
|
+
mockFetch.mockResolvedValueOnce({
|
|
16
|
+
ok: true,
|
|
17
|
+
json: async () => ({ threads: [{ sessionId: "s1", title: "Hello" }] }),
|
|
18
|
+
});
|
|
19
|
+
const threads = await manager.list();
|
|
20
|
+
(0, vitest_1.expect)(threads).toHaveLength(1);
|
|
21
|
+
(0, vitest_1.expect)(threads[0].sessionId).toBe("s1");
|
|
22
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith("http://localhost:3001/api/agents/my-agent/threads", vitest_1.expect.objectContaining({ headers: vitest_1.expect.any(Object) }));
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)("get() fetches a single thread", async () => {
|
|
25
|
+
mockFetch.mockResolvedValueOnce({
|
|
26
|
+
ok: true,
|
|
27
|
+
json: async () => ({
|
|
28
|
+
session: { id: "1", sessionId: "s1", messageCount: 5 },
|
|
29
|
+
events: [],
|
|
30
|
+
traces: [],
|
|
31
|
+
runs: [],
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
const detail = await manager.get("s1");
|
|
35
|
+
(0, vitest_1.expect)(detail.session.sessionId).toBe("s1");
|
|
36
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith("http://localhost:3001/api/agents/my-agent/threads/s1", vitest_1.expect.objectContaining({ headers: vitest_1.expect.any(Object) }));
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)("create() POSTs to create a thread", async () => {
|
|
39
|
+
mockFetch.mockResolvedValueOnce({
|
|
40
|
+
ok: true,
|
|
41
|
+
json: async () => ({ thread: { sessionId: "new-s", title: "" } }),
|
|
42
|
+
});
|
|
43
|
+
const thread = await manager.create();
|
|
44
|
+
(0, vitest_1.expect)(thread.sessionId).toBe("new-s");
|
|
45
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith("http://localhost:3001/api/agents/my-agent/threads", vitest_1.expect.objectContaining({ method: "POST" }));
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.it)("fork() POSTs to fork a thread", async () => {
|
|
48
|
+
mockFetch.mockResolvedValueOnce({
|
|
49
|
+
ok: true,
|
|
50
|
+
json: async () => ({ thread: { sessionId: "forked-s", title: "" } }),
|
|
51
|
+
});
|
|
52
|
+
const thread = await manager.fork("s1");
|
|
53
|
+
(0, vitest_1.expect)(thread.sessionId).toBe("forked-s");
|
|
54
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith("http://localhost:3001/api/agents/my-agent/threads/s1/fork", vitest_1.expect.objectContaining({ method: "POST" }));
|
|
55
|
+
});
|
|
56
|
+
(0, vitest_1.it)("interrupt() POSTs to interrupt a thread", async () => {
|
|
57
|
+
mockFetch.mockResolvedValueOnce({ ok: true, json: async () => ({}) });
|
|
58
|
+
await manager.interrupt("s1");
|
|
59
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith("http://localhost:3001/api/agents/my-agent/threads/s1/interrupt", vitest_1.expect.objectContaining({ method: "POST" }));
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)("throws on HTTP error", async () => {
|
|
62
|
+
mockFetch.mockResolvedValueOnce({
|
|
63
|
+
ok: false,
|
|
64
|
+
json: async () => ({ error: "Not found" }),
|
|
65
|
+
});
|
|
66
|
+
await (0, vitest_1.expect)(manager.get("bad-id")).rejects.toThrow("Not found");
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.it)("includes custom headers", async () => {
|
|
69
|
+
const authManager = new thread_manager_1.ThreadManager({
|
|
70
|
+
baseUrl: "http://localhost:3001/api/threads",
|
|
71
|
+
headers: { Authorization: "Bearer secret" },
|
|
72
|
+
});
|
|
73
|
+
mockFetch.mockResolvedValueOnce({
|
|
74
|
+
ok: true,
|
|
75
|
+
json: async () => ({ threads: [] }),
|
|
76
|
+
});
|
|
77
|
+
await authManager.list();
|
|
78
|
+
(0, vitest_1.expect)(mockFetch).toHaveBeenCalledWith(vitest_1.expect.any(String), vitest_1.expect.objectContaining({
|
|
79
|
+
headers: vitest_1.expect.objectContaining({
|
|
80
|
+
Authorization: "Bearer secret",
|
|
81
|
+
}),
|
|
82
|
+
}));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const registry_1 = require("../tool-ui/registry");
|
|
5
|
+
const make_tool_ui_1 = require("../tool-ui/make-tool-ui");
|
|
6
|
+
(0, vitest_1.describe)("ToolUIRegistry", () => {
|
|
7
|
+
(0, vitest_1.it)("registers and retrieves a tool UI component", () => {
|
|
8
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
9
|
+
const render = () => null;
|
|
10
|
+
registry.register({ toolName: "test_tool", component: render });
|
|
11
|
+
(0, vitest_1.expect)(registry.has("test_tool")).toBe(true);
|
|
12
|
+
(0, vitest_1.expect)(registry.get("test_tool")).toBe(render);
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.it)("returns undefined for unregistered tools", () => {
|
|
15
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
16
|
+
(0, vitest_1.expect)(registry.has("nonexistent")).toBe(false);
|
|
17
|
+
(0, vitest_1.expect)(registry.get("nonexistent")).toBeUndefined();
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)("registers multiple tools via registerAll", () => {
|
|
20
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
21
|
+
const renderA = () => null;
|
|
22
|
+
const renderB = () => null;
|
|
23
|
+
registry.registerAll([
|
|
24
|
+
{ toolName: "tool_a", component: renderA },
|
|
25
|
+
{ toolName: "tool_b", component: renderB },
|
|
26
|
+
]);
|
|
27
|
+
(0, vitest_1.expect)(registry.has("tool_a")).toBe(true);
|
|
28
|
+
(0, vitest_1.expect)(registry.has("tool_b")).toBe(true);
|
|
29
|
+
(0, vitest_1.expect)(registry.get("tool_a")).toBe(renderA);
|
|
30
|
+
(0, vitest_1.expect)(registry.get("tool_b")).toBe(renderB);
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)("lists registered tool names", () => {
|
|
33
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
34
|
+
registry.register({ toolName: "alpha", component: () => null });
|
|
35
|
+
registry.register({ toolName: "beta", component: () => null });
|
|
36
|
+
const names = registry.names();
|
|
37
|
+
(0, vitest_1.expect)(names).toContain("alpha");
|
|
38
|
+
(0, vitest_1.expect)(names).toContain("beta");
|
|
39
|
+
(0, vitest_1.expect)(names).toHaveLength(2);
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)("overwrites a registration for the same tool name", () => {
|
|
42
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
43
|
+
const first = () => null;
|
|
44
|
+
const second = () => null;
|
|
45
|
+
registry.register({ toolName: "tool", component: first });
|
|
46
|
+
(0, vitest_1.expect)(registry.get("tool")).toBe(first);
|
|
47
|
+
registry.register({ toolName: "tool", component: second });
|
|
48
|
+
(0, vitest_1.expect)(registry.get("tool")).toBe(second);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.describe)("makeToolUI", () => {
|
|
52
|
+
(0, vitest_1.it)("creates a registration from a tool object", () => {
|
|
53
|
+
const registration = (0, make_tool_ui_1.makeToolUI)({
|
|
54
|
+
tool: { id: "get_weather" },
|
|
55
|
+
render: () => null,
|
|
56
|
+
});
|
|
57
|
+
(0, vitest_1.expect)(registration.toolName).toBe("get_weather");
|
|
58
|
+
(0, vitest_1.expect)(typeof registration.component).toBe("function");
|
|
59
|
+
});
|
|
60
|
+
(0, vitest_1.it)("creates a registration from a tool name string", () => {
|
|
61
|
+
const registration = (0, make_tool_ui_1.makeToolUI)({
|
|
62
|
+
toolName: "search_db",
|
|
63
|
+
render: () => null,
|
|
64
|
+
});
|
|
65
|
+
(0, vitest_1.expect)(registration.toolName).toBe("search_db");
|
|
66
|
+
(0, vitest_1.expect)(typeof registration.component).toBe("function");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const toolkit_1 = require("../tool-ui/toolkit");
|
|
5
|
+
const registry_1 = require("../tool-ui/registry");
|
|
6
|
+
(0, vitest_1.describe)("toolkit", () => {
|
|
7
|
+
(0, vitest_1.it)("creates registrations from a map of tool names to render functions", () => {
|
|
8
|
+
const registrations = (0, toolkit_1.toolkit)({
|
|
9
|
+
weather: { render: () => null },
|
|
10
|
+
search: { render: () => null },
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.expect)(registrations).toHaveLength(2);
|
|
13
|
+
(0, vitest_1.expect)(registrations[0].toolName).toBe("weather");
|
|
14
|
+
(0, vitest_1.expect)(registrations[1].toolName).toBe("search");
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.it)("creates an empty array from an empty map", () => {
|
|
17
|
+
const registrations = (0, toolkit_1.toolkit)({});
|
|
18
|
+
(0, vitest_1.expect)(registrations).toHaveLength(0);
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("integrates with ToolUIRegistry.registerAll", () => {
|
|
21
|
+
const registrations = (0, toolkit_1.toolkit)({
|
|
22
|
+
tool_a: { render: () => null },
|
|
23
|
+
tool_b: { render: () => null },
|
|
24
|
+
tool_c: { render: () => null },
|
|
25
|
+
});
|
|
26
|
+
const registry = new registry_1.ToolUIRegistry();
|
|
27
|
+
registry.registerAll(registrations);
|
|
28
|
+
(0, vitest_1.expect)(registry.has("tool_a")).toBe(true);
|
|
29
|
+
(0, vitest_1.expect)(registry.has("tool_b")).toBe(true);
|
|
30
|
+
(0, vitest_1.expect)(registry.has("tool_c")).toBe(true);
|
|
31
|
+
(0, vitest_1.expect)(registry.names()).toHaveLength(3);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AttachmentPreviewProps {
|
|
2
|
+
url: string;
|
|
3
|
+
mediaType: string;
|
|
4
|
+
filename?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
onRemove?: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function AttachmentPreview({ url, mediaType, filename, className, onRemove }: AttachmentPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AttachmentPreview = AttachmentPreview;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
function AttachmentPreview({ url, mediaType, filename, className, onRemove }) {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
const isImage = mediaType.startsWith("image/");
|
|
9
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("relative inline-flex items-center gap-2 rounded-lg border border-zinc-200 p-2 dark:border-zinc-700", className), "data-mime-type": mediaType, children: [isImage ? ((0, jsx_runtime_1.jsx)("img", { src: url, alt: filename !== null && filename !== void 0 ? filename : "Attachment", className: "h-16 w-16 rounded object-cover" })) : ((0, jsx_runtime_1.jsx)("div", { className: "flex h-16 w-16 items-center justify-center rounded bg-zinc-100 text-xs dark:bg-zinc-800", children: (_b = filename !== null && filename !== void 0 ? filename : (_a = mediaType.split("/")[1]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : "FILE" })), onRemove && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onRemove, className: "absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-zinc-500 text-xs text-white hover:bg-zinc-600", "aria-label": "Remove attachment", children: "x" }))] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Composer = Composer;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const composer_1 = require("../primitives/composer");
|
|
7
|
+
const attachment_preview_1 = require("./attachment-preview");
|
|
8
|
+
function Composer({ className, placeholder = "Send a message...", allowAttachments = false, }) {
|
|
9
|
+
return ((0, jsx_runtime_1.jsxs)(composer_1.ComposerPrimitive.Root, { className: (0, cn_1.cn)("border-t border-zinc-200 p-4 dark:border-zinc-700", className), children: [(0, jsx_runtime_1.jsx)(composer_1.ComposerPrimitive.Attachments, { className: "mb-2 flex flex-wrap gap-2", children: (file, index, remove) => ((0, jsx_runtime_1.jsx)(attachment_preview_1.AttachmentPreview, { url: file.url, mediaType: file.mediaType, filename: file.filename, onRemove: remove }, index)) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-end gap-2", children: [allowAttachments && ((0, jsx_runtime_1.jsx)(composer_1.ComposerPrimitive.AttachmentTrigger, { className: "flex h-10 w-10 items-center justify-center rounded-lg text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300", accept: "image/*,.pdf,.txt,.md,.json,.csv", children: "+" })), (0, jsx_runtime_1.jsx)(composer_1.ComposerPrimitive.Input, { placeholder: placeholder, className: "flex-1 resize-none rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm outline-none placeholder:text-zinc-400 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:border-zinc-700 dark:bg-zinc-900 dark:placeholder:text-zinc-500 dark:focus:border-blue-400", rows: 1 }), (0, jsx_runtime_1.jsx)(composer_1.ComposerPrimitive.Send, { className: "flex h-10 items-center rounded-lg bg-blue-600 px-4 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-blue-500 dark:hover:bg-blue-600", children: "Send" })] })] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorBanner = ErrorBanner;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
function ErrorBanner({ message, className, onDismiss }) {
|
|
7
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex items-center gap-2 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 dark:border-red-800 dark:bg-red-950/30 dark:text-red-400", className), role: "alert", children: [(0, jsx_runtime_1.jsx)("span", { className: "shrink-0", children: "\u26A0" }), (0, jsx_runtime_1.jsx)("span", { className: "flex-1", children: message }), onDismiss && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onDismiss, className: "shrink-0 text-red-500 hover:text-red-700 dark:hover:text-red-300", "aria-label": "Dismiss error", children: "x" }))] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface MarkdownContentProps {
|
|
2
|
+
text: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Simple markdown-like text renderer.
|
|
7
|
+
*
|
|
8
|
+
* For full markdown support, override the Text component in MessagePrimitive.Content
|
|
9
|
+
* with your preferred markdown library (e.g., react-markdown).
|
|
10
|
+
*
|
|
11
|
+
* This component provides basic paragraph splitting and code block detection.
|
|
12
|
+
*/
|
|
13
|
+
export declare function MarkdownContent({ text, className }: MarkdownContentProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MarkdownContent = MarkdownContent;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
/**
|
|
7
|
+
* Simple markdown-like text renderer.
|
|
8
|
+
*
|
|
9
|
+
* For full markdown support, override the Text component in MessagePrimitive.Content
|
|
10
|
+
* with your preferred markdown library (e.g., react-markdown).
|
|
11
|
+
*
|
|
12
|
+
* This component provides basic paragraph splitting and code block detection.
|
|
13
|
+
*/
|
|
14
|
+
function MarkdownContent({ text, className }) {
|
|
15
|
+
const paragraphs = text.split("\n\n").filter(Boolean);
|
|
16
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("space-y-2", className), children: paragraphs.map((paragraph, i) => {
|
|
17
|
+
// Code block
|
|
18
|
+
if (paragraph.startsWith("```")) {
|
|
19
|
+
const lines = paragraph.split("\n");
|
|
20
|
+
const lang = lines[0].replace("```", "").trim();
|
|
21
|
+
const code = lines.slice(1, lines[lines.length - 1] === "```" ? -1 : undefined).join("\n");
|
|
22
|
+
return ((0, jsx_runtime_1.jsx)("pre", { className: "overflow-x-auto rounded-lg bg-zinc-900 p-3 text-sm text-zinc-100", "data-language": lang || undefined, children: (0, jsx_runtime_1.jsx)("code", { children: code }) }, i));
|
|
23
|
+
}
|
|
24
|
+
// Inline code
|
|
25
|
+
const parts = paragraph.split(/(`[^`]+`)/g);
|
|
26
|
+
if (parts.length > 1) {
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)("p", { children: parts.map((part, j) => part.startsWith("`") && part.endsWith("`") ? ((0, jsx_runtime_1.jsx)("code", { className: "rounded bg-zinc-100 px-1 py-0.5 text-sm dark:bg-zinc-800", children: part.slice(1, -1) }, j)) : ((0, jsx_runtime_1.jsx)("span", { children: part }, j))) }, i));
|
|
28
|
+
}
|
|
29
|
+
return (0, jsx_runtime_1.jsx)("p", { children: paragraph }, i);
|
|
30
|
+
}) }));
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Message = Message;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const message_1 = require("../primitives/message");
|
|
7
|
+
const action_bar_1 = require("../primitives/action-bar");
|
|
8
|
+
const composer_1 = require("../primitives/composer");
|
|
9
|
+
const markdown_content_1 = require("./markdown-content");
|
|
10
|
+
const tool_invocation_1 = require("./tool-invocation");
|
|
11
|
+
const use_message_1 = require("../primitives/message/use-message");
|
|
12
|
+
function MessageInner({ className }) {
|
|
13
|
+
const { message, isEditing } = (0, use_message_1.useMessage)();
|
|
14
|
+
const isUser = message.role === "user";
|
|
15
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex gap-3 py-4", isUser ? "flex-row-reverse" : "flex-row", className), children: [(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm", isUser
|
|
16
|
+
? "bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400"
|
|
17
|
+
: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400"), children: isUser ? "U" : "A" }), (0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex-1 space-y-1", isUser ? "text-right" : "text-left"), children: [isEditing ? ((0, jsx_runtime_1.jsx)(composer_1.ComposerPrimitive.EditRoot, { className: "space-y-2", children: ({ value, setValue, submit, cancel }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("textarea", { value: value, onChange: (e) => setValue(e.target.value), className: "w-full resize-none rounded-lg border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 dark:border-zinc-600 dark:bg-zinc-900", rows: 3 }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: submit, className: "rounded-lg bg-blue-600 px-3 py-1 text-xs font-medium text-white hover:bg-blue-700", children: "Save & Send" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: cancel, className: "rounded-lg border border-zinc-300 px-3 py-1 text-xs text-zinc-600 hover:bg-zinc-100 dark:border-zinc-600 dark:text-zinc-400 dark:hover:bg-zinc-800", children: "Cancel" })] })] })) })) : ((0, jsx_runtime_1.jsx)(message_1.MessagePrimitive.Content, { components: {
|
|
18
|
+
Text: ({ text }) => (0, jsx_runtime_1.jsx)(markdown_content_1.MarkdownContent, { text: text }),
|
|
19
|
+
ToolInvocation: (props) => (0, jsx_runtime_1.jsx)(tool_invocation_1.ToolInvocation, Object.assign({}, props)),
|
|
20
|
+
} })), !isEditing && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(message_1.MessagePrimitive.Role, { match: "user", children: (0, jsx_runtime_1.jsx)(action_bar_1.ActionBarPrimitive.Root, { className: "flex gap-1 pt-1", children: (0, jsx_runtime_1.jsx)(action_bar_1.ActionBarPrimitive.Edit, { className: "rounded px-2 py-1 text-xs text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300" }) }) }), (0, jsx_runtime_1.jsx)(message_1.MessagePrimitive.Role, { match: "assistant", children: (0, jsx_runtime_1.jsxs)(action_bar_1.ActionBarPrimitive.Root, { className: "flex gap-1 pt-1", children: [(0, jsx_runtime_1.jsx)(action_bar_1.ActionBarPrimitive.Copy, { className: "rounded px-2 py-1 text-xs text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300", children: (copied) => (copied ? "Copied!" : "Copy") }), (0, jsx_runtime_1.jsx)(action_bar_1.ActionBarPrimitive.Feedback, { className: "flex gap-1", children: ({ selected, onPositive, onNegative }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onPositive, className: (0, cn_1.cn)("rounded px-1.5 py-1 text-xs transition-colors", selected === "positive"
|
|
21
|
+
? "bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400"
|
|
22
|
+
: "text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300"), "aria-label": "Good response", children: "\uD83D\uDC4D" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onNegative, className: (0, cn_1.cn)("rounded px-1.5 py-1 text-xs transition-colors", selected === "negative"
|
|
23
|
+
? "bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400"
|
|
24
|
+
: "text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300"), "aria-label": "Bad response", children: "\uD83D\uDC4E" })] })) })] }) })] }))] })] }));
|
|
25
|
+
}
|
|
26
|
+
function Message({ message, index, className }) {
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)(message_1.MessagePrimitive.Root, { message: message, index: index, children: (0, jsx_runtime_1.jsx)(MessageInner, { className: className }) }));
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StatusIndicator = StatusIndicator;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const statusConfig = {
|
|
7
|
+
ready: { color: "bg-emerald-500", label: "Ready" },
|
|
8
|
+
submitted: { color: "bg-amber-500", label: "Sending..." },
|
|
9
|
+
streaming: { color: "bg-amber-500 animate-pulse", label: "Responding..." },
|
|
10
|
+
error: { color: "bg-red-500", label: "Error" },
|
|
11
|
+
};
|
|
12
|
+
function StatusIndicator({ status, className }) {
|
|
13
|
+
var _a;
|
|
14
|
+
const config = (_a = statusConfig[status]) !== null && _a !== void 0 ? _a : statusConfig.ready;
|
|
15
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex items-center gap-2 text-xs", className), "data-status": status, children: [(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("h-2 w-2 rounded-full", config.color) }), (0, jsx_runtime_1.jsx)("span", { children: config.label })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Suggestions = Suggestions;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const kognitive_context_1 = require("../context/kognitive-context");
|
|
7
|
+
function Suggestions({ className }) {
|
|
8
|
+
const { suggestions, send, isStreaming } = (0, kognitive_context_1.useKognitiveContext)();
|
|
9
|
+
if (suggestions.length === 0 || isStreaming)
|
|
10
|
+
return null;
|
|
11
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("flex flex-wrap gap-2 py-3", className), "data-suggestions": true, children: suggestions.map((suggestion, i) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => send(suggestion), className: "rounded-full border border-zinc-200 bg-white px-3 py-1.5 text-xs text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800", children: suggestion }, i))) }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ThreadList = ThreadList;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const thread_list_1 = require("../primitives/thread-list");
|
|
7
|
+
const statusColors = {
|
|
8
|
+
running: "bg-amber-500",
|
|
9
|
+
completed: "bg-emerald-500",
|
|
10
|
+
interrupted: "bg-orange-500",
|
|
11
|
+
error: "bg-red-500",
|
|
12
|
+
};
|
|
13
|
+
function ThreadList({ className }) {
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)(thread_list_1.ThreadListPrimitive.Root, { className: (0, cn_1.cn)("flex h-full flex-col border-r border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900", className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between border-b border-zinc-200 px-4 py-3 dark:border-zinc-700", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: "Conversations" }), (0, jsx_runtime_1.jsx)(thread_list_1.ThreadListPrimitive.New, { className: "rounded-lg bg-blue-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600", children: "New" })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto", children: (0, jsx_runtime_1.jsx)(thread_list_1.ThreadListPrimitive.Items, { children: (thread, isActive) => {
|
|
15
|
+
var _a;
|
|
16
|
+
return ((0, jsx_runtime_1.jsxs)(thread_list_1.ThreadListPrimitive.Item, { thread: thread, isActive: isActive, className: (0, cn_1.cn)("flex w-full flex-col gap-1 border-b border-zinc-100 px-4 py-3 text-left text-sm transition-colors dark:border-zinc-800", isActive
|
|
17
|
+
? "bg-white dark:bg-zinc-800"
|
|
18
|
+
: "hover:bg-zinc-100 dark:hover:bg-zinc-800/50"), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("h-2 w-2 shrink-0 rounded-full", (_a = statusColors[thread.status]) !== null && _a !== void 0 ? _a : "bg-zinc-400") }), (0, jsx_runtime_1.jsx)("span", { className: "truncate font-medium", children: thread.title || thread.lastUserPreview || "New conversation" })] }), thread.lastAssistantPreview && ((0, jsx_runtime_1.jsx)("p", { className: "truncate text-xs text-zinc-500 dark:text-zinc-400", children: thread.lastAssistantPreview }))] }, thread.sessionId));
|
|
19
|
+
} }) })] }));
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ComponentType } from "react";
|
|
3
|
+
export interface ThreadProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
emptyState?: React.ReactNode;
|
|
6
|
+
allowAttachments?: boolean;
|
|
7
|
+
components?: {
|
|
8
|
+
Message?: ComponentType<{
|
|
9
|
+
message: any;
|
|
10
|
+
index: number;
|
|
11
|
+
}>;
|
|
12
|
+
Composer?: ComponentType;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function Thread({ className, emptyState, allowAttachments, components, }: ThreadProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Thread = Thread;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const thread_1 = require("../primitives/thread");
|
|
7
|
+
const message_1 = require("./message");
|
|
8
|
+
const composer_1 = require("./composer");
|
|
9
|
+
const status_indicator_1 = require("./status-indicator");
|
|
10
|
+
const error_banner_1 = require("./error-banner");
|
|
11
|
+
const suggestions_1 = require("./suggestions");
|
|
12
|
+
const kognitive_context_1 = require("../context/kognitive-context");
|
|
13
|
+
function Thread({ className, emptyState, allowAttachments = false, components, }) {
|
|
14
|
+
var _a, _b;
|
|
15
|
+
const { status } = (0, kognitive_context_1.useKognitiveContext)();
|
|
16
|
+
const MessageComponent = (_a = components === null || components === void 0 ? void 0 : components.Message) !== null && _a !== void 0 ? _a : message_1.Message;
|
|
17
|
+
const ComposerComponent = (_b = components === null || components === void 0 ? void 0 : components.Composer) !== null && _b !== void 0 ? _b : composer_1.Composer;
|
|
18
|
+
return ((0, jsx_runtime_1.jsxs)(thread_1.ThreadPrimitive.Root, { className: (0, cn_1.cn)("flex h-full flex-col", className), children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-between border-b border-zinc-200 px-4 py-2 dark:border-zinc-700", children: (0, jsx_runtime_1.jsx)(status_indicator_1.StatusIndicator, { status: status }) }), (0, jsx_runtime_1.jsx)(thread_1.ThreadPrimitive.Error, { className: "px-4 pt-3", children: (error) => (0, jsx_runtime_1.jsx)(error_banner_1.ErrorBanner, { message: error.message }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 overflow-y-auto px-4", "data-kognitive-thread-root": true, children: [(0, jsx_runtime_1.jsx)(thread_1.ThreadPrimitive.Empty, { children: emptyState !== null && emptyState !== void 0 ? emptyState : ((0, jsx_runtime_1.jsx)("div", { className: "flex h-full items-center justify-center text-zinc-400", children: (0, jsx_runtime_1.jsx)("p", { children: "Start a conversation" }) })) }), (0, jsx_runtime_1.jsx)(thread_1.ThreadPrimitive.Messages, { children: (message, index) => ((0, jsx_runtime_1.jsx)(MessageComponent, { message: message, index: index }, message.id)) }), (0, jsx_runtime_1.jsx)(thread_1.ThreadPrimitive.Loading, { children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-3 py-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-zinc-100 text-sm text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400", children: "A" }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-1", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-zinc-400", style: { animationDelay: "0ms" } }), (0, jsx_runtime_1.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-zinc-400", style: { animationDelay: "150ms" } }), (0, jsx_runtime_1.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-zinc-400", style: { animationDelay: "300ms" } })] }) })] }) }), (0, jsx_runtime_1.jsx)(suggestions_1.Suggestions, {})] }), (components === null || components === void 0 ? void 0 : components.Composer) ? ((0, jsx_runtime_1.jsx)(ComposerComponent, {})) : ((0, jsx_runtime_1.jsx)(composer_1.Composer, { allowAttachments: allowAttachments }))] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ToolApprovalProps {
|
|
2
|
+
toolCallId: string;
|
|
3
|
+
toolName: string;
|
|
4
|
+
input: unknown;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function ToolApproval({ toolCallId, toolName, input, className }: ToolApprovalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolApproval = ToolApproval;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const cn_1 = require("../utils/cn");
|
|
6
|
+
const kognitive_context_1 = require("../context/kognitive-context");
|
|
7
|
+
function ToolApproval({ toolCallId, toolName, input, className }) {
|
|
8
|
+
const { onToolApproval } = (0, kognitive_context_1.useKognitiveContext)();
|
|
9
|
+
if (!onToolApproval)
|
|
10
|
+
return null;
|
|
11
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("my-2 rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-800 dark:bg-amber-950/30", className), "data-tool-approval": toolCallId, children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-2 flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-amber-600", children: "\u26A0" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-medium", children: [(0, jsx_runtime_1.jsx)("strong", { children: toolName }), " requires approval"] })] }), input !== undefined && input !== null && ((0, jsx_runtime_1.jsx)("pre", { className: "mb-3 overflow-auto rounded bg-amber-100/50 p-2 text-xs dark:bg-amber-900/20", children: JSON.stringify(input, null, 2) })), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onToolApproval(toolCallId, true), className: "rounded-lg bg-emerald-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-emerald-700", children: "Approve" }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onToolApproval(toolCallId, false), className: "rounded-lg border border-zinc-300 px-4 py-1.5 text-sm font-medium text-zinc-700 hover:bg-zinc-100 dark:border-zinc-600 dark:text-zinc-300 dark:hover:bg-zinc-800", children: "Reject" })] })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ToolUIRenderProps } from "../tool-ui/types";
|
|
2
|
+
export interface ToolInvocationProps extends ToolUIRenderProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function ToolInvocation({ toolName, toolCallId, input, output, state, className, }: ToolInvocationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolInvocation = ToolInvocation;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const cn_1 = require("../utils/cn");
|
|
7
|
+
const tool_approval_1 = require("./tool-approval");
|
|
8
|
+
function isComplete(state) {
|
|
9
|
+
return state === "output-available";
|
|
10
|
+
}
|
|
11
|
+
function stateLabel(state) {
|
|
12
|
+
switch (state) {
|
|
13
|
+
case "input-streaming": return "streaming...";
|
|
14
|
+
case "input-available": return "calling...";
|
|
15
|
+
case "approval-requested": return "awaiting approval";
|
|
16
|
+
case "approval-responded": return "approved";
|
|
17
|
+
case "output-available": return "completed";
|
|
18
|
+
case "error": return "error";
|
|
19
|
+
default: return state;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function ToolInvocation({ toolName, toolCallId, input, output, state, className, }) {
|
|
23
|
+
const [expanded, setExpanded] = (0, react_1.useState)(false);
|
|
24
|
+
const done = isComplete(state);
|
|
25
|
+
if (state === "approval-requested") {
|
|
26
|
+
return (0, jsx_runtime_1.jsx)(tool_approval_1.ToolApproval, { toolCallId: toolCallId, toolName: toolName, input: input, className: className });
|
|
27
|
+
}
|
|
28
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("my-2 rounded-lg border border-zinc-200 dark:border-zinc-700", className), "data-tool": toolName, "data-tool-state": state, children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setExpanded(!expanded), className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-zinc-50 dark:hover:bg-zinc-800/50", "aria-expanded": expanded, children: [(0, jsx_runtime_1.jsx)("span", { className: "text-amber-500", children: "\uD83D\uDD27" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: toolName }), (0, jsx_runtime_1.jsx)("span", { className: (0, cn_1.cn)("ml-auto rounded-full px-2 py-0.5 text-xs", done
|
|
29
|
+
? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
|
|
30
|
+
: state === "error"
|
|
31
|
+
? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
|
|
32
|
+
: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"), children: stateLabel(state) }), (0, jsx_runtime_1.jsx)("span", { className: "text-zinc-400", children: expanded ? "\u25BC" : "\u25B6" })] }), expanded && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-zinc-200 px-3 py-2 dark:border-zinc-700", children: [input !== undefined && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-1 text-xs font-medium text-zinc-500", children: "Arguments" }), (0, jsx_runtime_1.jsx)("pre", { className: "overflow-auto rounded bg-zinc-50 p-2 text-xs dark:bg-zinc-800/50", children: JSON.stringify(input, null, 2) })] })), output !== undefined && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-1 text-xs font-medium text-zinc-500", children: "Result" }), (0, jsx_runtime_1.jsx)("pre", { className: "overflow-auto rounded bg-zinc-50 p-2 text-xs dark:bg-zinc-800/50", children: JSON.stringify(output, null, 2) })] }))] }))] }));
|
|
33
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { KognitiveContextValue } from "./types";
|
|
2
|
+
export declare const KognitiveContextProvider: import("react").Provider<KognitiveContextValue | null>, useKognitiveContext: () => KognitiveContextValue, KognitiveContext: import("react").Context<KognitiveContextValue | null>;
|