-
+ {/* Composer notice */}
{composerNotice && (
-
+
-
{composerNotice.title}
-
{composerNotice.description}
+
{composerNotice.title}
+
{composerNotice.description}
- {onOpenSidebar && (
-
- )}
+
)}
- {/* Model capabilities ÔÇö floating above the pill */}
-
-
- In
-
-
-
- ┬À
-
- Out
-
-
-
-
- {/* The typing pill */}
-
-
-
-
-
+ {/* Queue badge */}
+ {messageQueue.length > 0 && (
+
+
+ {messageQueue.length} message{messageQueue.length > 1 ? 's' : ''} queued
+
+ )}
+ {/* Main input box */}
+
+ {!isInitialScreen && (
+
+ )}
-
- {/* Queue system */}
- {messageQueue.length > 0 && (
-
- {isQueueOpen && (
-
-
- Mensagens em espera
-
-
- {messageQueue.map((msg, index) => (
- -
- {msg}
-
-
- ))}
-
+
+
+
+
+
+
+
+
+
- )}
-
+
+
+ {showDebugTools && (
+
+ )}
+
setAgenticMode((value) => !value)} disabled={Boolean(composerNotice)} />
+
+ {generating ? (
+
+ ) : (
+
+ )}
+
- )}
+
-
+ )}
);
diff --git a/tauri-app/src/components/Icon.tsx b/tauri-app/src/components/Icon.tsx
new file mode 100644
index 0000000..e7d8175
--- /dev/null
+++ b/tauri-app/src/components/Icon.tsx
@@ -0,0 +1,38 @@
+import type { LucideProps } from "lucide-react";
+import {
+ AlertCircle,
+ CheckCircle,
+ CheckCircle2,
+ ChevronDown,
+ ChevronRight,
+ Circle,
+ Loader,
+ Loader2,
+ Minus,
+ XCircle,
+} from "lucide-react";
+
+const icons = {
+ AlertCircle,
+ CheckCircle,
+ CheckCircle2,
+ ChevronDown,
+ ChevronRight,
+ Circle,
+ Loader,
+ Loader2,
+ Minus,
+ XCircle,
+} as const;
+
+export type IconName = keyof typeof icons;
+export type IconProps = LucideProps & {
+ name: IconName;
+};
+
+export function Icon({ name, ...props }: IconProps) {
+ const Component = icons[name] ?? Circle;
+ return
;
+}
+
+export default Icon;
diff --git a/tauri-app/src/components/MessageBubble.css b/tauri-app/src/components/MessageBubble.css
index 675a568..1dcbdfb 100644
--- a/tauri-app/src/components/MessageBubble.css
+++ b/tauri-app/src/components/MessageBubble.css
@@ -162,6 +162,932 @@
padding: 13px 16px;
}
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text {
+ width: 100%;
+ max-width: min(100%, 72ch);
+ background: transparent;
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ color: var(--text);
+ overflow: visible;
+}
+
+/* ÔöÇÔöÇ Manus markdown ÔöÇÔöÇ */
+.manus-markdown {
+ font-family: var(--font-editorial);
+ font-size: 1rem;
+ line-height: 1.78;
+ color: rgba(244, 244, 245, 0.94);
+ letter-spacing: -0.01em;
+}
+
+.manus-markdown > :first-child { margin-top: 0; }
+.manus-markdown > :last-child { margin-bottom: 0; }
+
+.manus-markdown h1,
+.manus-markdown h2,
+.manus-markdown h3,
+.manus-markdown h4 {
+ font-family: var(--font-editorial);
+ font-weight: 560;
+ letter-spacing: -0.03em;
+ line-height: 1.18;
+ color: #fafafa;
+ margin: 1.2em 0 0.45em;
+}
+
+.manus-markdown h1 { font-size: clamp(1.65rem, 1.35rem + 0.9vw, 2.2rem); }
+.manus-markdown h2 { font-size: clamp(1.2rem, 1.1rem + 0.45vw, 1.45rem); }
+.manus-markdown h3 { font-size: 1.05rem; }
+
+.manus-markdown p { margin: 0.75em 0; color: rgba(228, 228, 231, 0.9); }
+
+.manus-markdown ul,
+.manus-markdown ol { margin: 0.9em 0; padding-left: 1.35rem; }
+.manus-markdown li { margin: 0.32rem 0; color: rgba(228, 228, 231, 0.88); }
+
+.manus-markdown blockquote {
+ margin: 1.1em 0;
+ border-left: 1px solid rgba(244, 244, 245, 0.14);
+ padding-left: 1rem;
+ color: rgba(212, 212, 216, 0.78);
+ font-style: normal;
+}
+
+.manus-markdown hr { margin: 1.35em 0; border: none; border-top: 1px solid rgba(244, 244, 245, 0.08); }
+
+.manus-markdown a { color: #dbeafe; text-decoration-color: rgba(219, 234, 254, 0.28); text-underline-offset: 0.18em; }
+
+.manus-markdown strong { color: #fcfcfd; font-weight: 620; }
+
+.manus-markdown code:not(.hljs) {
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ border-radius: 8px;
+ padding: 0.1rem 0.4rem;
+}
+
+.manus-markdown .code-block {
+ margin: 1.1rem 0;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 18px;
+ background: rgba(9, 9, 11, 0.88);
+}
+
+.manus-markdown .code-header {
+ background: rgba(255, 255, 255, 0.03);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.manus-markdown .copy-code-btn {
+ border-radius: 999px;
+ border-color: rgba(255, 255, 255, 0.09);
+ background: rgba(255, 255, 255, 0.03);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .msg-content,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .agent-final-response__content {
+ padding: 0;
+ font-family: var(--font-editorial);
+ font-size: 1rem;
+ line-height: 1.78;
+ color: rgba(244, 244, 245, 0.96);
+ letter-spacing: -0.01em;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .msg-content > :first-child,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .agent-final-response__content > :first-child {
+ margin-top: 0;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .msg-content > :last-child,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .agent-final-response__content > :last-child {
+ margin-bottom: 0;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h1,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h2,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h3,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h4,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h5,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h6 {
+ margin: 1.2em 0 0.45em;
+ color: #fafafa;
+ font-family: var(--font-editorial);
+ font-weight: 560;
+ letter-spacing: -0.03em;
+ line-height: 1.18;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h1 {
+ font-size: clamp(1.65rem, 1.35rem + 0.9vw, 2.2rem);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h2 {
+ font-size: clamp(1.2rem, 1.1rem + 0.45vw, 1.45rem);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text h3 {
+ font-size: 1.05rem;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text p {
+ margin: 0.75em 0;
+ color: rgba(228, 228, 231, 0.9);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text ul,
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text ol {
+ margin: 0.9em 0;
+ padding-left: 1.35rem;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text li {
+ margin: 0.32rem 0;
+ color: rgba(228, 228, 231, 0.88);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text blockquote {
+ margin: 1.1em 0;
+ border-left: 1px solid rgba(244, 244, 245, 0.14);
+ padding-left: 1rem;
+ color: rgba(212, 212, 216, 0.78);
+ font-style: normal;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text hr {
+ margin: 1.35em 0;
+ border: none;
+ border-top: 1px solid rgba(244, 244, 245, 0.08);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text a {
+ color: #dbeafe;
+ text-decoration-color: rgba(219, 234, 254, 0.28);
+ text-underline-offset: 0.18em;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text strong {
+ color: #fcfcfd;
+ font-weight: 620;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text code:not(.hljs) {
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ border-radius: 8px;
+ padding: 0.1rem 0.4rem;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .code-block {
+ margin: 1.1rem 0;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 18px;
+ background: rgba(9, 9, 11, 0.88);
+ box-shadow: none;
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .code-header {
+ background: rgba(255, 255, 255, 0.03);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.msg-wrapper.assistant .msg-bubble.msg-bubble--assistant-text .copy-code-btn {
+ border-radius: 999px;
+ border-color: rgba(255, 255, 255, 0.09);
+ background: rgba(255, 255, 255, 0.03);
+}
+
+.msg-inline-meta {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ margin-top: 14px;
+ min-height: 32px;
+}
+
+.msg-wrapper.assistant .message-metrics {
+ padding-left: 0;
+ font-size: 0.7rem;
+ color: rgba(161, 161, 170, 0.72);
+ font-family: var(--font-editorial);
+ gap: 10px;
+}
+
+.msg-actions--inline {
+ opacity: 0;
+ display: inline-flex;
+ align-items: center;
+ gap: 2px;
+ padding: 2px;
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.025);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ transition: opacity 0.2s ease-out, background 0.2s ease-out, border-color 0.2s ease-out;
+}
+
+.msg-wrapper.assistant:hover .msg-actions--inline,
+.msg-wrapper.assistant:focus-within .msg-actions--inline {
+ opacity: 1;
+}
+
+.msg-actions--inline .action-btn {
+ min-width: 34px;
+ min-height: 34px;
+ border: none;
+ border-radius: 999px;
+ padding: 0;
+ color: rgba(228, 228, 231, 0.7);
+}
+
+.msg-actions--inline .action-btn:hover {
+ background: rgba(255, 255, 255, 0.06);
+ color: #fafafa;
+}
+
+.msg-actions--inline .action-btn:focus-visible {
+ box-shadow: 0 0 0 2px rgba(75, 134, 255, 0.35);
+}
+
+.msg-actions--inline .action-btn.copied {
+ color: var(--success);
+ background: rgba(48, 209, 88, 0.1);
+}
+
+.msg-wrapper.assistant .msg-thinking {
+ margin-bottom: 14px;
+ border-bottom: none;
+}
+
+.msg-wrapper.assistant .reasoning-toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0;
+ background: transparent;
+ color: rgba(161, 161, 170, 0.8);
+ font-size: 0.72rem;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.14em;
+}
+
+.msg-wrapper.assistant .thinking-content {
+ padding: 10px 0 0;
+ color: rgba(212, 212, 216, 0.72);
+}
+
+.msg-wrapper.assistant .thinking-content > :first-child {
+ margin-left: 0;
+ padding-left: 12px;
+ border-left: 1px solid rgba(244, 244, 245, 0.08);
+}
+
+/* ÔöÇÔöÇ Minimalist Agentic plan ÔöÇÔöÇ */
+.agentic-plan {
+ display: flex;
+ flex-direction: column;
+}
+
+.agentic-plan__header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ color: var(--text);
+ text-align: left;
+ width: 100%;
+ font-family: inherit;
+}
+
+.agentic-plan__header:hover .agentic-plan__title {
+ color: var(--accent);
+}
+
+.agentic-plan__dot {
+ width: 7px;
+ height: 7px;
+ border-radius: 999px;
+ background: var(--accent);
+ box-shadow: 0 0 8px var(--accent-glow);
+ flex-shrink: 0;
+}
+
+.agentic-plan__title {
+ font-family: var(--font-editorial);
+ font-size: 0.82rem;
+ font-weight: 500;
+ color: rgba(244, 244, 245, 0.82);
+ letter-spacing: -0.005em;
+ transition: color 0.15s;
+}
+
+.agentic-plan__badge {
+ font-size: 0.6rem;
+ font-weight: 600;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: var(--text3);
+ border: 1px solid var(--border2);
+ border-radius: 999px;
+ padding: 1px 6px;
+ flex-shrink: 0;
+}
+
+.agentic-plan__counter {
+ font-size: 0.68rem;
+ color: var(--text3);
+ font-family: var(--font-editorial);
+ margin-left: auto;
+ flex-shrink: 0;
+}
+
+.agentic-plan__chevron {
+ width: 14px;
+ height: 14px;
+ color: var(--text3);
+ flex-shrink: 0;
+ transition: transform 0.2s ease-out;
+}
+
+.agentic-plan__chevron.rotated {
+ transform: rotate(180deg);
+}
+
+.agentic-plan__body {
+ padding-left: 15px;
+}
+
+.agentic-plan__overview {
+ margin: 6px 0 10px;
+ font-family: var(--font-editorial);
+ font-size: 0.82rem;
+ line-height: 1.6;
+ color: rgba(244, 244, 245, 0.5);
+}
+
+.agentic-steps {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.agentic-step {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+}
+
+.agentic-step__content {
+ min-width: 0;
+ flex: 1;
+}
+
+.agentic-step__title {
+ font-family: var(--font-editorial);
+ font-size: 0.84rem;
+ font-weight: 500;
+ color: rgba(244, 244, 245, 0.8);
+ line-height: 1.4;
+ margin: 0;
+}
+
+.agentic-step__desc {
+ margin: 2px 0 0;
+ font-size: 0.78rem;
+ line-height: 1.5;
+ color: rgba(244, 244, 245, 0.45);
+}
+
+.agentic-substeps {
+ list-style: none;
+ margin: 4px 0 0;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+}
+
+.agentic-substep {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 0.76rem;
+ color: rgba(244, 244, 245, 0.45);
+ font-family: var(--font-editorial);
+}
+
+.agentic-plan__prog {
+ margin-top: 10px;
+}
+
+.agentic-plan__prog-bar {
+ height: 2px;
+ background: var(--border);
+ border-radius: 999px;
+ overflow: hidden;
+}
+
+.agentic-plan__prog-fill {
+ height: 100%;
+ background: var(--accent);
+ border-radius: 999px;
+ transition: width 0.25s ease-out;
+}
+
+/* ÔöÇÔöÇ Agentic status dots ÔöÇÔöÇ */
+.agentic-dot {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ margin-top: 2px;
+}
+
+.agentic-dot--idle { color: var(--text3); }
+.agentic-dot--running { color: var(--accent); }
+.agentic-dot--done { color: var(--success); }
+.agentic-dot--error { color: var(--danger); }
+
+/* ÔöÇÔöÇ Agentic update (inline text) ÔöÇÔöÇ */
+.agentic-update {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-family: var(--font-editorial);
+ font-size: 0.8rem;
+ color: rgba(244, 244, 245, 0.48);
+ line-height: 1.5;
+}
+
+.agentic-update__icon {
+ flex-shrink: 0;
+ opacity: 0.7;
+}
+
+.agentic-update--success .agentic-update__icon { color: var(--success); opacity: 1; }
+.agentic-update--warning .agentic-update__icon { color: var(--warning); opacity: 1; }
+.agentic-update--error .agentic-update__icon { color: var(--danger); opacity: 1; }
+
+/* ÔöÇÔöÇ Specialist cards ÔöÇÔöÇ */
+.specialist-card {
+ display: flex;
+ flex-direction: column;
+ gap: 0;
+ padding: 12px 0;
+}
+
+.specialist-card__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+}
+
+.specialist-card__identity {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.specialist-card__dot {
+ width: 7px;
+ height: 7px;
+ border-radius: 999px;
+ background: var(--accent);
+ box-shadow: 0 0 8px var(--accent-glow);
+ flex-shrink: 0;
+}
+
+.specialist-card__name {
+ font-family: var(--font-editorial);
+ font-size: 0.84rem;
+ font-weight: 500;
+ color: rgba(244, 244, 245, 0.88);
+ letter-spacing: -0.005em;
+}
+
+.specialist-card__title {
+ font-family: var(--font-editorial);
+ font-size: 0.72rem;
+ color: rgba(244, 244, 245, 0.4);
+}
+
+.specialist-card__badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ font-size: 0.65rem;
+ font-weight: 600;
+ letter-spacing: 0.1em;
+ text-transform: uppercase;
+ padding: 2px 7px;
+ border-radius: 999px;
+}
+
+.specialist-card__badge--thinking {
+ color: var(--accent);
+ background: rgba(72, 166, 255, 0.08);
+ border: 1px solid rgba(72, 166, 255, 0.2);
+}
+
+.specialist-card__badge--done {
+ color: var(--success);
+ background: rgba(48, 209, 88, 0.08);
+ border: 1px solid rgba(48, 209, 88, 0.2);
+}
+
+.specialist-card__thinking-section {
+ margin-top: 8px;
+}
+
+.specialist-card__thinking-toggle {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ background: none;
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ font-family: var(--font-editorial);
+ font-size: 0.72rem;
+ font-weight: 500;
+ color: rgba(244, 244, 245, 0.38);
+ letter-spacing: 0.04em;
+ transition: color 0.15s;
+}
+
+.specialist-card__thinking-toggle:hover {
+ color: rgba(244, 244, 245, 0.65);
+}
+
+.specialist-card__chevron {
+ width: 12px;
+ height: 12px;
+ transition: transform 0.18s ease-out;
+ flex-shrink: 0;
+}
+
+.specialist-card__chevron.rotated {
+ transform: rotate(180deg);
+}
+
+.specialist-card__thinking-preview {
+ margin: 5px 0 0;
+ font-family: var(--font-editorial);
+ font-size: 0.76rem;
+ line-height: 1.5;
+ color: rgba(244, 244, 245, 0.32);
+ font-style: italic;
+}
+
+.specialist-card__thinking-body {
+ margin-top: 6px;
+}
+
+.specialist-card__thinking-text {
+ font-family: var(--font-editorial);
+ font-size: 0.8rem;
+ line-height: 1.65;
+ color: rgba(228, 228, 231, 0.6);
+ border-left: 1px solid rgba(244, 244, 245, 0.08);
+ padding-left: 12px;
+ margin: 0;
+}
+
+.specialist-card__response {
+ margin-top: 8px;
+}
+
+.specialist-card__response-text {
+ font-family: var(--font-editorial);
+ font-size: 0.88rem;
+ line-height: 1.72;
+ color: rgba(228, 228, 231, 0.88);
+ margin: 0;
+}
+
+.specialist-card__divider {
+ margin-top: 12px;
+ height: 1px;
+ background: rgba(244, 244, 245, 0.05);
+}
+
+/* ÔöÇÔöÇ Agentic artifact row ÔöÇÔöÇ */
+.agentic-artifact {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 8px 12px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ background: var(--bg2);
+ margin-top: 12px;
+ transition: background 0.15s;
+}
+
+.agentic-artifact:hover {
+ background: var(--bg3);
+}
+
+.agentic-artifact__icon {
+ flex-shrink: 0;
+ color: var(--accent);
+}
+
+.agentic-artifact__info {
+ min-width: 0;
+ flex: 1;
+}
+
+.agentic-artifact__name {
+ font-size: 0.82rem;
+ font-weight: 500;
+ color: var(--text);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.agentic-artifact__meta {
+ font-size: 0.7rem;
+ color: var(--text3);
+ margin-top: 1px;
+}
+
+.agentic-artifact__btn {
+ flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ padding: 5px 10px;
+ background: var(--bg3);
+ border: 1px solid var(--border2);
+ border-radius: var(--radius-sm);
+ color: var(--text2);
+ font-size: 0.72rem;
+ font-family: var(--font-sans);
+ cursor: pointer;
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
+}
+
+.agentic-artifact__btn:hover {
+ background: var(--bg4);
+ color: var(--text);
+ border-color: var(--accent);
+}
+
+.forgeagent-shell__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+
+.forgeagent-shell__label {
+ font-size: 0.76rem;
+ font-weight: 600;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: rgba(228, 228, 231, 0.92);
+}
+
+.forgeagent-shell__status {
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 999px;
+ padding: 4px 10px;
+ font-size: 0.68rem;
+ font-weight: 500;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: rgba(161, 161, 170, 0.84);
+ background: rgba(24, 24, 27, 0.74);
+}
+
+.forgeagent-card {
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ border-radius: 20px;
+ background: rgba(15, 23, 42, 0.34);
+ padding: 14px 16px;
+}
+
+.forgeagent-card__eyebrow {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 0.68rem;
+ font-weight: 600;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: rgba(161, 161, 170, 0.8);
+}
+
+.forgeagent-card__dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 999px;
+ background: #60a5fa;
+ box-shadow: 0 0 12px rgba(96, 165, 250, 0.45);
+}
+
+.forgeagent-card__title-row {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 12px;
+ margin-top: 8px;
+}
+
+.forgeagent-card__title {
+ margin: 0;
+ font-size: 1rem;
+ font-weight: 600;
+ line-height: 1.35;
+ color: #fafafa;
+}
+
+.forgeagent-card__progress {
+ flex-shrink: 0;
+ font-size: 0.75rem;
+ color: rgba(212, 212, 216, 0.72);
+}
+
+.forgeagent-card__overview {
+ margin: 6px 0 0;
+ font-size: 0.88rem;
+ line-height: 1.55;
+ color: rgba(212, 212, 216, 0.76);
+}
+
+.forgeagent-progress {
+ margin-top: 12px;
+ height: 5px;
+ overflow: hidden;
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.06);
+}
+
+.forgeagent-progress__bar {
+ height: 100%;
+ border-radius: 999px;
+ background: linear-gradient(90deg, rgba(226, 232, 240, 0.95), rgba(148, 163, 184, 0.92));
+ transition: width 0.2s ease-out;
+}
+
+.forgeagent-steps {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.forgeagent-steps--compact {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.forgeagent-step {
+ display: flex;
+ gap: 10px;
+ align-items: flex-start;
+}
+
+.forgeagent-step__marker {
+ flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ margin-top: 1px;
+ border-radius: 999px;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ background: rgba(9, 9, 11, 0.72);
+ font-size: 0.68rem;
+ color: rgba(161, 161, 170, 0.82);
+}
+
+.forgeagent-step.is-complete .forgeagent-step__marker {
+ border-color: rgba(52, 211, 153, 0.24);
+ background: rgba(16, 185, 129, 0.1);
+ color: rgba(167, 243, 208, 0.96);
+}
+
+.forgeagent-step.is-active .forgeagent-step__marker {
+ border-color: rgba(96, 165, 250, 0.3);
+ background: rgba(59, 130, 246, 0.12);
+ color: rgba(191, 219, 254, 0.96);
+}
+
+.forgeagent-step__body {
+ min-width: 0;
+ flex: 1;
+}
+
+.forgeagent-step__row {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 10px;
+}
+
+.forgeagent-step__title {
+ font-size: 0.88rem;
+ font-weight: 500;
+ line-height: 1.4;
+ color: rgba(244, 244, 245, 0.92);
+}
+
+.forgeagent-step__status {
+ flex-shrink: 0;
+ font-size: 0.68rem;
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ color: rgba(161, 161, 170, 0.72);
+}
+
+.forgeagent-step__description,
+.forgeagent-step__substep {
+ margin-top: 4px;
+ font-size: 0.8rem;
+ line-height: 1.5;
+ color: rgba(161, 161, 170, 0.82);
+}
+
+.forgeagent-step__substeps {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ margin-top: 6px;
+}
+
+.forgeagent-updates {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.forgeagent-update {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+ padding: 0;
+ font-size: 0.82rem;
+ line-height: 1.5;
+ color: rgba(212, 212, 216, 0.8);
+}
+
+.forgeagent-update__dot {
+ width: 6px;
+ height: 6px;
+ margin-top: 0.45rem;
+ flex-shrink: 0;
+ border-radius: 999px;
+ background: rgba(161, 161, 170, 0.72);
+}
+
+.forgeagent-update--success .forgeagent-update__dot {
+ background: rgba(52, 211, 153, 0.92);
+}
+
+.forgeagent-update--warning .forgeagent-update__dot {
+ background: rgba(251, 191, 36, 0.92);
+}
+
+.forgeagent-update--error .forgeagent-update__dot {
+ background: rgba(251, 113, 133, 0.92);
+}
+
+.agent-final-response {
+ padding-top: 6px;
+}
+
+.agent-final-response__label {
+ margin-bottom: 10px;
+ font-size: 0.72rem;
+ font-weight: 600;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: rgba(161, 161, 170, 0.8);
+}
+
+.agent-final-response__artifact-label {
+ margin-bottom: 6px;
+ font-size: 0.68rem;
+ font-weight: 600;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: rgba(161, 161, 170, 0.7);
+}
+
/* ÔöÇÔöÇ Message metrics ÔöÇÔöÇ */
.message-metrics {
display: flex;
@@ -324,6 +1250,21 @@
.action-btn {
flex: 1 1 132px;
}
+
+ .msg-inline-meta {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .msg-actions--inline {
+ opacity: 1;
+ }
+
+ .msg-actions--inline .action-btn {
+ flex: 0 0 auto;
+ min-width: 40px;
+ min-height: 40px;
+ }
}
@media (prefers-reduced-motion: reduce) {
diff --git a/tauri-app/src/components/MessageBubble.test.tsx b/tauri-app/src/components/MessageBubble.test.tsx
index 5eb121a..856e769 100644
--- a/tauri-app/src/components/MessageBubble.test.tsx
+++ b/tauri-app/src/components/MessageBubble.test.tsx
@@ -69,4 +69,86 @@ describe("MessageBubble", () => {
expect(container.textContent).toContain("Total 42");
expect(container.textContent).toContain("6.4 tok/s");
});
+
+ it("renders a clean agentic final response without classic bubble chrome", async () => {
+ const message = {
+ id: 22,
+ chat_id: 5,
+ role: "assistant",
+ content: "Aqui está o guia final.",
+ created_at: Date.now(),
+ display_mode: "agentic_final",
+ } as Message;
+
+ await act(async () => {
+ root.render(
+
`${text}
`}
+ />,
+ );
+ });
+
+ expect(container.querySelector(".agent-final-response")).toBeTruthy();
+ expect(container.textContent).toContain("Aqui está o guia final.");
+ });
+
+ it("keeps forgeagent execution cards visible for persisted agentic messages", async () => {
+ const message = {
+ id: 31,
+ chat_id: 7,
+ role: "assistant",
+ content: "Aqui está a resposta final organizada.",
+ created_at: Date.now(),
+ display_mode: "agentic_final",
+ forgeagent_state: {
+ plan_id: "plan-7",
+ current_step: 3,
+ status: "completed",
+ progress: 100,
+ final_response: "Aqui está a resposta final organizada em formato Manus-style, pronta para revisão e entrega.",
+ artifact: {
+ filename: "forgeagent-output.md",
+ content: "# Resultado final\n\nPrompt original: testar o agentico",
+ language: "markdown",
+ cta_label: "Entregar o guia ao usuário",
+ },
+ system_messages: [
+ { id: "m1", step_id: 1, tone: "info", content: "Analisei a solicitação e defini o objetivo principal." },
+ { id: "m2", step_id: 2, tone: "info", content: "Estruturei a solução e organizei a execução em blocos claros." },
+ ],
+ plan: {
+ title: "Pesquise sobre a qualidade das pedras nas montanhas",
+ overview: "Vou estruturar um plano curto, executar cada etapa visualmente e entregar a resposta final no estilo ForgeAgent.",
+ steps: [
+ { id: 1, title: "Entender a solicitação", description: "Quebrar o pedido em objetivo, stack e formato de entrega.", status: "completed", sub_steps: [] },
+ { id: 2, title: "Preparar a solução", description: "Montar a estrutura, dependências e fluxo recomendado.", status: "completed", sub_steps: [] },
+ { id: 3, title: "Gerar a resposta final", description: "Entregar o conteúdo final com orientação prática e artefato.", status: "completed", sub_steps: [] },
+ ],
+ },
+ },
+ } as Message & { forgeagent_state: unknown };
+
+ await act(async () => {
+ root.render(
+ `${text}
`}
+ />,
+ );
+ });
+
+ expect(container.querySelector(".forgeagent-steps--compact")).toBeTruthy();
+ expect(container.textContent).toContain("Pesquise sobre a qualidade das pedras nas montanhas");
+ expect(container.textContent).toContain("Entender a solicitação");
+ expect(container.textContent).toContain("Analisei a solicitação e defini o objetivo principal.");
+ expect(container.textContent).toContain("forgeagent-output.md");
+ expect(container.textContent).toContain("Resposta final");
+ expect(container.textContent).toContain("Concluí a execução do pedido");
+ expect(container.textContent).not.toContain("pronta para revisão e entrega");
+ });
});
diff --git a/tauri-app/src/components/MessageBubble.tsx b/tauri-app/src/components/MessageBubble.tsx
index 02df8e6..4242fed 100644
--- a/tauri-app/src/components/MessageBubble.tsx
+++ b/tauri-app/src/components/MessageBubble.tsx
@@ -7,10 +7,11 @@ interface Props {
onDelete: (id: number) => void;
onEditAndResend?: (msg: Message, newContent: string) => void;
onEditAssistant?: (id: number, newContent: string) => void;
+ onResend?: (msg: Message) => void;
renderMarkdown: (text: string) => string;
}
-export default function MessageBubble({ message, onDelete, onEditAndResend, onEditAssistant, renderMarkdown }: Props) {
+export default function MessageBubble({ message, onDelete, onEditAndResend, onEditAssistant, onResend, renderMarkdown }: Props) {
const [editing, setEditing] = useState(false);
const [editValue, setEditValue] = useState(message.content);
const [copied, setCopied] = useState(false);
@@ -90,6 +91,7 @@ export default function MessageBubble({ message, onDelete, onEditAndResend, onEd
);
const showFooter = message.role === "assistant";
+ const assistantBubbleClass = "msg-bubble msg-bubble--assistant-text";
return (
@@ -122,7 +124,7 @@ export default function MessageBubble({ message, onDelete, onEditAndResend, onEd
{message.role === "assistant" ? (
{hasReasoning && (
@@ -141,12 +143,12 @@ export default function MessageBubble({ message, onDelete, onEditAndResend, onEd
)}
{showFooter && (
-
+
{hasUsage && (
Sent {message.prompt_tokens ?? 0}
@@ -156,13 +158,28 @@ export default function MessageBubble({ message, onDelete, onEditAndResend, onEd
)}
{!hasUsage &&
}
-
+
+ {onResend && (
+
+ )}