quassel 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChatInputToolbar.d.ts +35 -6
- package/ChatMessages.d.ts +19 -15
- package/ChatPanel.d.ts +4 -2
- package/ChatSendContext.d.ts +7 -12
- package/DetailModeSwitch.d.ts +1 -1
- package/Markdown.d.ts +4 -11
- package/MessageActions.d.ts +1 -10
- package/PendingActionCard.d.ts +13 -0
- package/QuasselProvider.d.ts +76 -0
- package/README.md +39 -38
- package/StepPopover.d.ts +1 -1
- package/TimestampSwitch.d.ts +2 -2
- package/WorkingScenes.d.ts +3 -1
- package/attachments.d.ts +24 -0
- package/chat-attachments.d.ts +6 -0
- package/chat-scroll.d.ts +12 -0
- package/chat.css +2051 -0
- package/chunk-IGCFQJZB.js +183 -0
- package/chunk-IGCFQJZB.js.map +7 -0
- package/events.d.ts +74 -17
- package/events.js +11 -1
- package/index.d.ts +17 -10
- package/index.js +1615 -980
- package/index.js.map +4 -4
- package/options.d.ts +1 -1
- package/package.json +12 -10
- package/texts.d.ts +38 -11
- package/timestamps.d.ts +6 -4
- package/types.d.ts +6 -6
- package/ui/button.d.ts +8 -0
- package/ui/card.d.ts +5 -0
- package/ui/cn.d.ts +2 -0
- package/ui/popover.d.ts +4 -0
- package/ui/spinner.d.ts +2 -0
- package/ui/stop-button.d.ts +10 -0
- package/ui/toggle.d.ts +8 -0
- package/ui/useFileInput.d.ts +20 -0
- package/useChatAction.d.ts +6 -0
- package/QuestionCard.d.ts +0 -12
- package/chunk-DOLTANTM.js +0 -84
- package/chunk-DOLTANTM.js.map +0 -7
- package/css/chat.css +0 -927
- package/css/foundation/base.css +0 -24
- package/css/foundation/index.css +0 -3
- package/css/foundation/panel.css +0 -111
- package/css/foundation/tokens.css +0 -68
- package/css/foundation/wash.css +0 -26
- package/css/question.css +0 -149
- package/icons.d.ts +0 -15
- package/server/http.d.ts +0 -17
- package/server/index.d.ts +0 -6
- package/server/index.js +0 -478
- package/server/index.js.map +0 -7
- package/server/manager.d.ts +0 -12
- package/server/openai.d.ts +0 -16
- package/server/session.d.ts +0 -27
- package/server/store.d.ts +0 -18
- package/server/types.d.ts +0 -62
- package/useChat.d.ts +0 -14
package/options.d.ts
CHANGED
|
@@ -39,4 +39,4 @@ export interface MessageActionsOptions {
|
|
|
39
39
|
custom?: (message: Message) => readonly MessageAction[];
|
|
40
40
|
}
|
|
41
41
|
export type SendShortcut = "enter" | "mod-enter";
|
|
42
|
-
export declare
|
|
42
|
+
export declare const appearanceStyle: (appearance?: ChatAppearance) => CSSProperties;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quassel",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Chat building blocks for React: streaming transcript with thinking and tool steps, input card, themable Tailwind styles and an event contract",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ronald Schlenker",
|
|
7
7
|
"repository": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"llm",
|
|
16
16
|
"agent",
|
|
17
17
|
"streaming",
|
|
18
|
-
"ui"
|
|
18
|
+
"ui",
|
|
19
|
+
"tailwind"
|
|
19
20
|
],
|
|
20
21
|
"type": "module",
|
|
21
22
|
"sideEffects": [
|
|
@@ -30,13 +31,14 @@
|
|
|
30
31
|
"types": "./events.d.ts",
|
|
31
32
|
"default": "./events.js"
|
|
32
33
|
},
|
|
33
|
-
"./
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
34
|
+
"./chat.css": "./chat.css"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@base-ui/react": "^1.8.0",
|
|
38
|
+
"class-variance-authority": "^0.7.1",
|
|
39
|
+
"cn": "^0.3.0",
|
|
40
|
+
"lucide-react": "^1.46.0",
|
|
41
|
+
"streamdown": "^2.6.0"
|
|
40
42
|
},
|
|
41
43
|
"peerDependencies": {
|
|
42
44
|
"react": "^18 || ^19",
|
package/texts.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ export interface ChatTexts {
|
|
|
2
2
|
working: string;
|
|
3
3
|
toolRunning: string;
|
|
4
4
|
toolStillRunning: string;
|
|
5
|
+
currentTool: string;
|
|
5
6
|
thinkingChip: string;
|
|
7
|
+
toolChip: string;
|
|
6
8
|
stepGroupOne: string;
|
|
7
9
|
stepGroupMany: string;
|
|
8
10
|
stepGroupCollapse: string;
|
|
@@ -17,23 +19,48 @@ export interface ChatTexts {
|
|
|
17
19
|
stop: string;
|
|
18
20
|
placeholder: string;
|
|
19
21
|
steeringPlaceholder: string;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
questionSubmit: string;
|
|
23
|
-
questionPlaceholder: string;
|
|
24
|
-
questionAnswer: string;
|
|
25
|
-
copyMessage: string;
|
|
26
|
-
copyCode: string;
|
|
27
|
-
copied: string;
|
|
28
|
-
copyFailed: string;
|
|
29
|
-
editMessage: string;
|
|
30
|
-
retryMessage: string;
|
|
22
|
+
steered: string;
|
|
23
|
+
inputHint: string;
|
|
31
24
|
detailModeTitle: string;
|
|
32
25
|
detailModeOff: string;
|
|
26
|
+
detailModeCurrent: string;
|
|
33
27
|
detailModeIcons: string;
|
|
34
28
|
detailModeChips: string;
|
|
35
29
|
detailModeGrouped: string;
|
|
36
30
|
detailModeCompact: string;
|
|
37
31
|
detailModeFull: string;
|
|
32
|
+
timestamps: string;
|
|
33
|
+
showTimestamps: string;
|
|
34
|
+
hideTimestamps: string;
|
|
35
|
+
copyMessage: string;
|
|
36
|
+
editMessage: string;
|
|
37
|
+
retryMessage: string;
|
|
38
|
+
copyCode: string;
|
|
39
|
+
copied: string;
|
|
40
|
+
pendingAction: string;
|
|
41
|
+
dismissAction: string;
|
|
42
|
+
actionDismissed: string;
|
|
43
|
+
actionFailed: string;
|
|
44
|
+
clipboardUnavailable: string;
|
|
45
|
+
transcript: string;
|
|
46
|
+
attachments: string;
|
|
47
|
+
attachFiles: string;
|
|
48
|
+
attachFilesHint: string;
|
|
49
|
+
removeAttachment: string;
|
|
50
|
+
attachmentPreparing: string;
|
|
51
|
+
attachmentsPreparing: string;
|
|
52
|
+
attachmentReadFailed: string;
|
|
53
|
+
attachmentsWhileBusy: string;
|
|
54
|
+
tooManyAttachments: string;
|
|
55
|
+
attachmentsTooLarge: string;
|
|
56
|
+
attachmentUnsupported: string;
|
|
57
|
+
attachmentUnsupportedByModel: string;
|
|
58
|
+
attachmentKindImage: string;
|
|
59
|
+
attachmentKindVideo: string;
|
|
60
|
+
attachmentKindPdf: string;
|
|
61
|
+
notSent: string;
|
|
62
|
+
notSentAttachments: string;
|
|
63
|
+
insertUnsent: string;
|
|
38
64
|
}
|
|
65
|
+
export declare const fillText: (text: string, values: Record<string, string | number>) => string;
|
|
39
66
|
export declare const defaultTexts: ChatTexts;
|
package/timestamps.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { TimestampOptions } from "./options";
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function timestampDay(date: Date,
|
|
5
|
-
|
|
2
|
+
export declare function messageDate(at: string | undefined): Date | undefined;
|
|
3
|
+
export declare function timestampLabel(date: Date, options?: TimestampOptions, now?: number): string;
|
|
4
|
+
export declare function timestampDay(date: Date, options?: TimestampOptions): {
|
|
5
|
+
key: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
package/types.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import type { Message } from "./events";
|
|
2
|
-
export type { Role, ToolInfo,
|
|
2
|
+
export type { Role, ToolInfo, PendingAction, Message, ChatEvent, ChatTextCursor, ChatJournalCursor, ChatAttachment, ChatAttachmentInput, ChatAttachmentCapabilities, ChatStartupStatus } from "./events";
|
|
3
3
|
export { applyEvent, prettyJson, compactToolLine } from "./events";
|
|
4
4
|
/**
|
|
5
|
-
* off = nur Antworten, icons = Schritte als reine Symbole nebeneinander,
|
|
5
|
+
* current = nur der laufende Schritt, off = nur Antworten, icons = Schritte als reine Symbole nebeneinander,
|
|
6
6
|
* chips = Schritte als Symbol + Kurztext nebeneinander (mit Umbruch),
|
|
7
|
-
* grouped = aufeinanderfolgende Schritte
|
|
7
|
+
* grouped = aufeinanderfolgende Schritte als eine aufklappbare Zeile, dahinter einzeilig,
|
|
8
8
|
* compact = Denken und Werkzeuge einzeilig, full = alles ausgeklappt.
|
|
9
9
|
*/
|
|
10
|
-
export type DetailMode = "off" | "icons" | "chips" | "grouped" | "compact" | "full";
|
|
10
|
+
export type DetailMode = "off" | "current" | "icons" | "chips" | "grouped" | "compact" | "full";
|
|
11
11
|
/** running = call still open, thinking = thought block still open, done = finished, error = failed. */
|
|
12
12
|
export type StepState = "running" | "thinking" | "done" | "error";
|
|
13
13
|
/** The single derivation of a step state, so chips, hosts and tests read the same signal. */
|
|
14
14
|
export declare function stepState(message: Message): StepState;
|
|
15
|
-
/** A moment worth one screen reader announcement: a finished reply or a new
|
|
15
|
+
/** A moment worth one screen reader announcement: a finished reply or a new pending action. */
|
|
16
16
|
export type ChatAnnouncement = {
|
|
17
17
|
kind: "reply";
|
|
18
18
|
message: Message;
|
|
19
19
|
} | {
|
|
20
|
-
kind: "
|
|
20
|
+
kind: "action";
|
|
21
21
|
message: Message;
|
|
22
22
|
};
|
package/ui/button.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
|
|
5
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Button({ className, variant, size, ...props }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>): import("react").JSX.Element;
|
|
8
|
+
export { Button, buttonVariants };
|
package/ui/card.d.ts
ADDED
package/ui/cn.d.ts
ADDED
package/ui/popover.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
|
|
2
|
+
declare function Popover({ ...props }: PopoverPrimitive.Root.Props): import("react").JSX.Element;
|
|
3
|
+
declare function PopoverContent({ className, align, alignOffset, side, sideOffset, anchor, collisionPadding, keepMounted, ...props }: PopoverPrimitive.Popup.Props & Pick<PopoverPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "anchor" | "collisionPadding"> & Pick<PopoverPrimitive.Portal.Props, "keepMounted">): import("react").JSX.Element;
|
|
4
|
+
export { Popover, PopoverContent };
|
package/ui/spinner.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SquareIcon } from "lucide-react";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
import { Button } from "./button";
|
|
4
|
+
/** Die eine Stopp-Glyphe: ein gefülltes rotes Quadrat; ein Zustandssymbol trägt sie nie. */
|
|
5
|
+
export declare function StopGlyph({ className, ...props }: Omit<ComponentProps<typeof SquareIcon>, "fill">): import("react").JSX.Element;
|
|
6
|
+
/** Jeder Stopp-Knopf sieht gleich aus: die Glyphe als Symbol, das Wort im Tooltip, rot in Ruhe und beim Hover. */
|
|
7
|
+
export declare function StopButton({ label, busy, className, title, ...props }: Omit<ComponentProps<typeof Button>, "children" | "variant"> & {
|
|
8
|
+
label: string;
|
|
9
|
+
busy?: boolean;
|
|
10
|
+
}): import("react").JSX.Element;
|
package/ui/toggle.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const toggleVariants: (props?: ({
|
|
4
|
+
variant?: "default" | "outline" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Toggle({ className, variant, size, ...props }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>): import("react").JSX.Element;
|
|
8
|
+
export { Toggle, toggleVariants };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ChangeEvent, type ClipboardEvent, type DragEvent } from "react";
|
|
2
|
+
export declare function useFileInput({ disabled, onFiles, onPasteText }: {
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
onFiles: (files: File[]) => void | Promise<void>;
|
|
5
|
+
onPasteText?: (text: string) => void;
|
|
6
|
+
}): {
|
|
7
|
+
inputRef: import("react").RefObject<HTMLInputElement | null>;
|
|
8
|
+
dragging: boolean;
|
|
9
|
+
clearDragging: () => void;
|
|
10
|
+
inputProps: {
|
|
11
|
+
ref: import("react").RefObject<HTMLInputElement | null>;
|
|
12
|
+
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
13
|
+
};
|
|
14
|
+
dropProps: {
|
|
15
|
+
onDragOver: (event: DragEvent<HTMLElement>) => void;
|
|
16
|
+
onDragLeave: (event: DragEvent<HTMLElement>) => void;
|
|
17
|
+
onDrop: (event: DragEvent<HTMLElement>) => void;
|
|
18
|
+
onPaste: (event: ClipboardEvent<HTMLElement>) => void;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function useChatAction(): {
|
|
2
|
+
status: "done" | "idle" | "pending";
|
|
3
|
+
error: string | undefined;
|
|
4
|
+
invoke: (action: () => void | Promise<void>, failureLabel: string) => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export declare function copyChatText(text: string, unavailable: string): Promise<void>;
|
package/QuestionCard.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Question } from "./types";
|
|
2
|
-
import type { ChatTexts } from "./texts";
|
|
3
|
-
/**
|
|
4
|
-
* Rückfrage-Karte: Optionen untereinander, wahlweise Einzel- oder Mehrfachauswahl
|
|
5
|
-
* (question.multi), dazu immer eine freie Antwortzeile. Nach der Antwort nur noch Beleg.
|
|
6
|
-
*/
|
|
7
|
-
export declare function QuestionCard({ text, question, texts, onAnswer, }: {
|
|
8
|
-
text: string;
|
|
9
|
-
question: Question;
|
|
10
|
-
texts: ChatTexts;
|
|
11
|
-
onAnswer: (text: string) => void;
|
|
12
|
-
}): import("react").JSX.Element;
|
package/chunk-DOLTANTM.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// packages/quassel/src/events.ts
|
|
2
|
-
function closeLast(messages) {
|
|
3
|
-
const last = messages[messages.length - 1];
|
|
4
|
-
if (!last || last.closed) {
|
|
5
|
-
return messages;
|
|
6
|
-
}
|
|
7
|
-
return [...messages.slice(0, -1), { ...last, closed: true }];
|
|
8
|
-
}
|
|
9
|
-
function appendDelta(messages, role, delta, at) {
|
|
10
|
-
const last = messages[messages.length - 1];
|
|
11
|
-
if (last && last.role === role && !last.closed) {
|
|
12
|
-
return [...messages.slice(0, -1), { ...last, text: last.text + delta }];
|
|
13
|
-
}
|
|
14
|
-
return [...closeLast(messages), { key: crypto.randomUUID(), role, text: delta, at }];
|
|
15
|
-
}
|
|
16
|
-
function applyEvent(messages, event) {
|
|
17
|
-
switch (event.kind) {
|
|
18
|
-
case "reset":
|
|
19
|
-
return [];
|
|
20
|
-
case "user":
|
|
21
|
-
return [...closeLast(messages), { key: crypto.randomUUID(), role: "user", text: event.text, at: event.at }];
|
|
22
|
-
case "text":
|
|
23
|
-
return appendDelta(messages, "assistant", event.delta, event.at);
|
|
24
|
-
case "thinking":
|
|
25
|
-
return appendDelta(messages, "thinking", event.delta, event.at);
|
|
26
|
-
case "tool":
|
|
27
|
-
return [
|
|
28
|
-
...closeLast(messages),
|
|
29
|
-
{
|
|
30
|
-
key: crypto.randomUUID(),
|
|
31
|
-
role: "tool",
|
|
32
|
-
text: event.label ?? event.name,
|
|
33
|
-
closed: true,
|
|
34
|
-
tool: { id: event.id, name: event.name, arguments: event.arguments },
|
|
35
|
-
at: event.at
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
case "tool-result":
|
|
39
|
-
return messages.map(
|
|
40
|
-
(message) => message.tool?.id === event.id ? { ...message, tool: { ...message.tool, result: event.result, isError: event.isError } } : message
|
|
41
|
-
);
|
|
42
|
-
case "question":
|
|
43
|
-
return [
|
|
44
|
-
...closeLast(messages),
|
|
45
|
-
{
|
|
46
|
-
key: crypto.randomUUID(),
|
|
47
|
-
role: "question",
|
|
48
|
-
text: event.text,
|
|
49
|
-
closed: true,
|
|
50
|
-
question: { callId: event.callId, options: event.options, multi: event.multi },
|
|
51
|
-
at: event.at
|
|
52
|
-
}
|
|
53
|
-
];
|
|
54
|
-
case "question-answered":
|
|
55
|
-
return messages.map(
|
|
56
|
-
(message) => message.question?.callId === event.callId ? { ...message, question: { ...message.question, answer: event.answer } } : message
|
|
57
|
-
);
|
|
58
|
-
case "system":
|
|
59
|
-
return [...closeLast(messages), { key: crypto.randomUUID(), role: "system", text: event.text, closed: true, at: event.at }];
|
|
60
|
-
case "turn-done":
|
|
61
|
-
return closeLast(messages);
|
|
62
|
-
default:
|
|
63
|
-
return messages;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function prettyJson(value) {
|
|
67
|
-
try {
|
|
68
|
-
return JSON.stringify(JSON.parse(value), null, 2);
|
|
69
|
-
} catch {
|
|
70
|
-
return value;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function compactToolLine(tool) {
|
|
74
|
-
const args = tool.arguments.replace(/\s+/g, " ").trim();
|
|
75
|
-
const line = args && args !== "{}" ? `${tool.name} ${args}` : tool.name;
|
|
76
|
-
return line.length > 160 ? `${line.slice(0, 160)} ...` : line;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export {
|
|
80
|
-
applyEvent,
|
|
81
|
-
prettyJson,
|
|
82
|
-
compactToolLine
|
|
83
|
-
};
|
|
84
|
-
//# sourceMappingURL=chunk-DOLTANTM.js.map
|
package/chunk-DOLTANTM.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/events.ts"],
|
|
4
|
-
"sourcesContent": ["export type Role = \"user\" | \"assistant\" | \"thinking\" | \"tool\" | \"system\" | \"question\";\n\nexport interface ToolInfo {\n id: string;\n name: string;\n arguments: string;\n result?: string;\n isError?: boolean;\n}\n\n/** Eine R\u00FCckfrage des Assistenten. `answer` gesetzt hei\u00DFt: beantwortet, die Karte ist nur noch Beleg. */\nexport interface Question {\n callId: string;\n options: string[];\n multi?: boolean;\n answer?: string;\n}\n\nexport interface Message {\n key: string;\n role: Role;\n text: string;\n closed?: boolean;\n tool?: ToolInfo;\n question?: Question;\n /** ISO-Zeitpunkt der Nachricht; Anzeige optional (ChatMessages showTimestamps). */\n at?: string;\n /** Farbige Sprechblase statt Fliesstext, z.B. fuer Mehrparteien-Gespraeche. */\n bubble?: { color: string; side: \"start\" | \"end\"; label?: string };\n}\n\nexport type ChatEvent =\n | { kind: \"reset\" }\n | { kind: \"user\"; text: string; at?: string }\n | { kind: \"text\"; delta: string; at?: string }\n | { kind: \"thinking\"; delta: string; at?: string }\n | { kind: \"tool\"; id: string; name: string; arguments: string; label?: string; at?: string }\n | { kind: \"tool-result\"; id: string; result: string; isError?: boolean }\n | { kind: \"question\"; callId: string; text: string; options: string[]; multi?: boolean; at?: string }\n | { kind: \"question-answered\"; callId: string; answer: string }\n | { kind: \"system\"; text: string; at?: string }\n | { kind: \"status\"; running: boolean }\n | { kind: \"turn-done\" }\n | { kind: \"extension\"; pluginId: string; type: string; payload?: unknown; at?: string };\n\nfunction closeLast(messages: Message[]): Message[] {\n const last = messages[messages.length - 1];\n if (!last || last.closed) {\n return messages;\n }\n return [...messages.slice(0, -1), { ...last, closed: true }];\n}\n\nfunction appendDelta(messages: Message[], role: Role, delta: string, at?: string): Message[] {\n const last = messages[messages.length - 1];\n if (last && last.role === role && !last.closed) {\n return [...messages.slice(0, -1), { ...last, text: last.text + delta }];\n }\n return [...closeLast(messages), { key: crypto.randomUUID(), role, text: delta, at }];\n}\n\n/** Der Streaming-Kern: Deltas verschmelzen mit dem letzten offenen Block, alles andere schlie\u00DFt ihn. */\nexport function applyEvent(messages: Message[], event: ChatEvent): Message[] {\n switch (event.kind) {\n case \"reset\":\n return [];\n case \"user\":\n return [...closeLast(messages), { key: crypto.randomUUID(), role: \"user\", text: event.text, at: event.at }];\n case \"text\":\n return appendDelta(messages, \"assistant\", event.delta, event.at);\n case \"thinking\":\n return appendDelta(messages, \"thinking\", event.delta, event.at);\n case \"tool\":\n return [\n ...closeLast(messages),\n {\n key: crypto.randomUUID(),\n role: \"tool\",\n text: event.label ?? event.name,\n closed: true,\n tool: { id: event.id, name: event.name, arguments: event.arguments },\n at: event.at,\n },\n ];\n case \"tool-result\":\n return messages.map((message) =>\n message.tool?.id === event.id\n ? { ...message, tool: { ...message.tool, result: event.result, isError: event.isError } }\n : message,\n );\n case \"question\":\n return [\n ...closeLast(messages),\n {\n key: crypto.randomUUID(),\n role: \"question\",\n text: event.text,\n closed: true,\n question: { callId: event.callId, options: event.options, multi: event.multi },\n at: event.at,\n },\n ];\n case \"question-answered\":\n return messages.map((message) =>\n message.question?.callId === event.callId\n ? { ...message, question: { ...message.question, answer: event.answer } }\n : message,\n );\n case \"system\":\n return [...closeLast(messages), { key: crypto.randomUUID(), role: \"system\", text: event.text, closed: true, at: event.at }];\n case \"turn-done\":\n return closeLast(messages);\n default:\n return messages;\n }\n}\n\nexport function prettyJson(value: string): string {\n try {\n return JSON.stringify(JSON.parse(value), null, 2);\n } catch {\n return value;\n }\n}\n\nexport function compactToolLine(tool: ToolInfo): string {\n const args = tool.arguments.replace(/\\s+/g, \" \").trim();\n const line = args && args !== \"{}\" ? `${tool.name} ${args}` : tool.name;\n return line.length > 160 ? `${line.slice(0, 160)} ...` : line;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|