@springbrand/message-panel 0.1.3-alpha.1 → 0.1.3-alpha.3
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/cloud-os/README.md +71 -0
- package/cloud-os/chat/activity-indicator.tsx +29 -0
- package/cloud-os/chat/cloud-os-chat-messages.tsx +632 -0
- package/cloud-os/chat/markdown-message.tsx +78 -0
- package/cloud-os/chat/rich-blocks.tsx +672 -0
- package/cloud-os/chat/tool-presentation.ts +584 -0
- package/cloud-os/chat/tool-rows.tsx +216 -0
- package/cloud-os/chat/transcript-model.ts +672 -0
- package/cloud-os/composer/cloud-os-chat-input.tsx +541 -0
- package/cloud-os/index.ts +107 -0
- package/cloud-os/internal/cn.ts +6 -0
- package/cloud-os/internal/theme-context.tsx +16 -0
- package/cloud-os/layout/cloud-os-root.tsx +34 -0
- package/cloud-os/layout/cloud-os-workspace-split.tsx +242 -0
- package/cloud-os/primitives/dropdown-menu.tsx +82 -0
- package/cloud-os/primitives/tooltip.tsx +68 -0
- package/cloud-os/primitives/workshop-controls.tsx +114 -0
- package/cloud-os/styles/cloud-os.css +573 -0
- package/cloud-os/workspace/cloud-os-workspace-panel.tsx +272 -0
- package/demo/camel-chat-showcase.tsx +13 -917
- package/demo/chat-scenarios.ts +926 -0
- package/demo/cloud-os-chat-showcase.tsx +471 -0
- package/demo/index.ts +2 -0
- package/package.json +16 -4
- package/src/camel/camel-chat-messages.tsx +41 -18
- package/src/camel/camel-prompt-input.tsx +2 -1
- package/src/chat-summary-panel.tsx +1 -1
- package/src/composer/chat-composer.tsx +2 -1
- package/src/composer/composer.tsx +2 -1
- package/src/composer/index.ts +1 -0
- package/src/composer/key-rules.ts +12 -0
- package/src/message.tsx +0 -8
- package/src/styles/index.css +4 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { CaretRight } from "@phosphor-icons/react";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { MarkdownMessage } from "./markdown-message";
|
|
4
|
+
import {
|
|
5
|
+
getToolCallSummary,
|
|
6
|
+
getToolIcon,
|
|
7
|
+
normalizeOutputText,
|
|
8
|
+
safeStringify,
|
|
9
|
+
type CloudOsToolCall,
|
|
10
|
+
type PhosphorIcon,
|
|
11
|
+
type ToolCallGroup,
|
|
12
|
+
} from "./tool-presentation";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 工作行(work rows)。整块从 cloudflare-os-main 的 ChatInterface.tsx 拷来:
|
|
16
|
+
* WorkIcon / ToolCallDetails / NestedToolCallRow / ToolGroupRow / ThinkingTraceRow。
|
|
17
|
+
* className 一个字没改;改的只有取数——从 gadgets 的 AiToolCall 换成
|
|
18
|
+
* UIMessage 归一化后的 CloudOsToolCall。
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export function WorkIcon({ Icon }: { Icon: PhosphorIcon }) {
|
|
22
|
+
return <Icon size={15} className="text-kumo-inactive" />;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function OutputPre({ label, value }: { label?: string; value: string }) {
|
|
26
|
+
if (!value) return null;
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
{label && (
|
|
30
|
+
<span className="font-mono text-[11px] leading-4 text-kumo-inactive uppercase tracking-[0.08em]">
|
|
31
|
+
{label}
|
|
32
|
+
</span>
|
|
33
|
+
)}
|
|
34
|
+
<pre className="max-h-56 overflow-auto rounded-xl border border-kumo-line/70 bg-kumo-base p-3 font-mono text-[12px] leading-[18px] text-kumo-subtle whitespace-pre-wrap">
|
|
35
|
+
{value}
|
|
36
|
+
</pre>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const ToolCallDetails = memo(function ToolCallDetails({
|
|
42
|
+
toolCall: tc,
|
|
43
|
+
}: {
|
|
44
|
+
toolCall: CloudOsToolCall;
|
|
45
|
+
}) {
|
|
46
|
+
const code =
|
|
47
|
+
typeof tc.input.code === "string"
|
|
48
|
+
? tc.input.code
|
|
49
|
+
: typeof tc.input.command === "string"
|
|
50
|
+
? tc.input.command
|
|
51
|
+
: "";
|
|
52
|
+
const inputText =
|
|
53
|
+
Object.keys(tc.input).length > 0 ? safeStringify(tc.input) : "";
|
|
54
|
+
return (
|
|
55
|
+
<div className="space-y-2">
|
|
56
|
+
{tc.errorText && (
|
|
57
|
+
<pre className="rounded-xl border border-kumo-danger/20 bg-kumo-danger-tint/40 p-3 font-mono text-[12px] leading-[18px] text-kumo-danger whitespace-pre-wrap">
|
|
58
|
+
{tc.errorText}
|
|
59
|
+
</pre>
|
|
60
|
+
)}
|
|
61
|
+
{code ? (
|
|
62
|
+
<>
|
|
63
|
+
<OutputPre label="Code" value={code} />
|
|
64
|
+
<OutputPre label="Output" value={tc.outputText} />
|
|
65
|
+
</>
|
|
66
|
+
) : (
|
|
67
|
+
<>
|
|
68
|
+
<OutputPre value={inputText} />
|
|
69
|
+
{tc.outputText && <OutputPre label="Output" value={tc.outputText} />}
|
|
70
|
+
</>
|
|
71
|
+
)}
|
|
72
|
+
{!code && !inputText && !tc.outputText && !tc.errorText && (
|
|
73
|
+
<p className="m-0 text-[12px] leading-4 text-kumo-inactive">
|
|
74
|
+
No additional data
|
|
75
|
+
</p>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const NestedToolCallRow = memo(function NestedToolCallRow({
|
|
82
|
+
toolCall: tc,
|
|
83
|
+
open,
|
|
84
|
+
onToggle,
|
|
85
|
+
}: {
|
|
86
|
+
toolCall: CloudOsToolCall;
|
|
87
|
+
open: boolean;
|
|
88
|
+
onToggle: (key: string) => void;
|
|
89
|
+
}) {
|
|
90
|
+
const key = `call-${tc.toolCallId}`;
|
|
91
|
+
const summary = getToolCallSummary(tc);
|
|
92
|
+
const label = `${summary.verb}${summary.target ? ` ${summary.target}` : ""}`;
|
|
93
|
+
const Icon = getToolIcon(tc.kind);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<div className="group/nested">
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
onClick={() => onToggle(key)}
|
|
100
|
+
className="flex w-full cursor-pointer items-center gap-3 rounded-xl px-1.5 py-1 text-left text-kumo-subtle transition-colors duration-150 ease-out hover:text-kumo-default focus-visible:text-kumo-default focus-visible:outline-none active:scale-[0.995]"
|
|
101
|
+
aria-expanded={open}
|
|
102
|
+
>
|
|
103
|
+
<span className="flex h-5 w-5 flex-shrink-0 items-center justify-center">
|
|
104
|
+
<WorkIcon Icon={Icon} />
|
|
105
|
+
</span>
|
|
106
|
+
<span className="flex min-w-0 flex-1 items-center gap-2 text-[14px] leading-5 tracking-[-0.25px]">
|
|
107
|
+
<span className="min-w-0 truncate">{label}</span>
|
|
108
|
+
{tc.failed && (
|
|
109
|
+
<span className="flex-shrink-0 rounded-full bg-kumo-danger-tint px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.04em] text-kumo-danger">
|
|
110
|
+
Error
|
|
111
|
+
</span>
|
|
112
|
+
)}
|
|
113
|
+
<CaretRight
|
|
114
|
+
size={13}
|
|
115
|
+
weight="bold"
|
|
116
|
+
className={`flex-shrink-0 text-kumo-inactive transition-transform duration-150 ease-out ${open ? "rotate-90" : ""}`}
|
|
117
|
+
/>
|
|
118
|
+
</span>
|
|
119
|
+
</button>
|
|
120
|
+
{open && (
|
|
121
|
+
<div className="themed-surface-inset ml-8 mt-1 space-y-3 rounded-2xl border border-kumo-line/70 bg-kumo-elevated/45 p-3">
|
|
122
|
+
<ToolCallDetails toolCall={tc} />
|
|
123
|
+
</div>
|
|
124
|
+
)}
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export const ThinkingTraceRow = memo(function ThinkingTraceRow({
|
|
130
|
+
reasoning,
|
|
131
|
+
}: {
|
|
132
|
+
reasoning: string;
|
|
133
|
+
}) {
|
|
134
|
+
return (
|
|
135
|
+
<div className="min-w-0 py-1 text-kumo-subtle">
|
|
136
|
+
<div className="cos-markdown min-w-0 text-[13px] leading-[19px]">
|
|
137
|
+
<MarkdownMessage message={reasoning} />
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const ToolGroupRow = memo(function ToolGroupRow({
|
|
144
|
+
group,
|
|
145
|
+
open,
|
|
146
|
+
expandedKeys,
|
|
147
|
+
onToggle,
|
|
148
|
+
}: {
|
|
149
|
+
group: ToolCallGroup;
|
|
150
|
+
open: boolean;
|
|
151
|
+
expandedKeys: ReadonlySet<string>;
|
|
152
|
+
onToggle: (key: string) => void;
|
|
153
|
+
}) {
|
|
154
|
+
return (
|
|
155
|
+
<div className="group -ml-0.5">
|
|
156
|
+
<button
|
|
157
|
+
type="button"
|
|
158
|
+
onClick={() => onToggle(group.key)}
|
|
159
|
+
className="flex w-full cursor-pointer items-center gap-3 rounded-xl px-1.5 py-1 text-left text-kumo-subtle transition-colors duration-150 ease-out hover:text-kumo-default focus-visible:text-kumo-default focus-visible:outline-none active:scale-[0.995]"
|
|
160
|
+
aria-expanded={open}
|
|
161
|
+
>
|
|
162
|
+
<span className="flex h-5 w-5 flex-shrink-0 items-center justify-center">
|
|
163
|
+
<WorkIcon Icon={group.Icon} />
|
|
164
|
+
</span>
|
|
165
|
+
<span className="min-w-0 flex-1">
|
|
166
|
+
<span className="flex min-w-0 items-center gap-2 text-[14px] leading-5 tracking-[-0.25px]">
|
|
167
|
+
<span
|
|
168
|
+
className={`min-w-0 truncate ${group.hasRunning ? "cos-thinking-shimmer" : ""}`}
|
|
169
|
+
>
|
|
170
|
+
{group.label}
|
|
171
|
+
</span>
|
|
172
|
+
{group.hasError && (
|
|
173
|
+
<span className="flex-shrink-0 rounded-full bg-kumo-danger-tint px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.04em] text-kumo-danger">
|
|
174
|
+
Error
|
|
175
|
+
</span>
|
|
176
|
+
)}
|
|
177
|
+
<CaretRight
|
|
178
|
+
size={13}
|
|
179
|
+
weight="bold"
|
|
180
|
+
className={`flex-shrink-0 text-kumo-inactive transition-transform duration-150 ease-out ${open ? "rotate-90" : ""}`}
|
|
181
|
+
/>
|
|
182
|
+
</span>
|
|
183
|
+
{group.detailLines.length > 1 && (
|
|
184
|
+
<span className="mt-1 block truncate font-mono text-[12px] leading-4 text-kumo-inactive">
|
|
185
|
+
{group.detailLines.join(" · ")}
|
|
186
|
+
</span>
|
|
187
|
+
)}
|
|
188
|
+
</span>
|
|
189
|
+
</button>
|
|
190
|
+
{open &&
|
|
191
|
+
(group.calls.length === 1 ? (
|
|
192
|
+
<div className="themed-surface-inset ml-8 mt-1 space-y-3 rounded-2xl border border-kumo-line/70 bg-kumo-elevated/45 p-3">
|
|
193
|
+
<ToolCallDetails toolCall={group.calls[0]} />
|
|
194
|
+
</div>
|
|
195
|
+
) : (
|
|
196
|
+
<div className="ml-8 mt-1 space-y-1">
|
|
197
|
+
{group.calls.map((toolCall) => {
|
|
198
|
+
const key = `call-${toolCall.toolCallId}`;
|
|
199
|
+
return (
|
|
200
|
+
<NestedToolCallRow
|
|
201
|
+
key={toolCall.toolCallId}
|
|
202
|
+
toolCall={toolCall}
|
|
203
|
+
open={expandedKeys.has(key)}
|
|
204
|
+
onToggle={onToggle}
|
|
205
|
+
/>
|
|
206
|
+
);
|
|
207
|
+
})}
|
|
208
|
+
</div>
|
|
209
|
+
))}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
export function toolOutputSummary(call: CloudOsToolCall): string {
|
|
215
|
+
return normalizeOutputText(call.output);
|
|
216
|
+
}
|