Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
27c62d6
feat(agent-blocks): add agent building block components
ogabrielluiz Dec 16, 2025
c45158d
feat(frontend): add agent_blocks category to sidebar
ogabrielluiz Dec 16, 2025
1e46c08
feat(unified_models): implement lazy loading for individual model cla…
ogabrielluiz Dec 16, 2025
fd466fa
refactor(chat): improve model name extraction logic in ChatComponent
ogabrielluiz Dec 16, 2025
c61ea42
feat(agent-graph): implement agent graph builder with execution context
ogabrielluiz Dec 16, 2025
dbca0f3
feat(agent-step): enhance streaming with immediate tool notifications…
ogabrielluiz Dec 16, 2025
ae34748
feat(component): enhance output processing logic to include grouped o…
ogabrielluiz Dec 16, 2025
6e1069a
feat(component): enhance message handling logic to prevent skipping i…
ogabrielluiz Dec 16, 2025
e28394c
feat(component): improve message event handling to ensure message ID …
ogabrielluiz Dec 16, 2025
31dfd7f
feat(component): prevent overwriting explicitly set parameters during…
ogabrielluiz Dec 16, 2025
c48735e
feat(tests): add integration tests for agent graph builder module
ogabrielluiz Dec 16, 2025
565249f
feat(component): update chat output/input checks to use base_name for…
ogabrielluiz Dec 16, 2025
e68cf54
feat(tests): add async test for state model with group outputs and co…
ogabrielluiz Dec 16, 2025
61c4f6e
feat(graph): preserve start_component_id during preparation in Graph …
ogabrielluiz Dec 16, 2025
7d4d385
feat(tests): add unit and integration tests for agent graph builder m…
ogabrielluiz Dec 16, 2025
6ed3aa4
feat(tests): update test cases to use FakeAgentStepComponent instead …
ogabrielluiz Dec 16, 2025
9cec18c
feat(chat): add clarification comments on message storage logic in Ch…
ogabrielluiz Dec 16, 2025
19d1d2e
feat(agent): add AgentLoopComponent to encapsulate complete agent loo…
ogabrielluiz Dec 16, 2025
3ab9c1a
tests: Adds contract tests for agent loop and events
ogabrielluiz Dec 16, 2025
97422bc
feat(dependencies): add langchain-openai to integration dependencies
ogabrielluiz Dec 16, 2025
69b55f5
fix: prevent double chunk aggregation in AgentStep streaming
ogabrielluiz Dec 17, 2025
0e9549e
feat(agent): enhance AgentLoopComponent with message history and cont…
ogabrielluiz Dec 17, 2025
4ad8c4d
refactor(agent): refactor run_agent method for improved structure and…
ogabrielluiz Dec 17, 2025
91a4b21
refactor(agent): remove agent graph builder and associated tests
ogabrielluiz Dec 18, 2025
a629b46
feat(graph): update GraphExecutionContext import and enhance its defi…
ogabrielluiz Dec 18, 2025
92a0333
feat(tests): add integration tests for agent graph execution and unit…
ogabrielluiz Dec 18, 2025
8a799ce
feat(agent): add SharedContextComponent for multi-agent collaboration
ogabrielluiz Dec 18, 2025
41c26f6
feat(tests): add integration and unit tests for SharedContextComponent
ogabrielluiz Dec 18, 2025
51f157e
feat(gitignore): add .claude to ignore list
ogabrielluiz Dec 26, 2025
2a2a4ad
fix(frontend): properly validate loop edges in cleanEdges and detectB…
ogabrielluiz Dec 26, 2025
633788a
feat(frontend): add shared context events display in chat
ogabrielluiz Dec 26, 2025
d519e33
fix(frontend): reorder imports for consistency in SharedContextEvents…
ogabrielluiz Dec 26, 2025
b2582f3
feat(loop): update LoopComponent to enhance execution flow and add ne…
ogabrielluiz Dec 26, 2025
e69fdb1
Merge feat/loop-subgraph into feat/agent-blocks
ogabrielluiz Jan 8, 2026
45ea79a
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 8, 2026
a81922c
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Jan 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { extractLanguage, isCodeBlock } from "@/utils/codeBlockUtils";
import ForwardedIconComponent from "../../common/genericIconComponent";
import SimplifiedCodeTabComponent from "../codeTabsComponent";
import DurationDisplay from "./DurationDisplay";
import { SharedContextEventsDisplay } from "./SharedContextEventsDisplay";

export default function ContentDisplay({
content,
Expand Down Expand Up @@ -267,6 +268,10 @@ export default function ContentDisplay({
</div>
);
break;

case "shared_context":
contentData = <SharedContextEventsDisplay events={content.events} />;
break;
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { AnimatePresence, motion } from "framer-motion";
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import { Badge } from "@/components/ui/badge";
import type { SharedContextEventData } from "@/types/chat";
import { cn } from "@/utils/utils";

interface SharedContextEventsDisplayProps {
events: SharedContextEventData[];
}

const OPERATION_CONFIG: Record<
SharedContextEventData["operation"],
{ color: string; bgColor: string; icon: string; label: string }
> = {
get: {
color: "text-blue-600 dark:text-blue-400",
bgColor: "bg-blue-500/20",
icon: "Eye",
label: "GET",
},
set: {
color: "text-green-600 dark:text-green-400",
bgColor: "bg-green-500/20",
icon: "Pencil",
label: "SET",
},
append: {
color: "text-yellow-600 dark:text-yellow-400",
bgColor: "bg-yellow-500/20",
icon: "Plus",
label: "APPEND",
},
delete: {
color: "text-red-600 dark:text-red-400",
bgColor: "bg-red-500/20",
icon: "Trash2",
label: "DELETE",
},
keys: {
color: "text-gray-600 dark:text-gray-400",
bgColor: "bg-gray-500/20",
icon: "List",
label: "KEYS",
},
has_key: {
color: "text-gray-600 dark:text-gray-400",
bgColor: "bg-gray-500/20",
icon: "Search",
label: "CHECK",
},
};

function formatTime(timestamp: string): string {
const date = new Date(timestamp);
return date.toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
}

export function SharedContextEventsDisplay({
events,
}: SharedContextEventsDisplayProps) {
if (!events?.length) {
return (
<div className="p-4 text-sm text-muted-foreground">
No shared context activity yet.
</div>
);
}

// Group by namespace
const groupedByNamespace = events.reduce(
(acc, event) => {
const ns = event.namespace || "default";
if (!acc[ns]) acc[ns] = [];
acc[ns].push(event);
return acc;
},
{} as Record<string, SharedContextEventData[]>,
);

return (
<div className="flex flex-col gap-2 p-4">
{Object.entries(groupedByNamespace).map(([namespace, nsEvents]) => (
<div key={namespace} className="flex flex-col gap-1">
{namespace !== "default" && (
<div className="mb-1 text-xs font-medium text-muted-foreground">
Namespace: {namespace}
</div>
)}

{/* Timeline */}
<div className="relative border-l-2 border-border pl-4">
<AnimatePresence>
{nsEvents.map((event, index) => {
const config = OPERATION_CONFIG[event.operation];
return (
<motion.div
key={`${event.timestamp}-${index}`}
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -10 }}
transition={{ duration: 0.2, delay: index * 0.05 }}
className="relative flex items-center gap-3 py-1.5"
>
{/* Timeline dot */}
<div
className={cn(
"absolute -left-[21px] h-2.5 w-2.5 rounded-full border-2 border-background",
config.bgColor,
)}
/>

{/* Operation badge */}
<Badge
variant="outline"
size="xq"
className={cn(
"min-w-[70px] justify-center",
config.bgColor,
config.color,
)}
>
<ForwardedIconComponent
name={config.icon}
className="mr-1 h-3 w-3"
/>
{config.label}
</Badge>

{/* Key name */}
<span className="font-mono text-sm text-foreground">
{event.key || "(all keys)"}
</span>

{/* Timestamp */}
<span className="ml-auto text-xs text-muted-foreground">
{formatTime(event.timestamp)}
</span>
</motion.div>
);
})}
</AnimatePresence>
</div>
</div>
))}

{/* Summary */}
<div className="mt-2 border-t border-border pt-2 text-xs text-muted-foreground">
{events.length} operation{events.length !== 1 ? "s" : ""} total
</div>
</div>
);
}
34 changes: 34 additions & 0 deletions src/frontend/src/stores/sharedContextStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { create } from "zustand";

export interface SharedContextEvent {
operation: "get" | "set" | "append" | "delete" | "keys" | "has_key";
key: string;
namespace: string;
timestamp: string;
component_id: string;
}

interface SharedContextState {
events: SharedContextEvent[];
addEvent: (event: SharedContextEvent) => void;
clearEvents: () => void;
getEventsByNamespace: (namespace: string) => SharedContextEvent[];
}

export const useSharedContextStore = create<SharedContextState>((set, get) => ({
events: [],

addEvent: (event) => {
set((state) => ({
events: [...state.events, event],
}));
},

clearEvents: () => {
set({ events: [] });
},

getEventsByNamespace: (namespace) => {
return get().events.filter((e) => e.namespace === namespace);
},
}));
16 changes: 15 additions & 1 deletion src/frontend/src/types/chat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,28 @@ export interface ToolContent extends BaseContent {
error?: any;
}

export interface SharedContextEventData {
operation: "get" | "set" | "append" | "delete" | "keys" | "has_key";
key: string;
namespace: string;
timestamp: string;
component_id: string;
}

export interface SharedContextContent extends BaseContent {
type: "shared_context";
events: SharedContextEventData[];
}

// Union type for all content types
export type ContentType =
| ErrorContent
| TextContent
| MediaContent
| JSONContent
| CodeContent
| ToolContent;
| ToolContent
| SharedContextContent;

// Updated ContentBlock interface
export interface ContentBlock {
Expand Down
Loading
Loading