@kanzo-tech/ai 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-mark.d.ts +1 -1
- package/dist/ai-mark.d.ts.map +1 -1
- package/dist/ai-mark.js +12 -12
- package/dist/ai-mark.js.map +1 -1
- package/dist/assist.d.ts +71 -0
- package/dist/assist.d.ts.map +1 -0
- package/dist/assist.js +394 -0
- package/dist/assist.js.map +1 -0
- package/dist/chat.d.ts +41 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +77 -0
- package/dist/chat.js.map +1 -0
- package/dist/engine.d.ts +101 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +197 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +7 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -56
- package/dist/index.js.map +1 -1
- package/dist/message.js +25 -66
- package/dist/message.js.map +1 -1
- package/dist/prompt-input.d.ts +2 -2
- package/dist/prompt-input.d.ts.map +1 -1
- package/dist/prompt-input.js +47 -49
- package/dist/prompt-input.js.map +1 -1
- package/dist/proposals.d.ts +28 -0
- package/dist/proposals.d.ts.map +1 -0
- package/dist/proposals.js +56 -0
- package/dist/proposals.js.map +1 -0
- package/dist/reasoning.d.ts +4 -3
- package/dist/reasoning.d.ts.map +1 -1
- package/dist/reasoning.js +60 -55
- package/dist/reasoning.js.map +1 -1
- package/dist/tool.d.ts +25 -50
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +83 -95
- package/dist/tool.js.map +1 -1
- package/package.json +18 -34
- package/dist/complete.d.ts +0 -87
- package/dist/complete.d.ts.map +0 -1
- package/dist/complete.js +0 -278
- package/dist/complete.js.map +0 -1
- package/dist/message-part.d.ts +0 -122
- package/dist/message-part.d.ts.map +0 -1
- package/dist/message-part.js +0 -8
- package/dist/message-part.js.map +0 -1
- package/dist/message-text.d.ts +0 -44
- package/dist/message-text.d.ts.map +0 -1
- package/dist/message-text.js +0 -49
- package/dist/message-text.js.map +0 -1
- package/dist/suggest.d.ts +0 -82
- package/dist/suggest.d.ts.map +0 -1
- package/dist/suggest.js +0 -123
- package/dist/suggest.js.map +0 -1
- package/dist/task.d.ts +0 -48
- package/dist/task.d.ts.map +0 -1
- package/dist/task.js +0 -91
- package/dist/task.js.map +0 -1
- package/dist/types.d.ts +0 -10
- package/dist/types.d.ts.map +0 -1
- package/dist/use-ai.d.ts +0 -170
- package/dist/use-ai.d.ts.map +0 -1
- package/dist/use-ai.js +0 -186
- package/dist/use-ai.js.map +0 -1
package/dist/reasoning.js
CHANGED
|
@@ -1,55 +1,59 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { ark as
|
|
4
|
-
import { BrainIcon as
|
|
5
|
-
import * as
|
|
6
|
-
import { Collapsible as
|
|
7
|
-
const
|
|
2
|
+
import { jsx as n, jsxs as h, Fragment as S } from "react/jsx-runtime";
|
|
3
|
+
import { ark as v } from "@ark-ui/react/factory";
|
|
4
|
+
import { BrainIcon as T } from "lucide-react";
|
|
5
|
+
import * as t from "react";
|
|
6
|
+
import { Collapsible as I, cn as f, CollapsibleTrigger as k, Spinner as z, CollapsibleIndicator as E, CollapsibleContent as M } from "@kanzo-tech/ui";
|
|
7
|
+
const g = t.createContext({
|
|
8
8
|
seconds: null,
|
|
9
|
-
streaming: !1
|
|
10
|
-
|
|
9
|
+
streaming: !1,
|
|
10
|
+
text: ""
|
|
11
|
+
}), O = 1e3, _ = 1e3, L = (s) => {
|
|
11
12
|
const {
|
|
12
|
-
|
|
13
|
-
open:
|
|
14
|
-
defaultOpen:
|
|
15
|
-
onOpenChange:
|
|
16
|
-
className:
|
|
17
|
-
children:
|
|
18
|
-
slot:
|
|
19
|
-
...
|
|
20
|
-
} =
|
|
21
|
-
return
|
|
22
|
-
if (
|
|
23
|
-
|
|
13
|
+
part: e,
|
|
14
|
+
open: i,
|
|
15
|
+
defaultOpen: c = !1,
|
|
16
|
+
onOpenChange: o,
|
|
17
|
+
className: l,
|
|
18
|
+
children: u,
|
|
19
|
+
slot: b,
|
|
20
|
+
...N
|
|
21
|
+
} = s, r = e.state === "streaming", [C, d] = t.useState(c), [R, w] = t.useState(null), p = t.useRef(!1), x = t.useRef(!1), a = t.useRef(null);
|
|
22
|
+
return t.useEffect(() => {
|
|
23
|
+
if (r) {
|
|
24
|
+
a.current ?? (a.current = Date.now());
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
}, [
|
|
28
|
-
if (
|
|
29
|
-
if (
|
|
30
|
-
|
|
27
|
+
a.current !== null && (w(Math.max(1, Math.ceil((Date.now() - a.current) / _))), a.current = null);
|
|
28
|
+
}, [r]), t.useEffect(() => {
|
|
29
|
+
if (r === x.current || (x.current = r, p.current)) return;
|
|
30
|
+
if (r) {
|
|
31
|
+
d(!0);
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
|
-
const
|
|
34
|
-
return () => clearTimeout(
|
|
35
|
-
}, [
|
|
36
|
-
|
|
34
|
+
const m = setTimeout(() => d(!1), O);
|
|
35
|
+
return () => clearTimeout(m);
|
|
36
|
+
}, [r]), /* @__PURE__ */ n(g.Provider, { value: { seconds: R, streaming: r, text: e.text }, children: /* @__PURE__ */ n(
|
|
37
|
+
I,
|
|
37
38
|
{
|
|
38
|
-
className: f("group/reasoning w-full",
|
|
39
|
-
"data-streaming":
|
|
40
|
-
onOpenChange: (
|
|
41
|
-
|
|
39
|
+
className: f("group/reasoning w-full", l),
|
|
40
|
+
"data-streaming": r ? "" : void 0,
|
|
41
|
+
onOpenChange: (m) => {
|
|
42
|
+
p.current = !0, d(m.open), o == null || o(m);
|
|
42
43
|
},
|
|
43
|
-
open:
|
|
44
|
-
...
|
|
45
|
-
slot:
|
|
46
|
-
children:
|
|
44
|
+
open: i ?? C,
|
|
45
|
+
...N,
|
|
46
|
+
slot: b ?? "reasoning",
|
|
47
|
+
children: u ?? /* @__PURE__ */ h(S, { children: [
|
|
48
|
+
/* @__PURE__ */ n(y, {}),
|
|
49
|
+
/* @__PURE__ */ n(D, {})
|
|
50
|
+
] })
|
|
47
51
|
}
|
|
48
52
|
) });
|
|
49
|
-
},
|
|
50
|
-
const { className: e, children:
|
|
51
|
-
return /* @__PURE__ */
|
|
52
|
-
|
|
53
|
+
}, j = (s, e) => s ? "Thinking…" : e === null ? "Reasoning" : `Thought for ${e} second${e === 1 ? "" : "s"}`, y = (s) => {
|
|
54
|
+
const { className: e, children: i, slot: c, ...o } = s, { seconds: l, streaming: u } = t.useContext(g);
|
|
55
|
+
return /* @__PURE__ */ h(
|
|
56
|
+
k,
|
|
53
57
|
{
|
|
54
58
|
className: f(
|
|
55
59
|
"-ms-1.5 inline-flex min-h-[24px] w-fit items-center gap-1.5 rounded-md px-1.5 py-1",
|
|
@@ -59,19 +63,19 @@ const p = n.createContext({
|
|
|
59
63
|
"[&_svg:not([class*='size-'])]:size-3.5",
|
|
60
64
|
e
|
|
61
65
|
),
|
|
62
|
-
...
|
|
63
|
-
slot:
|
|
66
|
+
...o,
|
|
67
|
+
slot: c ?? "reasoning-trigger",
|
|
64
68
|
children: [
|
|
65
|
-
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
-
/* @__PURE__ */
|
|
69
|
+
u ? /* @__PURE__ */ n(z, { "aria-hidden": !0, className: "size-3.5" }) : /* @__PURE__ */ n(T, {}),
|
|
70
|
+
/* @__PURE__ */ n(v.span, { className: "text-start font-medium", children: i ?? j(u, l) }),
|
|
71
|
+
/* @__PURE__ */ n(E, { className: "opacity-64" })
|
|
68
72
|
]
|
|
69
73
|
}
|
|
70
74
|
);
|
|
71
|
-
},
|
|
72
|
-
const { className: e, slot:
|
|
73
|
-
return /* @__PURE__ */
|
|
74
|
-
|
|
75
|
+
}, D = (s) => {
|
|
76
|
+
const { className: e, children: i, slot: c, ...o } = s, { text: l } = t.useContext(g);
|
|
77
|
+
return /* @__PURE__ */ n(
|
|
78
|
+
M,
|
|
75
79
|
{
|
|
76
80
|
className: f(
|
|
77
81
|
"mt-1 ms-2.5 whitespace-pre-wrap break-words",
|
|
@@ -81,14 +85,15 @@ const p = n.createContext({
|
|
|
81
85
|
"transition-colors motion-reduce:transition-none!",
|
|
82
86
|
e
|
|
83
87
|
),
|
|
84
|
-
...
|
|
85
|
-
slot:
|
|
88
|
+
...o,
|
|
89
|
+
slot: c ?? "reasoning-content",
|
|
90
|
+
children: i ?? l
|
|
86
91
|
}
|
|
87
92
|
);
|
|
88
93
|
};
|
|
89
94
|
export {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
L as Reasoning,
|
|
96
|
+
D as ReasoningContent,
|
|
97
|
+
y as ReasoningTrigger
|
|
93
98
|
};
|
|
94
99
|
//# sourceMappingURL=reasoning.js.map
|
package/dist/reasoning.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reasoning.js","sources":["../src/reasoning.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { BrainIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport {\n cn,\n Collapsible,\n CollapsibleContent,\n CollapsibleIndicator,\n CollapsibleTrigger,\n Spinner,\n} from \"@kanzo-tech/ui\";\n\nconst Ctx = React.createContext<{ streaming: boolean; seconds: number | null }>({\n seconds: null,\n streaming: false,\n});\n\n/**\n * How long the thinking is left on screen after it stops. AI Elements' `AUTO_CLOSE_DELAY`, and the\n * reason is the last sentence: closing on the instant the stream ends takes the end of the thought\n * away from the reader who was reading it.\n */\nconst LINGER = 1000;\nconst MS_IN_S = 1000;\n\nexport interface ReasoningProps extends React.ComponentProps<typeof Collapsible> {\n /** The
|
|
1
|
+
{"version":3,"file":"reasoning.js","sources":["../src/reasoning.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { BrainIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport {\n cn,\n Collapsible,\n CollapsibleContent,\n CollapsibleIndicator,\n CollapsibleTrigger,\n Spinner,\n} from \"@kanzo-tech/ui\";\nimport type { ReasoningUIPart } from \"@kanzo-tech/llm\";\n\nconst Ctx = React.createContext<{ streaming: boolean; seconds: number | null; text: string }>({\n seconds: null,\n streaming: false,\n text: \"\",\n});\n\n/**\n * How long the thinking is left on screen after it stops. AI Elements' `AUTO_CLOSE_DELAY`, and the\n * reason is the last sentence: closing on the instant the stream ends takes the end of the thought\n * away from the reader who was reading it.\n */\nconst LINGER = 1000;\nconst MS_IN_S = 1000;\n\nexport interface ReasoningProps extends Omit<React.ComponentProps<typeof Collapsible>, \"part\"> {\n /** The reasoning as the AI SDK streams it: its text, and whether it is still arriving. */\n part: ReasoningUIPart;\n}\n\n/**\n * A model's thinking, folded away.\n *\n * The behaviour that *is* the component: it opens itself when the thinking starts and closes itself\n * when it ends, so the reader watches it happen without being left with a wall of it afterwards.\n * One exception, and it is the reason for the ref rather than a plain effect — **a reader's own\n * toggle ends the automatic behaviour for good.** Anything else means a panel that reopens what\n * somebody just closed, which is the version of this everyone has met.\n *\n * `group/reasoning` sits beside `Collapsible`'s own `group/collapsible`: the parts below key off\n * `data-streaming`, which is this component's, not the machine's.\n */\nexport const Reasoning = (props: ReasoningProps) => {\n const {\n part,\n open,\n defaultOpen = false,\n onOpenChange,\n className,\n children,\n slot,\n ...rest\n } = props;\n const streaming = part.state === \"streaming\";\n const [selfOpen, setSelfOpen] = React.useState(defaultOpen);\n const [seconds, setSeconds] = React.useState<number | null>(null);\n const touched = React.useRef(false);\n const wasStreaming = React.useRef(false);\n const startedAt = React.useRef<number | null>(null);\n\n /**\n * **How long it thought, because the trigger says so once it is folded away.** Taken from AI\n * Elements, where the closed state reads *Thought for N seconds* rather than a static label — a\n * disclosure that says nothing about what is behind it gives the reader no reason to open it.\n *\n * Rounded up, and `null` until there is something to report: a block that never streamed has no\n * duration, which is not the same as a duration of zero.\n */\n React.useEffect(() => {\n if (streaming) {\n startedAt.current ??= Date.now();\n return;\n }\n if (startedAt.current === null) return;\n setSeconds(Math.max(1, Math.ceil((Date.now() - startedAt.current) / MS_IN_S)));\n startedAt.current = null;\n }, [streaming]);\n\n React.useEffect(() => {\n if (streaming === wasStreaming.current) return;\n wasStreaming.current = streaming;\n if (touched.current) return;\n if (streaming) {\n setSelfOpen(true);\n return;\n }\n // It lingers. Closing on the instant the last token lands snatches the end of the thought away\n // from somebody mid-sentence, and this is the one beat that makes the fold readable.\n const timer = setTimeout(() => setSelfOpen(false), LINGER);\n return () => clearTimeout(timer);\n }, [streaming]);\n\n return (\n <Ctx.Provider value={{ seconds, streaming, text: part.text }}>\n <Collapsible\n className={cn(\"group/reasoning w-full\", className)}\n data-streaming={streaming ? \"\" : undefined}\n onOpenChange={(details) => {\n touched.current = true;\n setSelfOpen(details.open);\n onOpenChange?.(details);\n }}\n open={open ?? selfOpen}\n {...rest}\n slot={slot ?? \"reasoning\"}\n >\n {children ?? (\n <>\n <ReasoningTrigger />\n <ReasoningContent />\n </>\n )}\n </Collapsible>\n </Ctx.Provider>\n );\n};\n\n/**\n * What the trigger says, which is the only thing a folded-away thought tells anybody.\n *\n * **`Spinner` and not a shimmer, and that is a deliberate divergence.** AI Elements shimmers the\n * word *Thinking...* — a gradient swept across the glyphs with `background-clip: text`, on a\n * `motion/react` loop. It is a second vocabulary for *busy* beside the one this library already\n * has, and it costs an animation library to say what a `Spinner` says. Every other busy surface\n * here spins; the ✨ spins while a completion streams. One busy is a house principle, and AI\n * Elements is a source rather than a reference.\n */\nconst label = (streaming: boolean, seconds: number | null) => {\n if (streaming) return \"Thinking…\";\n if (seconds === null) return \"Reasoning\";\n return `Thought for ${seconds} second${seconds === 1 ? \"\" : \"s\"}`;\n};\n\n/**\n * The disclosure itself, sized to its own words rather than to the column: thinking is subordinate\n * to the answer beside it, and a full-width bar with a chevron at the far end reads as a section\n * heading — the one thing this is not.\n */\nexport const ReasoningTrigger = (props: React.ComponentProps<typeof CollapsibleTrigger>) => {\n const { className, children, slot, ...rest } = props;\n const { seconds, streaming } = React.useContext(Ctx);\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"-ms-1.5 inline-flex min-h-[24px] w-fit items-center gap-1.5 rounded-md px-1.5 py-1\",\n \"text-muted-foreground text-xs\",\n \"transition-colors hover:bg-accent hover:text-foreground motion-reduce:transition-none!\",\n \"group-data-streaming/reasoning:text-info-foreground\",\n \"[&_svg:not([class*='size-'])]:size-3.5\",\n className\n )}\n {...rest}\n slot={slot ?? \"reasoning-trigger\"}\n >\n {streaming ? <Spinner aria-hidden className=\"size-3.5\" /> : <BrainIcon />}\n <ark.span className=\"text-start font-medium\">\n {children ?? label(streaming, seconds)}\n </ark.span>\n <CollapsibleIndicator className=\"opacity-64\" />\n </CollapsibleTrigger>\n );\n};\n\n/**\n * The thinking, on a rail rather than in a panel — a quotation of the model to itself, and quieter\n * than any message beside it. The rail takes the streaming tint so a wall of text that is still\n * growing says so at the edge, where it does not move the words.\n */\nexport const ReasoningContent = (props: React.ComponentProps<typeof CollapsibleContent>) => {\n const { className, children, slot, ...rest } = props;\n const { text } = React.useContext(Ctx);\n\n return (\n <CollapsibleContent\n className={cn(\n \"mt-1 ms-2.5 whitespace-pre-wrap break-words\",\n \"border-border border-s ps-3.5\",\n \"text-muted-foreground text-sm leading-relaxed\",\n \"group-data-streaming/reasoning:border-info\",\n \"transition-colors motion-reduce:transition-none!\",\n className\n )}\n {...rest}\n slot={slot ?? \"reasoning-content\"}\n >\n {children ?? text}\n </CollapsibleContent>\n );\n};\n"],"names":[],"mappings":";;;;;;AAeA;AAA8F;AACnF;AACE;AAEb;AA4BE;AAAM;AACJ;AACA;AACc;AACd;AACA;AACA;AACA;AACG;AAiBL;AACE;AACE;AACA;AAAA;AAEF;AAEoB;AAMpB;AACA;AACE;AACA;AAAA;AAIF;AACA;AAA+B;AAK7B;AAAC;AAAA;AACkD;AAChB;AAE/B;AAEe;AACjB;AACc;AACV;AACU;AAIV;AAAkB;AACA;AACpB;AAAA;AAKV;AAwBE;AAGA;AACE;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AAAA;AAEE;AACU;AAEb;AAAsE;AAGvE;AAC6C;AAAA;AAAA;AAGnD;AAQE;AAGA;AACE;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AAAA;AAEE;AACU;AAED;AAAA;AAGnB;;;;;;"}
|
package/dist/tool.d.ts
CHANGED
|
@@ -1,56 +1,31 @@
|
|
|
1
1
|
import { ark } from '@ark-ui/react/factory';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { DynamicToolUIPart, ToolUIPart } from '@kanzo-tech/llm';
|
|
3
|
+
import { CollapsibleContent, CollapsibleTrigger } from '@kanzo-tech/ui';
|
|
4
4
|
import * as React from "react";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
defaultOpen?: boolean;
|
|
8
|
-
open?: boolean;
|
|
9
|
-
onOpenChange?: React.ComponentProps<typeof Collapsible>["onOpenChange"];
|
|
10
|
-
}
|
|
5
|
+
/** A tool call as the AI SDK streams it. */
|
|
6
|
+
export type ToolPart = ToolUIPart | DynamicToolUIPart;
|
|
11
7
|
/**
|
|
12
|
-
* One call the model made,
|
|
13
|
-
* it,
|
|
8
|
+
* One call the model made, bound to its part: state, name, input, output and error are read from
|
|
9
|
+
* it, so a caller passes the part and nothing else.
|
|
14
10
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* when it finished and not when it failed. Failing silently closed is the worse half: the reason
|
|
19
|
-
* the call failed sat behind a click nobody knew to make. The docblock claimed the opposite, and a
|
|
20
|
-
* showcase had to work around it before anyone noticed.
|
|
21
|
-
*
|
|
22
|
-
* A caller passing `open` still wins outright; `defaultOpen` still decides the first paint.
|
|
23
|
-
*
|
|
24
|
-
* The state sits on a wrapper rather than on the collapsible, and that is not tidiness: Ark writes
|
|
25
|
-
* its own `data-state` (`open` / `closed`) on the machine's root, so a tool state written there
|
|
26
|
-
* replaces it — the parts keep working, and every `[data-state=open]` a consumer wrote stops
|
|
27
|
-
* matching, with nothing to see in a diff.
|
|
28
|
-
*/
|
|
29
|
-
export declare const Tool: (props: ToolProps) => React.JSX.Element;
|
|
30
|
-
/**
|
|
31
|
-
* The row that says a call happened: the wrench, the tool's name in the face its arguments are
|
|
32
|
-
* written in, the state as a pill, and the chevron the whole row toggles.
|
|
33
|
-
*/
|
|
34
|
-
export declare const ToolHeader: (props: React.ComponentProps<typeof CollapsibleTrigger>) => React.JSX.Element;
|
|
35
|
-
export declare const ToolContent: (props: React.ComponentProps<typeof CollapsibleContent>) => React.JSX.Element;
|
|
36
|
-
export interface ToolIoProps extends React.ComponentProps<typeof ark.div> {
|
|
37
|
-
/** Drawn as a JSON tree when there are no children. */
|
|
38
|
-
data?: unknown;
|
|
39
|
-
/** The small heading over the panel. `null` drops it. */
|
|
40
|
-
label?: string | null;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* What was passed to the call — **children, not a formatted-JSON prop.**
|
|
44
|
-
*
|
|
45
|
-
* The reference takes `input` and renders it as JSON because a general chatbot cannot know what
|
|
46
|
-
* the tool was. We always know: our input is a SQL statement and our output is a result table, and
|
|
47
|
-
* both have a component in this house already. So the payload is composition, and JSON is only the
|
|
48
|
-
* default for when the caller has nothing better — never the one thing on offer.
|
|
49
|
-
*
|
|
50
|
-
* Which is also why the panel does not force a monospace face on everything inside it: a result
|
|
51
|
-
* table set in mono is the cost of a default that assumed JSON. Code sets itself.
|
|
11
|
+
* It opens itself when the call settles — a result is what a reader came for — unless the reader
|
|
12
|
+
* has already opened or closed it, in which case their choice stands. The state sits on a wrapper
|
|
13
|
+
* rather than on the collapsible because Ark writes its own `data-state` (`open`/`closed`) there.
|
|
52
14
|
*/
|
|
53
|
-
export declare
|
|
54
|
-
|
|
55
|
-
|
|
15
|
+
export declare function Tool(props: Omit<React.ComponentProps<typeof ark.div>, "part"> & {
|
|
16
|
+
part: ToolPart;
|
|
17
|
+
}): React.JSX.Element;
|
|
18
|
+
/** The tool's name, its state as a pill, and the chevron the whole row toggles. */
|
|
19
|
+
export declare function ToolHeader(props: React.ComponentProps<typeof CollapsibleTrigger>): React.JSX.Element;
|
|
20
|
+
export declare function ToolContent(props: React.ComponentProps<typeof CollapsibleContent>): React.JSX.Element;
|
|
21
|
+
/** What the model passed in; the JSON tree unless `children` draws it. */
|
|
22
|
+
export declare function ToolInput(props: {
|
|
23
|
+
children?: React.ReactNode;
|
|
24
|
+
label?: string;
|
|
25
|
+
}): React.JSX.Element | null;
|
|
26
|
+
/** What came back — or why nothing did. The JSON tree unless `children` draws it. */
|
|
27
|
+
export declare function ToolOutput(props: {
|
|
28
|
+
children?: React.ReactNode;
|
|
29
|
+
label?: string;
|
|
30
|
+
}): React.JSX.Element | null;
|
|
56
31
|
//# sourceMappingURL=tool.d.ts.map
|
package/dist/tool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAE5C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,iBAAiB,EAAe,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAKL,kBAAkB,EAElB,kBAAkB,EAGnB,MAAM,gBAAgB,CAAC;AAExB,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAuCtD;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,qBA0ClG;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,qBA2BhF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,qBASjF;AAeD,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,4BAQ9E;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,4BAe/E"}
|
package/dist/tool.js
CHANGED
|
@@ -1,122 +1,110 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as t, jsxs as
|
|
3
|
-
import { ark as
|
|
4
|
-
import { WrenchIcon as
|
|
5
|
-
import * as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
c.div,
|
|
2
|
+
import { jsx as t, jsxs as i, Fragment as C } from "react/jsx-runtime";
|
|
3
|
+
import { ark as u } from "@ark-ui/react/factory";
|
|
4
|
+
import { WrenchIcon as T, CircleXIcon as I, CircleCheckIcon as k, CircleDashedIcon as O } from "lucide-react";
|
|
5
|
+
import * as n from "react";
|
|
6
|
+
import { getToolName as R } from "@kanzo-tech/llm";
|
|
7
|
+
import { Collapsible as E, cn as d, CollapsibleTrigger as P, Badge as L, CollapsibleIndicator as y, CollapsibleContent as z, JsonTreeView as x, Spinner as A } from "@kanzo-tech/ui";
|
|
8
|
+
const g = {
|
|
9
|
+
"input-streaming": { tone: "info", label: "Preparing", settled: !1, failed: !1 },
|
|
10
|
+
"input-available": { tone: "info", label: "Running", settled: !1, failed: !1 },
|
|
11
|
+
"approval-requested": { tone: "outline", label: "Awaiting approval", settled: !1, failed: !1 },
|
|
12
|
+
"approval-responded": { tone: "info", label: "Running", settled: !1, failed: !1 },
|
|
13
|
+
"output-available": { tone: "success", label: "Done", settled: !0, failed: !1 },
|
|
14
|
+
"output-error": { tone: "destructive", label: "Failed", settled: !0, failed: !0 },
|
|
15
|
+
"output-denied": { tone: "destructive", label: "Denied", settled: !0, failed: !0 }
|
|
16
|
+
}, D = (e) => e.failed ? /* @__PURE__ */ t(I, { className: "text-destructive-foreground" }) : e.settled ? /* @__PURE__ */ t(k, { className: "text-success-foreground" }) : e.tone === "outline" ? /* @__PURE__ */ t(O, { className: "text-muted-foreground" }) : /* @__PURE__ */ t(A, { className: "text-info-foreground" }), S = "mb-1.5 block font-medium text-muted-foreground text-xs uppercase tracking-wide", j = "min-w-0 overflow-x-auto rounded-lg bg-muted px-3 py-2 text-xs [&_code]:font-mono", v = n.createContext(null), m = (e) => {
|
|
17
|
+
const l = n.useContext(v);
|
|
18
|
+
if (!l) throw new Error(`${e} must render inside <Tool>`);
|
|
19
|
+
return l;
|
|
20
|
+
};
|
|
21
|
+
function X(e) {
|
|
22
|
+
const { part: l, className: a, children: r, slot: c, ...s } = e, o = g[l.state], [N, p] = n.useState(o.settled), h = n.useRef(!1), b = n.useRef(o.settled);
|
|
23
|
+
return n.useEffect(() => {
|
|
24
|
+
!h.current && o.settled && !b.current && p(!0), b.current = o.settled;
|
|
25
|
+
}, [o.settled]), /* @__PURE__ */ t(v.Provider, { value: l, children: /* @__PURE__ */ t(
|
|
26
|
+
u.div,
|
|
28
27
|
{
|
|
29
|
-
className:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"data-state": e,
|
|
35
|
-
...T,
|
|
36
|
-
"data-slot": r ?? "tool",
|
|
28
|
+
className: d("group/tool w-full overflow-hidden rounded-xl border bg-card shadow-xs/5", a),
|
|
29
|
+
"data-failed": o.failed || void 0,
|
|
30
|
+
"data-state": l.state,
|
|
31
|
+
...s,
|
|
32
|
+
"data-slot": c ?? "tool",
|
|
37
33
|
children: /* @__PURE__ */ t(
|
|
38
|
-
|
|
34
|
+
E,
|
|
39
35
|
{
|
|
40
|
-
onOpenChange: (
|
|
41
|
-
|
|
36
|
+
onOpenChange: (w) => {
|
|
37
|
+
h.current = !0, p(w.open);
|
|
42
38
|
},
|
|
43
|
-
open:
|
|
39
|
+
open: N,
|
|
44
40
|
slot: "tool-collapsible",
|
|
45
|
-
children:
|
|
41
|
+
children: r ?? /* @__PURE__ */ i(C, { children: [
|
|
42
|
+
/* @__PURE__ */ t(B, {}),
|
|
43
|
+
/* @__PURE__ */ i(F, { children: [
|
|
44
|
+
/* @__PURE__ */ t(H, {}),
|
|
45
|
+
/* @__PURE__ */ t(_, {})
|
|
46
|
+
] })
|
|
47
|
+
] })
|
|
46
48
|
}
|
|
47
49
|
)
|
|
48
50
|
}
|
|
49
51
|
) });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
}
|
|
53
|
+
function B(e) {
|
|
54
|
+
const { className: l, children: a, slot: r, ...c } = e, s = m("ToolHeader"), o = g[s.state];
|
|
55
|
+
return /* @__PURE__ */ i(
|
|
56
|
+
P,
|
|
54
57
|
{
|
|
55
|
-
className:
|
|
58
|
+
className: d(
|
|
56
59
|
"flex min-h-[24px] w-full items-center gap-2.5 px-3 py-2.5 text-sm",
|
|
57
60
|
"transition-colors hover:bg-accent motion-reduce:transition-none!",
|
|
58
61
|
"[&_svg:not([class*='size-'])]:size-4",
|
|
59
|
-
|
|
62
|
+
l
|
|
60
63
|
),
|
|
61
|
-
...
|
|
62
|
-
slot:
|
|
64
|
+
...c,
|
|
65
|
+
slot: r ?? "tool-header",
|
|
63
66
|
children: [
|
|
64
|
-
/* @__PURE__ */ t(
|
|
65
|
-
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1 truncate text-start font-medium font-mono", children:
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
/* @__PURE__ */ t(T, { className: "shrink-0 text-muted-foreground" }),
|
|
68
|
+
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1 truncate text-start font-medium font-mono", children: a ?? R(s) }),
|
|
69
|
+
/* @__PURE__ */ i(L, { "data-state": s.state, pill: !0, size: "sm", slot: "tool-badge", variant: o.tone, children: [
|
|
70
|
+
D(o),
|
|
71
|
+
o.label
|
|
69
72
|
] }),
|
|
70
|
-
/* @__PURE__ */ t(
|
|
73
|
+
/* @__PURE__ */ t(y, { className: "shrink-0 text-muted-foreground" })
|
|
71
74
|
]
|
|
72
75
|
}
|
|
73
76
|
);
|
|
74
|
-
}
|
|
75
|
-
|
|
77
|
+
}
|
|
78
|
+
function F(e) {
|
|
79
|
+
const { className: l, slot: a, ...r } = e;
|
|
76
80
|
return /* @__PURE__ */ t(
|
|
77
|
-
|
|
81
|
+
z,
|
|
78
82
|
{
|
|
79
|
-
className:
|
|
80
|
-
...
|
|
81
|
-
slot:
|
|
83
|
+
className: d("flex min-w-0 flex-col gap-4 border-t px-3 py-3", l),
|
|
84
|
+
...r,
|
|
85
|
+
slot: a ?? "tool-content"
|
|
82
86
|
}
|
|
83
87
|
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return /* @__PURE__ */
|
|
87
|
-
|
|
88
|
-
/* @__PURE__ */ t(
|
|
89
|
-
] })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
l === null ? null : /* @__PURE__ */ t(c.span, { className: v, "data-slot": "tool-label", children: l }),
|
|
100
|
-
/* @__PURE__ */ t(
|
|
101
|
-
c.div,
|
|
102
|
-
{
|
|
103
|
-
className: i(
|
|
104
|
-
w,
|
|
105
|
-
"group-data-[state=failed]/tool:bg-destructive/7"
|
|
106
|
-
),
|
|
107
|
-
"data-slot": "tool-panel",
|
|
108
|
-
children: r
|
|
109
|
-
}
|
|
110
|
-
)
|
|
111
|
-
] })
|
|
112
|
-
}
|
|
113
|
-
);
|
|
114
|
-
};
|
|
88
|
+
}
|
|
89
|
+
function f(e) {
|
|
90
|
+
return /* @__PURE__ */ i(u.div, { className: d("min-w-0", e.failed && "text-destructive-foreground"), "data-slot": e.slot, children: [
|
|
91
|
+
/* @__PURE__ */ t(u.span, { className: S, "data-slot": "tool-label", children: e.label }),
|
|
92
|
+
/* @__PURE__ */ t(u.div, { className: d(j, e.failed && "bg-destructive/7"), "data-slot": "tool-panel", children: e.children })
|
|
93
|
+
] });
|
|
94
|
+
}
|
|
95
|
+
function H(e) {
|
|
96
|
+
const l = m("ToolInput");
|
|
97
|
+
return e.children === void 0 && l.input === void 0 ? null : /* @__PURE__ */ t(f, { label: e.label ?? "Parameters", slot: "tool-input", children: e.children ?? /* @__PURE__ */ t(x, { data: l.input }) });
|
|
98
|
+
}
|
|
99
|
+
function _(e) {
|
|
100
|
+
const l = m("ToolOutput");
|
|
101
|
+
return l.state === "output-error" || l.state === "output-denied" ? /* @__PURE__ */ t(f, { failed: !0, label: e.label ?? "Error", slot: "tool-output", children: l.state === "output-error" ? l.errorText : "The call was not allowed." }) : l.state !== "output-available" ? null : /* @__PURE__ */ t(f, { label: e.label ?? "Result", slot: "tool-output", children: e.children ?? /* @__PURE__ */ t(x, { data: l.output }) });
|
|
102
|
+
}
|
|
115
103
|
export {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
104
|
+
X as Tool,
|
|
105
|
+
F as ToolContent,
|
|
106
|
+
B as ToolHeader,
|
|
107
|
+
H as ToolInput,
|
|
108
|
+
_ as ToolOutput
|
|
121
109
|
};
|
|
122
110
|
//# sourceMappingURL=tool.js.map
|
package/dist/tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sources":["../src/tool.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { WrenchIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport {\n Badge,\n type BadgeVariant,\n cn,\n Collapsible,\n CollapsibleContent,\n CollapsibleIndicator,\n CollapsibleTrigger,\n JsonTreeView,\n} from \"@kanzo-tech/ui\";\
|
|
1
|
+
{"version":3,"file":"tool.js","sources":["../src/tool.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { CircleCheckIcon, CircleDashedIcon, CircleXIcon, WrenchIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { type DynamicToolUIPart, getToolName, type ToolUIPart } from \"@kanzo-tech/llm\";\nimport {\n Badge,\n type BadgeVariant,\n cn,\n Collapsible,\n CollapsibleContent,\n CollapsibleIndicator,\n CollapsibleTrigger,\n JsonTreeView,\n Spinner,\n} from \"@kanzo-tech/ui\";\n\n/** A tool call as the AI SDK streams it. */\nexport type ToolPart = ToolUIPart | DynamicToolUIPart;\ntype State = ToolPart[\"state\"];\n\n/**\n * The AI SDK's own states, drawn — not mapped onto a vocabulary of ours. Four tones are all a\n * reader needs to tell apart (waiting, working, done, failed); the label says which of the SDK's\n * seven it is.\n */\nconst LOOK: Record<State, { tone: BadgeVariant; label: string; settled: boolean; failed: boolean }> = {\n \"input-streaming\": { tone: \"info\", label: \"Preparing\", settled: false, failed: false },\n \"input-available\": { tone: \"info\", label: \"Running\", settled: false, failed: false },\n \"approval-requested\": { tone: \"outline\", label: \"Awaiting approval\", settled: false, failed: false },\n \"approval-responded\": { tone: \"info\", label: \"Running\", settled: false, failed: false },\n \"output-available\": { tone: \"success\", label: \"Done\", settled: true, failed: false },\n \"output-error\": { tone: \"destructive\", label: \"Failed\", settled: true, failed: true },\n \"output-denied\": { tone: \"destructive\", label: \"Denied\", settled: true, failed: true },\n};\n\nconst mark = (look: (typeof LOOK)[State]) =>\n look.failed ? (\n <CircleXIcon className=\"text-destructive-foreground\" />\n ) : look.settled ? (\n <CircleCheckIcon className=\"text-success-foreground\" />\n ) : look.tone === \"outline\" ? (\n <CircleDashedIcon className=\"text-muted-foreground\" />\n ) : (\n <Spinner className=\"text-info-foreground\" />\n );\n\nconst LABEL = \"mb-1.5 block font-medium text-muted-foreground text-xs uppercase tracking-wide\";\nconst PANEL = \"min-w-0 overflow-x-auto rounded-lg bg-muted px-3 py-2 text-xs [&_code]:font-mono\";\n\nconst Ctx = React.createContext<ToolPart | null>(null);\nconst usePart = (name: string) => {\n const part = React.useContext(Ctx);\n if (!part) throw new Error(`${name} must render inside <Tool>`);\n return part;\n};\n\n/**\n * One call the model made, bound to its part: state, name, input, output and error are read from\n * it, so a caller passes the part and nothing else.\n *\n * It opens itself when the call settles — a result is what a reader came for — unless the reader\n * has already opened or closed it, in which case their choice stands. The state sits on a wrapper\n * rather than on the collapsible because Ark writes its own `data-state` (`open`/`closed`) there.\n */\nexport function Tool(props: Omit<React.ComponentProps<typeof ark.div>, \"part\"> & { part: ToolPart }) {\n const { part, className, children, slot, ...rest } = props;\n const look = LOOK[part.state];\n const [open, setOpen] = React.useState(look.settled);\n const touched = React.useRef(false);\n const wasSettled = React.useRef(look.settled);\n\n React.useEffect(() => {\n if (!touched.current && look.settled && !wasSettled.current) setOpen(true);\n wasSettled.current = look.settled;\n }, [look.settled]);\n\n return (\n <Ctx.Provider value={part}>\n <ark.div\n className={cn(\"group/tool w-full overflow-hidden rounded-xl border bg-card shadow-xs/5\", className)}\n data-failed={look.failed || undefined}\n data-state={part.state}\n {...rest}\n data-slot={slot ?? \"tool\"}\n >\n <Collapsible\n onOpenChange={(details) => {\n touched.current = true;\n setOpen(details.open);\n }}\n open={open}\n slot=\"tool-collapsible\"\n >\n {children ?? (\n <>\n <ToolHeader />\n <ToolContent>\n <ToolInput />\n <ToolOutput />\n </ToolContent>\n </>\n )}\n </Collapsible>\n </ark.div>\n </Ctx.Provider>\n );\n}\n\n/** The tool's name, its state as a pill, and the chevron the whole row toggles. */\nexport function ToolHeader(props: React.ComponentProps<typeof CollapsibleTrigger>) {\n const { className, children, slot, ...rest } = props;\n const part = usePart(\"ToolHeader\");\n const look = LOOK[part.state];\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"flex min-h-[24px] w-full items-center gap-2.5 px-3 py-2.5 text-sm\",\n \"transition-colors hover:bg-accent motion-reduce:transition-none!\",\n \"[&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...rest}\n slot={slot ?? \"tool-header\"}\n >\n <WrenchIcon className=\"shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1 truncate text-start font-medium font-mono\">\n {children ?? getToolName(part)}\n </span>\n <Badge data-state={part.state} pill size=\"sm\" slot=\"tool-badge\" variant={look.tone}>\n {mark(look)}\n {look.label}\n </Badge>\n <CollapsibleIndicator className=\"shrink-0 text-muted-foreground\" />\n </CollapsibleTrigger>\n );\n}\n\nexport function ToolContent(props: React.ComponentProps<typeof CollapsibleContent>) {\n const { className, slot, ...rest } = props;\n return (\n <CollapsibleContent\n className={cn(\"flex min-w-0 flex-col gap-4 border-t px-3 py-3\", className)}\n {...rest}\n slot={slot ?? \"tool-content\"}\n />\n );\n}\n\nfunction Io(props: { label: string; failed?: boolean; slot: string; children: React.ReactNode }) {\n return (\n <ark.div className={cn(\"min-w-0\", props.failed && \"text-destructive-foreground\")} data-slot={props.slot}>\n <ark.span className={LABEL} data-slot=\"tool-label\">\n {props.label}\n </ark.span>\n <ark.div className={cn(PANEL, props.failed && \"bg-destructive/7\")} data-slot=\"tool-panel\">\n {props.children}\n </ark.div>\n </ark.div>\n );\n}\n\n/** What the model passed in; the JSON tree unless `children` draws it. */\nexport function ToolInput(props: { children?: React.ReactNode; label?: string }) {\n const part = usePart(\"ToolInput\");\n if (props.children === undefined && part.input === undefined) return null;\n return (\n <Io label={props.label ?? \"Parameters\"} slot=\"tool-input\">\n {props.children ?? <JsonTreeView data={part.input} />}\n </Io>\n );\n}\n\n/** What came back — or why nothing did. The JSON tree unless `children` draws it. */\nexport function ToolOutput(props: { children?: React.ReactNode; label?: string }) {\n const part = usePart(\"ToolOutput\");\n if (part.state === \"output-error\" || part.state === \"output-denied\") {\n return (\n <Io failed label={props.label ?? \"Error\"} slot=\"tool-output\">\n {part.state === \"output-error\" ? part.errorText : \"The call was not allowed.\"}\n </Io>\n );\n }\n if (part.state !== \"output-available\") return null;\n return (\n <Io label={props.label ?? \"Result\"} slot=\"tool-output\">\n {props.children ?? <JsonTreeView data={part.output} />}\n </Io>\n );\n}\n"],"names":[],"mappings":";;;;;;;AA2BA;AAAsG;AACrB;AACF;AACgB;AACb;AACH;AACE;AAEjF;AAkBE;AACA;AACA;AACF;AAUO;AACL;AAMA;AACE;AAC0B;AAKxB;AAAK;AAAJ;AACmG;AACtE;AACX;AACb;AACe;AAEnB;AAAC;AAAA;AAEG;AACoB;AACtB;AACA;AACK;AAID;AAAY;AAEV;AAAW;AACC;AACd;AACF;AAAA;AAAA;AAEJ;AAIR;AAGO;AACL;AAIA;AACE;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AAAA;AAEE;AACU;AAEd;AAAuD;AAGvD;AAEG;AAAS;AACJ;AACR;AACiE;AAAA;AAAA;AAGvE;AAEO;AACL;AACA;AACE;AAAC;AAAA;AAC0E;AACrE;AACU;AAAA;AAGpB;AAEA;AACE;AAEI;AAEA;AAGA;AAGN;AAGO;AACL;AACA;AAMF;AAGO;AACL;AACA;AAaF;;;;;;;;"}
|