mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
Revert "feat(integrations): add Intelligence threads to langgraph-fastapi"
This commit is contained in:
@@ -151,7 +151,10 @@
|
||||
"src/app/api/copilotkit/**",
|
||||
"docker/Dockerfile.agent",
|
||||
"docker-compose.test.yml",
|
||||
"scripts/**"
|
||||
"scripts/**",
|
||||
"src/components/threads-drawer/**",
|
||||
"src/app/page.tsx",
|
||||
"next.config.ts"
|
||||
],
|
||||
"packageJsonOverrides": {
|
||||
"scripts.dev:agent": "cd agent && uv run main.py",
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
AGENT_URL=http://localhost:8000
|
||||
OPENAI_API_KEY=
|
||||
|
||||
# --- CopilotKit Intelligence (optional; set COPILOTKIT_LICENSE_TOKEN to enable Threads — server + UI) ---
|
||||
# COPILOTKIT_LICENSE_TOKEN=
|
||||
# INTELLIGENCE_API_URL=http://localhost:4201
|
||||
# INTELLIGENCE_GATEWAY_WS_URL=ws://localhost:4401
|
||||
# INTELLIGENCE_API_KEY= # local dev: see examples/integrations/_intelligence/.env.intelligence for the seed value
|
||||
|
||||
@@ -3,19 +3,6 @@ import type { NextConfig } from "next";
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
serverExternalPackages: ["@copilotkit/runtime"],
|
||||
env: {
|
||||
// The public Threads UI flag is DERIVED from the server-side license token.
|
||||
// Set COPILOTKIT_LICENSE_TOKEN (only) to enable Threads — do not set this flag
|
||||
// directly. NOTE: NEXT_PUBLIC_* resolves at BUILD time while the runtime reads
|
||||
// the token per-request, so the UI gate and runtime agree only when the token is
|
||||
// present at build time (the standard `next dev` / host-build flow). For a
|
||||
// standalone/Docker image built without the token and injected at runtime, set
|
||||
// COPILOTKIT_LICENSE_TOKEN at build time too (or gate the UI at runtime) so the
|
||||
// baked flag reflects it.
|
||||
NEXT_PUBLIC_COPILOTKIT_THREADS_ENABLED: process.env.COPILOTKIT_LICENSE_TOKEN
|
||||
? "true"
|
||||
: "false",
|
||||
},
|
||||
typescript: {
|
||||
// Docker route override uses HttpAgent which has a type mismatch with CopilotRuntime
|
||||
ignoreBuildErrors: true,
|
||||
|
||||
-19500
File diff suppressed because it is too large
Load Diff
+1
-19
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
CopilotRuntime,
|
||||
CopilotKitIntelligence,
|
||||
createCopilotEndpoint,
|
||||
InMemoryAgentRunner,
|
||||
} from "@copilotkit/runtime/v2";
|
||||
@@ -19,22 +18,7 @@ const defaultAgent = new LangGraphHttpAgent({
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: { default: defaultAgent },
|
||||
// --- copilotkit:intelligence (remove this block to opt out) ---
|
||||
...(process.env.COPILOTKIT_LICENSE_TOKEN
|
||||
? {
|
||||
intelligence: new CopilotKitIntelligence({
|
||||
apiKey: process.env.INTELLIGENCE_API_KEY ?? "",
|
||||
apiUrl: process.env.INTELLIGENCE_API_URL ?? "http://localhost:4201",
|
||||
wsUrl:
|
||||
process.env.INTELLIGENCE_GATEWAY_WS_URL ?? "ws://localhost:4401",
|
||||
}),
|
||||
// Demo stub — replace with your real auth-derived user identity before any
|
||||
// multi-user deployment, or all users share one thread history.
|
||||
identifyUser: () => ({ id: "demo-user", name: "Demo User" }),
|
||||
licenseToken: process.env.COPILOTKIT_LICENSE_TOKEN,
|
||||
}
|
||||
: { runner: new InMemoryAgentRunner() }),
|
||||
// --- /copilotkit:intelligence ---
|
||||
runner: new InMemoryAgentRunner(),
|
||||
openGenerativeUI: true,
|
||||
a2ui: {
|
||||
injectA2UITool: false,
|
||||
@@ -57,5 +41,3 @@ const app = createCopilotEndpoint({
|
||||
|
||||
export const GET = handle(app);
|
||||
export const POST = handle(app);
|
||||
export const PATCH = handle(app);
|
||||
export const DELETE = handle(app);
|
||||
|
||||
@@ -1,57 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { ExampleLayout } from "@/components/example-layout";
|
||||
import { ExampleCanvas } from "@/components/example-canvas";
|
||||
import { ThreadsDrawer } from "@/components/threads-drawer";
|
||||
import { ThreadsPanelGate } from "@/components/threads-drawer/locked-state";
|
||||
import { useGenerativeUIExamples, useExampleSuggestions } from "@/hooks";
|
||||
|
||||
import {
|
||||
CopilotChat,
|
||||
CopilotChatConfigurationProvider,
|
||||
} from "@copilotkit/react-core/v2";
|
||||
|
||||
import styles from "@/components/threads-drawer/threads-drawer.module.css";
|
||||
import { CopilotChat } from "@copilotkit/react-core/v2";
|
||||
|
||||
export default function HomePage() {
|
||||
useGenerativeUIExamples();
|
||||
useExampleSuggestions();
|
||||
|
||||
const [threadId, setThreadId] = useState<string | undefined>(undefined);
|
||||
|
||||
return (
|
||||
<div className={styles.layout}>
|
||||
<ThreadsPanelGate>
|
||||
<ThreadsDrawer
|
||||
agentId="default"
|
||||
threadId={threadId}
|
||||
onThreadChange={setThreadId}
|
||||
<ExampleLayout
|
||||
chatContent={
|
||||
<CopilotChat
|
||||
attachments={{ enabled: true }}
|
||||
input={{ disclaimer: () => null, className: "pb-6" }}
|
||||
/>
|
||||
</ThreadsPanelGate>
|
||||
<div className={styles.mainPanel}>
|
||||
{/*
|
||||
Wrap both the chat and the canvas in one CopilotChatConfigurationProvider
|
||||
so they share the active threadId. `useAgent()` falls back to the
|
||||
provider's threadId when called without an explicit one, which makes
|
||||
the canvas read from the same per-thread agent clone that the chat's
|
||||
/connect replay populates. Without this wrapper, the canvas resolves
|
||||
to the registry agent and never receives STATE_SNAPSHOT events on
|
||||
thread resume.
|
||||
*/}
|
||||
<CopilotChatConfigurationProvider agentId="default" threadId={threadId}>
|
||||
<ExampleLayout
|
||||
chatContent={
|
||||
<CopilotChat
|
||||
attachments={{ enabled: true }}
|
||||
input={{ disclaimer: () => null, className: "pb-6" }}
|
||||
/>
|
||||
}
|
||||
appContent={<ExampleCanvas />}
|
||||
/>
|
||||
</CopilotChatConfigurationProvider>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
appContent={<ExampleCanvas />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# Threads Drawer — Theming Contract
|
||||
|
||||
The threads-drawer is a BASE component. It is fully driven by CSS variables and
|
||||
contains no hardcoded colors, shadows, or surface radii. To theme it for an
|
||||
example, (re)define the tokens below on any ancestor (e.g. `:root`, `body`, or a
|
||||
wrapper element) — **never edit the drawer files**.
|
||||
|
||||
The drawer first consumes the shared design-system tokens (`--card`,
|
||||
`--border`, `--radius`, …) that `ui/card.tsx` and `ui/button.tsx` also consume.
|
||||
For a handful of drawer-specific visuals (scrim, shadows, delete-hover tint) it
|
||||
exposes dedicated `--threads-*` tokens, each with a fallback to a shared token or
|
||||
the original literal — so defining nothing reproduces the default look exactly.
|
||||
|
||||
## Shared design-system tokens consumed
|
||||
|
||||
| Token | Controls |
|
||||
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--background` | Tooltip text color (`color: var(--background)` on the dark tooltip body) |
|
||||
| `--foreground` | Drawer/dialog title + body text, active segment text, tooltip surface bg |
|
||||
| `--card` | Drawer surface bg (via `--threads-drawer-bg`), active segment bg, empty/dialog/load-more bg |
|
||||
| `--border` | Drawer + header + filter + dialog borders, thread accent (idle), selected-row inset ring, secondary-button hover bg, tooltip border |
|
||||
| `--radius` | Drawer/dialog/button/segment/thread/empty-card radii; tooltip radius derives from it |
|
||||
| `--primary` | New-thread button bg, primary dialog button bg, selected thread accent |
|
||||
| `--primary-foreground` | New-thread button text, primary dialog button text |
|
||||
| `--secondary` | Icon-button + thread-row + load-more hover bg, segment track, archived badge bg, secondary dialog button bg, loading skeleton bars, thread-enter start bg |
|
||||
| `--secondary-foreground` | (locked-state) inline code text |
|
||||
| `--muted-foreground` | Icon-button idle color, segment idle text, meta text, placeholder/archived titles, empty/dialog description, load-more text, collapsed-rail icon |
|
||||
| `--accent` | Selected thread-row bg |
|
||||
| `--ring` | Focus-visible outline on buttons, thread items, segments, dialog buttons |
|
||||
| `--destructive` | Delete-button icon color + delete-hover text |
|
||||
| `--destructive-foreground` | Destructive dialog button text |
|
||||
| `--font-body` | Header, segments, tooltip, empty card, and dialog typography |
|
||||
|
||||
(locked-state additionally uses `--secondary`, `--muted-foreground`, `--border`,
|
||||
`--radius`, `--secondary-foreground`, and the `ui/card` + `ui/button` tokens via
|
||||
those components.)
|
||||
|
||||
## Drawer-specific tokens (with fallbacks)
|
||||
|
||||
| Token | Controls | Fallback |
|
||||
| --------------------------------- | ----------------------------------------- | --------------------------------------------------------- |
|
||||
| `--threads-drawer-bg` | Drawer surface background | `var(--card)` |
|
||||
| `--threads-drawer-border` | Drawer right border color | `var(--border)` |
|
||||
| `--threads-drawer-shadow` | Open-drawer drop shadow | `4px 0 20px rgb(0 0 0 / 0.04)` |
|
||||
| `--threads-segment-active-shadow` | Active filter-segment shadow | `0 1px 2px rgb(0 0 0 / 0.06)` |
|
||||
| `--threads-delete-hover-bg` | Delete-button hover/focus background tint | `color-mix(in srgb, var(--destructive) 10%, transparent)` |
|
||||
| `--threads-overlay-bg` | Confirm-dialog overlay scrim | `rgb(0 0 0 / 0.5)` |
|
||||
| `--threads-dialog-shadow` | Confirm-dialog drop shadow | `0 20px 50px rgb(0 0 0 / 0.25)` |
|
||||
| `--threads-tooltip-radius` | Action-button tooltip corner radius | `calc(var(--radius) - 0.45rem)` (= `0.3rem` at default) |
|
||||
|
||||
All fallbacks resolve to the original hardcoded values in the north-star, so an
|
||||
example that defines none of the `--threads-*` tokens renders pixel-identical to
|
||||
the pre-tokenization drawer.
|
||||
@@ -1,4 +0,0 @@
|
||||
"use client";
|
||||
|
||||
export { default as ThreadsDrawer } from "./threads-drawer";
|
||||
export type { ThreadsDrawerProps } from "./threads-drawer";
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import styles from "./threads-drawer.module.css";
|
||||
|
||||
export function ThreadsPanelGate({ children }: { children: React.ReactNode }) {
|
||||
// The Threads drawer reads a client-only external store (useThreads /
|
||||
// useSyncExternalStore) with no server snapshot, so it must not render during
|
||||
// SSR/prerender — Next would fail to prerender "/". Defer to client mount.
|
||||
const [mounted, setMounted] = React.useState(false);
|
||||
React.useEffect(() => setMounted(true), []);
|
||||
|
||||
if (process.env.NEXT_PUBLIC_COPILOTKIT_THREADS_ENABLED === "true") {
|
||||
if (!mounted) {
|
||||
// SSR / first-paint placeholder: matches the open drawer's footprint +
|
||||
// surface (and collapses to nothing on mobile) so the panel doesn't flash
|
||||
// a bare-background column or shift the content when the drawer mounts.
|
||||
return <div className={styles.drawerPlaceholder} aria-hidden />;
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex w-80 shrink-0 flex-col items-center justify-center p-4 bg-[var(--threads-drawer-bg,var(--card))] border-r border-[var(--threads-drawer-border,var(--border))] max-lg:hidden">
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<div className="mb-2 flex h-10 w-10 items-center justify-center rounded-full bg-[var(--secondary)]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-[var(--muted-foreground)]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<rect width="18" height="11" x="3" y="11" rx="2" ry="2" />
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
||||
</svg>
|
||||
</div>
|
||||
<CardTitle>Threads</CardTitle>
|
||||
<CardDescription>
|
||||
Threads is a licensed CopilotKit Intelligence feature. Unlock
|
||||
persistent conversation history, multi-session context, and thread
|
||||
management across your application.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-[var(--muted-foreground)]">
|
||||
To enable Threads, add a CopilotKit Intelligence license to your
|
||||
project with:
|
||||
</p>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col items-start gap-3">
|
||||
<div className="w-full rounded-[var(--radius)] border border-[var(--border)] bg-[var(--secondary)] px-3 py-2">
|
||||
<code className="text-xs whitespace-nowrap text-[var(--secondary-foreground)]">
|
||||
copilotkit add-intelligence
|
||||
</code>
|
||||
</div>
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="w-full"
|
||||
onClick={() =>
|
||||
window.open(
|
||||
"https://docs.copilotkit.ai/intelligence",
|
||||
"_blank",
|
||||
"noopener,noreferrer",
|
||||
)
|
||||
}
|
||||
>
|
||||
Learn more
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
-738
@@ -1,738 +0,0 @@
|
||||
.layout {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
min-height: 100vh;
|
||||
min-height: 100svh;
|
||||
height: 100dvh;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.drawer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
min-height: 100svh;
|
||||
height: 100dvh;
|
||||
background: var(--threads-drawer-bg, var(--card));
|
||||
border-right: 1px solid var(--threads-drawer-border, var(--border));
|
||||
transition:
|
||||
width 180ms ease,
|
||||
box-shadow 180ms ease;
|
||||
}
|
||||
|
||||
.drawerOpen {
|
||||
width: 18rem;
|
||||
box-shadow: var(--threads-drawer-shadow, 4px 0 20px rgb(0 0 0 / 0.04));
|
||||
}
|
||||
|
||||
.drawerClosed {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
||||
/* First-paint placeholder (rendered by ThreadsPanelGate before the client-only
|
||||
drawer mounts). Matches the open drawer's footprint + surface so there's no
|
||||
bare-background column flash and no content shift on mount. On mobile the
|
||||
real drawer floats (no grid footprint), so the placeholder reserves nothing. */
|
||||
.drawerPlaceholder {
|
||||
width: 18rem;
|
||||
flex-shrink: 0;
|
||||
min-height: 100vh;
|
||||
min-height: 100svh;
|
||||
height: 100dvh;
|
||||
background: var(--threads-drawer-bg, var(--card));
|
||||
border-right: 1px solid var(--threads-drawer-border, var(--border));
|
||||
}
|
||||
|
||||
.drawerSurface {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.drawerHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
padding: 1rem 1rem 0.75rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.drawerHeaderMain {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
.drawerTitle {
|
||||
margin: 0;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.headerActions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.iconButton {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius);
|
||||
color: var(--muted-foreground);
|
||||
background: transparent;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
color 140ms ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.iconButton:hover,
|
||||
.iconButton:focus-visible {
|
||||
background: var(--secondary);
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.iconButton:focus-visible,
|
||||
.threadItem:focus-visible,
|
||||
.newThreadButton:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.newThreadButton {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
min-height: 2.25rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius);
|
||||
background: var(--primary);
|
||||
color: var(--primary-foreground);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
opacity 140ms ease,
|
||||
transform 140ms ease;
|
||||
}
|
||||
|
||||
.newThreadButton:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.filterBar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.segmented {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
padding: 0.2rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--secondary);
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.segmentedOption {
|
||||
flex: 1;
|
||||
min-height: 1.75rem;
|
||||
padding: 0.3rem 0.75rem;
|
||||
border: 0;
|
||||
border-radius: calc(var(--radius) - 0.15rem);
|
||||
background: transparent;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
color 140ms ease,
|
||||
box-shadow 140ms ease;
|
||||
}
|
||||
|
||||
.segmentedOption:hover {
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.segmentedOption:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.segmentedOptionActive {
|
||||
background: var(--card);
|
||||
color: var(--foreground);
|
||||
box-shadow: var(--threads-segment-active-shadow, 0 1px 2px rgb(0 0 0 / 0.06));
|
||||
}
|
||||
|
||||
.drawerContent {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.threadList {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
overflow-y: auto;
|
||||
/* Reserve scrollbar space so the list doesn't shift horizontally
|
||||
when the scrollbar appears during the thread-enter animation. */
|
||||
scrollbar-gutter: stable;
|
||||
padding: 0.75rem 0.5rem;
|
||||
}
|
||||
|
||||
.threadRow {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.threadItem {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 0.65rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
box-shadow 140ms ease,
|
||||
padding-right 140ms ease;
|
||||
}
|
||||
|
||||
.threadItem:hover,
|
||||
.threadItem:focus-visible {
|
||||
background: var(--secondary);
|
||||
}
|
||||
|
||||
.threadRow:hover .threadItem,
|
||||
.threadRow:focus-within .threadItem {
|
||||
padding-right: 3.5rem;
|
||||
}
|
||||
|
||||
.threadItemSelected {
|
||||
background: var(--accent);
|
||||
box-shadow: inset 0 0 0 1px var(--border);
|
||||
}
|
||||
|
||||
.threadItemAnimatingIn {
|
||||
animation: threadItemEnter 420ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.threadAccent {
|
||||
flex: none;
|
||||
width: 0.35rem;
|
||||
height: 1.75rem;
|
||||
border-radius: 999px;
|
||||
background: var(--border);
|
||||
transition: background 140ms ease;
|
||||
}
|
||||
|
||||
.threadItemSelected .threadAccent {
|
||||
background: var(--primary);
|
||||
}
|
||||
|
||||
.threadBody {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.threadTitle {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.threadTitlePlaceholder {
|
||||
color: var(--muted-foreground);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.threadTitleAnimated {
|
||||
display: inline-block;
|
||||
animation: generatedTitleReveal 360ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.threadMeta {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.7rem;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.threadItemArchived .threadTitle {
|
||||
color: var(--muted-foreground);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.threadItemArchived .threadAccent {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.archivedBadge {
|
||||
display: inline-block;
|
||||
margin-left: 0.35rem;
|
||||
padding: 0.05rem 0.35rem;
|
||||
border-radius: 999px;
|
||||
background: var(--secondary);
|
||||
font-size: 0.6rem;
|
||||
font-weight: 600;
|
||||
color: var(--muted-foreground);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.loadMoreButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 2rem;
|
||||
margin-top: 0.25rem;
|
||||
padding: 0.4rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--card);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
color: var(--muted-foreground);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
color 140ms ease;
|
||||
}
|
||||
|
||||
.loadMoreButton:hover:not(:disabled) {
|
||||
background: var(--secondary);
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.loadMoreButton:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.threadActions {
|
||||
position: absolute;
|
||||
right: 0.4rem;
|
||||
top: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.15rem;
|
||||
transform: translateY(-50%) scale(0.96);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
opacity 140ms ease,
|
||||
transform 140ms ease;
|
||||
}
|
||||
|
||||
.threadRow:hover .threadActions,
|
||||
.threadRow:focus-within .threadActions {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(-50%) scale(1);
|
||||
}
|
||||
|
||||
.threadActionButton {
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tooltip::after {
|
||||
content: attr(data-tooltip);
|
||||
position: absolute;
|
||||
top: calc(100% + 0.3rem);
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-2px);
|
||||
padding: 0.2rem 0.45rem;
|
||||
border-radius: var(--threads-tooltip-radius, calc(var(--radius) - 0.45rem));
|
||||
border: 1px solid var(--border);
|
||||
background: var(--foreground);
|
||||
color: var(--background);
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
opacity 110ms ease 200ms,
|
||||
transform 110ms ease 200ms;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.tooltip:hover::after,
|
||||
.tooltip:focus-visible::after {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
|
||||
.deleteButton {
|
||||
color: var(--destructive);
|
||||
}
|
||||
|
||||
.deleteButton:hover,
|
||||
.deleteButton:focus-visible {
|
||||
background: var(
|
||||
--threads-delete-hover-bg,
|
||||
color-mix(in srgb, var(--destructive) 10%, transparent)
|
||||
);
|
||||
color: var(--destructive);
|
||||
}
|
||||
|
||||
.loadingList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
padding: 0.2rem 0;
|
||||
}
|
||||
|
||||
.loadingRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 0.65rem;
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.loadingAccent {
|
||||
flex: none;
|
||||
width: 0.35rem;
|
||||
height: 1.75rem;
|
||||
border-radius: 999px;
|
||||
background: var(--secondary);
|
||||
animation: threadsDrawerPulse 1.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loadingBody {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.loadingTitleBar {
|
||||
height: 0.6rem;
|
||||
width: 60%;
|
||||
border-radius: 999px;
|
||||
background: var(--secondary);
|
||||
animation: threadsDrawerPulse 1.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loadingMetaBar {
|
||||
height: 0.45rem;
|
||||
width: 35%;
|
||||
border-radius: 999px;
|
||||
background: var(--secondary);
|
||||
animation: threadsDrawerPulse 1.4s ease-in-out infinite;
|
||||
animation-delay: 140ms;
|
||||
}
|
||||
|
||||
@keyframes threadsDrawerPulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.45;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.emptyState {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.emptyCard {
|
||||
display: flex;
|
||||
max-width: 13rem;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--card);
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
.emptyTitle {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.emptyMessage {
|
||||
margin: 0;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.collapsedRail {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 1rem 0.5rem;
|
||||
}
|
||||
|
||||
.mainPanel {
|
||||
min-width: 0;
|
||||
min-height: 100vh;
|
||||
min-height: 100svh;
|
||||
height: 100dvh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.dialogOverlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 200;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
background: var(--threads-overlay-bg, rgb(0 0 0 / 0.5));
|
||||
backdrop-filter: blur(2px);
|
||||
animation: dialogOverlayEnter 140ms ease-out;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
width: 100%;
|
||||
max-width: 22rem;
|
||||
padding: 1.1rem 1.1rem 1rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: calc(var(--radius) + 0.25rem);
|
||||
background: var(--card);
|
||||
color: var(--foreground);
|
||||
box-shadow: var(--threads-dialog-shadow, 0 20px 50px rgb(0 0 0 / 0.25));
|
||||
font-family: var(--font-body);
|
||||
animation: dialogEnter 160ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.dialogTitle {
|
||||
margin: 0 0 0.35rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.dialogDescription {
|
||||
margin: 0 0 1rem;
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.5;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.dialogActions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.dialogButton {
|
||||
min-height: 2.25rem;
|
||||
padding: 0.5rem 0.95rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius);
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
color 140ms ease,
|
||||
opacity 140ms ease;
|
||||
}
|
||||
|
||||
.dialogButton:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.dialogButtonSecondary {
|
||||
background: var(--secondary);
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.dialogButtonSecondary:hover {
|
||||
background: var(--border);
|
||||
}
|
||||
|
||||
.dialogButtonPrimary {
|
||||
background: var(--primary);
|
||||
color: var(--primary-foreground);
|
||||
}
|
||||
|
||||
.dialogButtonPrimary:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dialogButtonDestructive {
|
||||
background: var(--destructive);
|
||||
color: var(--destructive-foreground);
|
||||
}
|
||||
|
||||
.dialogButtonDestructive:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
@keyframes dialogOverlayEnter {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dialogEnter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(6px) scale(0.98);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes threadItemEnter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-10px);
|
||||
background: var(--secondary);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes generatedTitleReveal {
|
||||
0% {
|
||||
opacity: 0;
|
||||
filter: blur(6px);
|
||||
transform: translateY(4px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
filter: blur(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet + phone: the threads panel goes off-canvas so the content and the
|
||||
(full-screen) chat get the whole width instead of squeezing into a column. */
|
||||
@media (max-width: 1024px) {
|
||||
.layout {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
/* The mounted drawer floats on mobile, so the first-paint placeholder must
|
||||
reserve no column (otherwise content shifts left when the drawer mounts). */
|
||||
.drawerPlaceholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Collapsed: a small floating launcher pinned top-left, above the full-screen
|
||||
mobile chat (z-index 1200) so threads stay reachable over it. */
|
||||
.drawer.drawerClosed {
|
||||
position: fixed;
|
||||
top: 0.5rem;
|
||||
left: 0.5rem;
|
||||
width: auto;
|
||||
height: auto;
|
||||
/* Override the base drawer's full-viewport height + chrome so the closed
|
||||
state shrinks to a small floating launcher. */
|
||||
min-height: 0;
|
||||
border-right: 0;
|
||||
background: transparent;
|
||||
z-index: 1300;
|
||||
}
|
||||
|
||||
.drawerClosed .collapsedRail {
|
||||
flex-direction: row;
|
||||
width: auto;
|
||||
height: auto;
|
||||
gap: 0.125rem;
|
||||
padding: 0.1875rem;
|
||||
overflow: visible;
|
||||
border-radius: 999px;
|
||||
background: var(--threads-drawer-bg, var(--card));
|
||||
border: 1px solid var(--threads-drawer-border, var(--border));
|
||||
box-shadow: 0 8px 24px rgb(0 0 0 / 0.16);
|
||||
}
|
||||
|
||||
/* Trim the launcher's icon buttons so the pill's height lines up with the
|
||||
top-right Chat/App toggle instead of towering over it. */
|
||||
.drawerClosed .collapsedRail .iconButton {
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
/* Open: full-height off-canvas panel from the left, above the chat. */
|
||||
.drawer.drawerOpen {
|
||||
position: fixed;
|
||||
inset: 0 auto 0 0;
|
||||
z-index: 1300;
|
||||
width: min(20rem, 92vw);
|
||||
box-shadow: 0 20px 50px rgb(0 0 0 / 0.25);
|
||||
}
|
||||
|
||||
.mainPanel {
|
||||
grid-column: 1;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
-586
@@ -1,586 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Archive,
|
||||
ArchiveRestore,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Plus,
|
||||
Trash2,
|
||||
} from "lucide-react";
|
||||
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useThreads } from "@copilotkit/react-core/v2";
|
||||
import styles from "./threads-drawer.module.css";
|
||||
|
||||
export interface ThreadsDrawerProps {
|
||||
agentId: string;
|
||||
threadId: string | undefined;
|
||||
onThreadChange: (threadId: string | undefined) => void;
|
||||
}
|
||||
|
||||
interface DrawerThread {
|
||||
id: string;
|
||||
name: string | null;
|
||||
updatedAt: string;
|
||||
archived: boolean;
|
||||
lastRunAt?: string;
|
||||
}
|
||||
|
||||
const THREAD_ENTRY_ANIMATION_MS = 420;
|
||||
const TITLE_ANIMATION_MS = 360;
|
||||
const UNTITLED_THREAD_LABEL = "New thread";
|
||||
const RUNTIME_BASE_PATH = "/api/copilotkit";
|
||||
|
||||
function formatThreadTimestamp(updatedAt: string): string {
|
||||
const timestamp = new Date(updatedAt);
|
||||
if (Number.isNaN(timestamp.getTime())) return "Updated recently";
|
||||
return new Intl.DateTimeFormat("en-US", {
|
||||
dateStyle: "medium",
|
||||
timeStyle: "short",
|
||||
}).format(timestamp);
|
||||
}
|
||||
|
||||
function cx(...classNames: Array<string | false | undefined>): string {
|
||||
return classNames.filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
export default function ThreadsDrawer({
|
||||
agentId,
|
||||
threadId,
|
||||
onThreadChange,
|
||||
}: ThreadsDrawerProps) {
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
// Start collapsed on narrow screens (tablet + phone) so the panel — which
|
||||
// becomes an off-canvas overlay below 1024px — doesn't cover the content +
|
||||
// chat on load. The drawer is client-mounted, so reading window here is safe
|
||||
// and won't cause a hydration mismatch.
|
||||
const [isOpen, setIsOpen] = useState(
|
||||
() => typeof window === "undefined" || window.innerWidth > 1024,
|
||||
);
|
||||
const [pendingDelete, setPendingDelete] = useState<{
|
||||
id: string;
|
||||
title: string;
|
||||
} | null>(null);
|
||||
const deleteTriggerRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
const {
|
||||
threads,
|
||||
archiveThread,
|
||||
deleteThread,
|
||||
error,
|
||||
isLoading,
|
||||
hasMoreThreads,
|
||||
isFetchingMoreThreads,
|
||||
fetchMoreThreads,
|
||||
} = useThreads({
|
||||
agentId,
|
||||
includeArchived: showArchived,
|
||||
limit: 20,
|
||||
});
|
||||
|
||||
const restoreThread = useCallback(
|
||||
async (id: string) => {
|
||||
const response = await fetch(
|
||||
`${RUNTIME_BASE_PATH}/threads/${encodeURIComponent(id)}`,
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ agentId, archived: false }),
|
||||
},
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Restore failed: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
[agentId],
|
||||
);
|
||||
|
||||
const hasMountedRef = useRef(false);
|
||||
const hasLoadedOnceRef = useRef(false);
|
||||
const stableThreadsRef = useRef<DrawerThread[]>(threads);
|
||||
const previousThreadIdsRef = useRef<Set<string>>(new Set());
|
||||
const previousNamesRef = useRef<Map<string, string | null>>(new Map());
|
||||
const entryTimeoutsRef = useRef<Map<string, number>>(new Map());
|
||||
const titleTimeoutsRef = useRef<Map<string, number>>(new Map());
|
||||
|
||||
if (!isLoading) {
|
||||
hasLoadedOnceRef.current = true;
|
||||
stableThreadsRef.current = threads;
|
||||
}
|
||||
const displayThreads: DrawerThread[] =
|
||||
isLoading && hasLoadedOnceRef.current ? stableThreadsRef.current : threads;
|
||||
const [enteringThreadIds, setEnteringThreadIds] = useState<
|
||||
Record<string, true>
|
||||
>({});
|
||||
const [revealedTitleIds, setRevealedTitleIds] = useState<
|
||||
Record<string, true>
|
||||
>({});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
for (const timeoutId of entryTimeoutsRef.current.values()) {
|
||||
window.clearTimeout(timeoutId);
|
||||
}
|
||||
for (const timeoutId of titleTimeoutsRef.current.values()) {
|
||||
window.clearTimeout(timeoutId);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Skip diffing while the store is refetching (e.g. after a filter change
|
||||
// clears the list). Otherwise every thread would be treated as newly
|
||||
// added once the new page lands.
|
||||
if (isLoading) return;
|
||||
|
||||
const nextThreadIds = new Set(threads.map((t) => t.id));
|
||||
|
||||
if (!hasMountedRef.current) {
|
||||
hasMountedRef.current = true;
|
||||
previousThreadIdsRef.current = nextThreadIds;
|
||||
previousNamesRef.current = new Map(threads.map((t) => [t.id, t.name]));
|
||||
return;
|
||||
}
|
||||
|
||||
const addedThreadIds = threads
|
||||
.filter((t) => !previousThreadIdsRef.current.has(t.id))
|
||||
.map((t) => t.id);
|
||||
|
||||
if (addedThreadIds.length > 0) {
|
||||
setEnteringThreadIds((current) => {
|
||||
const next = { ...current };
|
||||
for (const id of addedThreadIds) {
|
||||
next[id] = true;
|
||||
const existing = entryTimeoutsRef.current.get(id);
|
||||
if (existing !== undefined) window.clearTimeout(existing);
|
||||
const tid = window.setTimeout(() => {
|
||||
setEnteringThreadIds((s) => {
|
||||
const updated = { ...s };
|
||||
delete updated[id];
|
||||
return updated;
|
||||
});
|
||||
entryTimeoutsRef.current.delete(id);
|
||||
}, THREAD_ENTRY_ANIMATION_MS);
|
||||
entryTimeoutsRef.current.set(id, tid);
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}
|
||||
|
||||
const renamedThreadIds = threads
|
||||
.filter((t) => {
|
||||
// Only reveal when an already-tracked thread's name transitions from
|
||||
// null → named. Threads appearing for the first time (e.g. on a
|
||||
// filter switch) already have their final name and should not trigger
|
||||
// the title reveal animation — that would layer a blur/translateY
|
||||
// onto the row's enter animation and produce a visible jitter.
|
||||
if (!previousNamesRef.current.has(t.id)) return false;
|
||||
const prev = previousNamesRef.current.get(t.id) ?? null;
|
||||
return prev === null && t.name !== null;
|
||||
})
|
||||
.map((t) => t.id);
|
||||
|
||||
if (renamedThreadIds.length > 0) {
|
||||
setRevealedTitleIds((current) => {
|
||||
const next = { ...current };
|
||||
for (const id of renamedThreadIds) {
|
||||
next[id] = true;
|
||||
const existing = titleTimeoutsRef.current.get(id);
|
||||
if (existing !== undefined) window.clearTimeout(existing);
|
||||
const tid = window.setTimeout(() => {
|
||||
setRevealedTitleIds((s) => {
|
||||
const updated = { ...s };
|
||||
delete updated[id];
|
||||
return updated;
|
||||
});
|
||||
titleTimeoutsRef.current.delete(id);
|
||||
}, TITLE_ANIMATION_MS);
|
||||
titleTimeoutsRef.current.set(id, tid);
|
||||
}
|
||||
return next;
|
||||
});
|
||||
}
|
||||
|
||||
previousThreadIdsRef.current = nextThreadIds;
|
||||
previousNamesRef.current = new Map(threads.map((t) => [t.id, t.name]));
|
||||
}, [threads, isLoading]);
|
||||
|
||||
const isInitialLoading = isLoading && !hasLoadedOnceRef.current;
|
||||
if (error) {
|
||||
console.error("Unable to load threads", error);
|
||||
}
|
||||
|
||||
if (!isOpen) {
|
||||
return (
|
||||
<aside
|
||||
aria-label="Threads drawer"
|
||||
className={cx(styles.drawer, styles.drawerClosed)}
|
||||
>
|
||||
<div className={styles.collapsedRail}>
|
||||
{/* Native title here (not the styled ::after): the collapsed rail
|
||||
sits at the viewport's left edge where a centered tooltip clips. */}
|
||||
<button
|
||||
aria-label="Open threads drawer"
|
||||
title="Expand"
|
||||
className={styles.iconButton}
|
||||
type="button"
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<ChevronRight size={18} />
|
||||
</button>
|
||||
<button
|
||||
aria-label="Create thread"
|
||||
title="New thread"
|
||||
className={styles.iconButton}
|
||||
type="button"
|
||||
onClick={() => onThreadChange(crypto.randomUUID())}
|
||||
>
|
||||
<Plus size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
const closeDeleteDialog = () => {
|
||||
setPendingDelete(null);
|
||||
const trigger = deleteTriggerRef.current;
|
||||
deleteTriggerRef.current = null;
|
||||
trigger?.focus?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<aside
|
||||
aria-label="Threads drawer"
|
||||
className={cx(styles.drawer, styles.drawerOpen)}
|
||||
>
|
||||
<div className={styles.drawerSurface}>
|
||||
<div className={styles.drawerHeader}>
|
||||
<div className={styles.drawerHeaderMain}>
|
||||
<h2 className={styles.drawerTitle}>Threads</h2>
|
||||
</div>
|
||||
<div className={styles.headerActions}>
|
||||
<button
|
||||
aria-label="Create thread"
|
||||
className={styles.newThreadButton}
|
||||
type="button"
|
||||
onClick={() => onThreadChange(crypto.randomUUID())}
|
||||
>
|
||||
<Plus size={14} />
|
||||
<span>New thread</span>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Collapse threads drawer"
|
||||
className={styles.iconButton}
|
||||
type="button"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
<ChevronLeft size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.filterBar}>
|
||||
<div
|
||||
aria-label="Thread filter"
|
||||
className={styles.segmented}
|
||||
role="tablist"
|
||||
>
|
||||
<button
|
||||
aria-selected={!showArchived}
|
||||
className={cx(
|
||||
styles.segmentedOption,
|
||||
!showArchived && styles.segmentedOptionActive,
|
||||
)}
|
||||
role="tab"
|
||||
type="button"
|
||||
onClick={() => setShowArchived(false)}
|
||||
>
|
||||
Active
|
||||
</button>
|
||||
<button
|
||||
aria-selected={showArchived}
|
||||
className={cx(
|
||||
styles.segmentedOption,
|
||||
showArchived && styles.segmentedOptionActive,
|
||||
)}
|
||||
role="tab"
|
||||
type="button"
|
||||
onClick={() => setShowArchived(true)}
|
||||
>
|
||||
All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.drawerContent}>
|
||||
{error ? (
|
||||
<div className={styles.emptyState}>
|
||||
<div className={styles.emptyCard}>
|
||||
<p className={styles.emptyTitle}>
|
||||
Couldn’t load threads
|
||||
</p>
|
||||
<p className={styles.emptyMessage}>
|
||||
The thread list failed to load. Try reloading the page.
|
||||
</p>
|
||||
<button
|
||||
className={styles.loadMoreButton}
|
||||
type="button"
|
||||
onClick={() => window.location.reload()}
|
||||
>
|
||||
Reload
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : isInitialLoading ? (
|
||||
<div
|
||||
aria-busy="true"
|
||||
aria-label="Loading threads"
|
||||
className={styles.loadingList}
|
||||
role="status"
|
||||
>
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i} className={styles.loadingRow}>
|
||||
<span className={styles.loadingAccent} />
|
||||
<span className={styles.loadingBody}>
|
||||
<span className={styles.loadingTitleBar} />
|
||||
<span className={styles.loadingMetaBar} />
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : displayThreads.length === 0 ? (
|
||||
<div className={styles.emptyState}>
|
||||
<div className={styles.emptyCard}>
|
||||
<p className={styles.emptyTitle}>No threads yet</p>
|
||||
<p className={styles.emptyMessage}>
|
||||
Create a thread to start a fresh conversation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.threadList}>
|
||||
{displayThreads.map((thread) => {
|
||||
const hasTitle = thread.name !== null;
|
||||
const title = thread.name ?? UNTITLED_THREAD_LABEL;
|
||||
|
||||
return (
|
||||
<div key={thread.id} className={styles.threadRow}>
|
||||
<button
|
||||
aria-current={
|
||||
threadId === thread.id ? "page" : undefined
|
||||
}
|
||||
className={cx(
|
||||
styles.threadItem,
|
||||
threadId === thread.id && styles.threadItemSelected,
|
||||
enteringThreadIds[thread.id] &&
|
||||
styles.threadItemAnimatingIn,
|
||||
thread.archived && styles.threadItemArchived,
|
||||
)}
|
||||
type="button"
|
||||
onClick={() => onThreadChange(thread.id)}
|
||||
>
|
||||
<span aria-hidden className={styles.threadAccent} />
|
||||
<span className={styles.threadBody}>
|
||||
<span
|
||||
className={cx(
|
||||
styles.threadTitle,
|
||||
!hasTitle && styles.threadTitlePlaceholder,
|
||||
revealedTitleIds[thread.id] &&
|
||||
styles.threadTitleAnimated,
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
{thread.archived && (
|
||||
<span className={styles.archivedBadge}>
|
||||
Archived
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className={styles.threadMeta}>
|
||||
{formatThreadTimestamp(
|
||||
thread.lastRunAt ?? thread.updatedAt,
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<div className={styles.threadActions}>
|
||||
{thread.archived ? (
|
||||
<button
|
||||
aria-label={`Restore ${title}`}
|
||||
className={cx(
|
||||
styles.iconButton,
|
||||
styles.threadActionButton,
|
||||
styles.tooltip,
|
||||
)}
|
||||
data-tooltip="Restore thread"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
restoreThread(thread.id).catch((err: unknown) => {
|
||||
console.error("Unable to restore thread", err);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ArchiveRestore size={14} />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
aria-label={`Archive ${title}`}
|
||||
className={cx(
|
||||
styles.iconButton,
|
||||
styles.threadActionButton,
|
||||
styles.tooltip,
|
||||
)}
|
||||
data-tooltip="Archive thread"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (threadId === thread.id)
|
||||
onThreadChange(undefined);
|
||||
archiveThread(thread.id).catch((err: unknown) => {
|
||||
console.error("Unable to archive thread", err);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Archive size={14} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
aria-label={`Delete ${title}`}
|
||||
className={cx(
|
||||
styles.iconButton,
|
||||
styles.threadActionButton,
|
||||
styles.deleteButton,
|
||||
styles.tooltip,
|
||||
)}
|
||||
data-tooltip="Delete thread"
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
deleteTriggerRef.current = e.currentTarget;
|
||||
setPendingDelete({ id: thread.id, title });
|
||||
}}
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{hasMoreThreads && (
|
||||
<button
|
||||
className={styles.loadMoreButton}
|
||||
disabled={isFetchingMoreThreads}
|
||||
type="button"
|
||||
onClick={fetchMoreThreads}
|
||||
>
|
||||
{isFetchingMoreThreads ? "Loading\u2026" : "Load more"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
{pendingDelete && (
|
||||
<ConfirmDialog
|
||||
confirmLabel="Delete"
|
||||
description={`Delete "${pendingDelete.title}"? This cannot be undone.`}
|
||||
destructive
|
||||
title="Delete thread"
|
||||
onCancel={closeDeleteDialog}
|
||||
onConfirm={() => {
|
||||
const { id } = pendingDelete;
|
||||
closeDeleteDialog();
|
||||
if (threadId === id) onThreadChange(undefined);
|
||||
deleteThread(id).catch((err: unknown) => {
|
||||
console.error("Unable to delete thread", err);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface ConfirmDialogProps {
|
||||
title: string;
|
||||
description: string;
|
||||
confirmLabel: string;
|
||||
cancelLabel?: string;
|
||||
destructive?: boolean;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
function ConfirmDialog({
|
||||
title,
|
||||
description,
|
||||
confirmLabel,
|
||||
cancelLabel = "Cancel",
|
||||
destructive = false,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
}: ConfirmDialogProps) {
|
||||
const titleId = useId();
|
||||
const descId = useId();
|
||||
|
||||
useEffect(() => {
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") onCancel();
|
||||
};
|
||||
window.addEventListener("keydown", onKey);
|
||||
return () => window.removeEventListener("keydown", onKey);
|
||||
}, [onCancel]);
|
||||
|
||||
if (typeof document === "undefined") return null;
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
className={styles.dialogOverlay}
|
||||
role="presentation"
|
||||
onClick={onCancel}
|
||||
>
|
||||
<div
|
||||
aria-describedby={descId}
|
||||
aria-labelledby={titleId}
|
||||
aria-modal="true"
|
||||
className={styles.dialog}
|
||||
role="dialog"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<h3 className={styles.dialogTitle} id={titleId}>
|
||||
{title}
|
||||
</h3>
|
||||
<p className={styles.dialogDescription} id={descId}>
|
||||
{description}
|
||||
</p>
|
||||
<div className={styles.dialogActions}>
|
||||
<button
|
||||
autoFocus
|
||||
className={cx(styles.dialogButton, styles.dialogButtonSecondary)}
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
>
|
||||
{cancelLabel}
|
||||
</button>
|
||||
<button
|
||||
className={cx(
|
||||
styles.dialogButton,
|
||||
destructive
|
||||
? styles.dialogButtonDestructive
|
||||
: styles.dialogButtonPrimary,
|
||||
)}
|
||||
type="button"
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{confirmLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
@@ -1,991 +0,0 @@
|
||||
{
|
||||
"name": "agent",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "agent",
|
||||
"version": "0.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@copilotkit/sdk-js": "1.56.5",
|
||||
"@langchain/core": "1.1.44",
|
||||
"@langchain/langgraph": "1.3.0",
|
||||
"@langchain/openai": "1.4.4",
|
||||
"langchain": "1.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/html-to-text": "^9.0.4",
|
||||
"@types/node": "^22.9.0",
|
||||
"typescript": "^5.6.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@ag-ui/client": {
|
||||
"version": "0.0.55",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/client/-/client-0.0.55.tgz",
|
||||
"integrity": "sha512-cyTY0S1UK3ynFCtLh6XPkxECQiYL6XvFcAei5FD4yYzln5agSCZ3cAmdD86mwE4UbS5teS3Nci8Q5tEAjrRRgA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.55",
|
||||
"@ag-ui/encoder": "0.0.55",
|
||||
"@ag-ui/proto": "0.0.55",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"compare-versions": "^6.1.1",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"rxjs": "7.8.1",
|
||||
"untruncate-json": "^0.0.1",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@ag-ui/core": {
|
||||
"version": "0.0.55",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/core/-/core-0.0.55.tgz",
|
||||
"integrity": "sha512-Pj7Ke0NsCxbCFgI3xK5YE56LaMRxnXnyeDUgDFTYxeF6KZDcSf5E0x2gB6/37w6bE0hcn/LRNPFd8Es18eIEzA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@ag-ui/encoder": {
|
||||
"version": "0.0.55",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/encoder/-/encoder-0.0.55.tgz",
|
||||
"integrity": "sha512-co4RB8kCatQ/+sBOR+nmNMzuKKWynHD73U/MTn9yG8rdznG51KuAPlQAwTP03VChFgO5GfNqEAzcGf5dR6jyMg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.55",
|
||||
"@ag-ui/proto": "0.0.55"
|
||||
}
|
||||
},
|
||||
"node_modules/@ag-ui/langgraph": {
|
||||
"version": "0.0.31",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/langgraph/-/langgraph-0.0.31.tgz",
|
||||
"integrity": "sha512-mK24pfQZiV5SlnDLhTka+873gw7QQOAWXqqDSnwkuyoQQQFX7KC8xZR+4Da2dWqyVhbhNPx+amE16X7twS1wcg==",
|
||||
"dependencies": {
|
||||
"@langchain/core": "^1.1.40",
|
||||
"@langchain/langgraph-sdk": "^1.8.8",
|
||||
"langchain": ">=1.2.0",
|
||||
"partial-json": "^0.1.7",
|
||||
"rxjs": "7.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ag-ui/client": ">=0.0.42",
|
||||
"@ag-ui/core": ">=0.0.42"
|
||||
}
|
||||
},
|
||||
"node_modules/@ag-ui/proto": {
|
||||
"version": "0.0.55",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/proto/-/proto-0.0.55.tgz",
|
||||
"integrity": "sha512-DNavmWA/dL3u4mpB+g/NPzF7XrYLjVFgmS8CnSOsenrmO64XVoR5RrbQghzaKvP9VNkhvdFI9tllpItfE3Pryw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.55",
|
||||
"@bufbuild/protobuf": "^2.2.5",
|
||||
"@protobuf-ts/protoc": "^2.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz",
|
||||
"integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==",
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/@cfworker/json-schema": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz",
|
||||
"integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@copilotkit/license-verifier": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@copilotkit/license-verifier/-/license-verifier-0.2.0.tgz",
|
||||
"integrity": "sha512-hliCifqy5a65YTozgRckuQmvBEQlt4L2PhbpSDY6fb/TKqPHyNDJgItRSnOpxOVDqvEfHEbUUqw3NaD88ZtdJA=="
|
||||
},
|
||||
"node_modules/@copilotkit/sdk-js": {
|
||||
"version": "1.56.5",
|
||||
"resolved": "https://registry.npmjs.org/@copilotkit/sdk-js/-/sdk-js-1.56.5.tgz",
|
||||
"integrity": "sha512-v4jZdZaiRVH+xtJYBSjltiTWih6JKgG0Gk2ospxxrHLDKEGcwvm+GtQIpwf0Arb5nqFa5OnxV62EPC70IXRAdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ag-ui/langgraph": "0.0.31",
|
||||
"@copilotkit/shared": "1.56.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": ">=0.4.0 <2.0.0",
|
||||
"@langchain/langgraph": ">=0.4.0 <2.0.0",
|
||||
"langchain": ">=1.0.0",
|
||||
"typescript": "^5.2.3",
|
||||
"zod": "^3.23.3 || ^3.24.0 || ^3.25.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared": {
|
||||
"version": "1.56.5",
|
||||
"resolved": "https://registry.npmjs.org/@copilotkit/shared/-/shared-1.56.5.tgz",
|
||||
"integrity": "sha512-jK2iEa+jRgWYXOw/v09RaU9txX5wNAYIrGl/SO405uzbC5mi0cYgXhJ3PC+VjNM7rlH//LRqa0+ELJO0UBwfPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ag-ui/client": "0.0.53",
|
||||
"@copilotkit/license-verifier": "0.2.0",
|
||||
"@segment/analytics-node": "^2.1.2",
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"chalk": "4.1.2",
|
||||
"graphql": "^16.8.1",
|
||||
"partial-json": "^0.1.7",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.23.3",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ag-ui/core": ">=0.0.48"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/client": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/client/-/client-0.0.53.tgz",
|
||||
"integrity": "sha512-Mkup36KUp0KXy9v89QtAOWDUoh8H1s1Vgl4zvQv9HqXuAK1TkbtpXJHpbgZJXIxTqd54KT6yCurmC2UkOP7FDQ==",
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.53",
|
||||
"@ag-ui/encoder": "0.0.53",
|
||||
"@ag-ui/proto": "0.0.53",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"compare-versions": "^6.1.1",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"rxjs": "7.8.1",
|
||||
"untruncate-json": "^0.0.1",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/client/node_modules/@ag-ui/core": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/core/-/core-0.0.53.tgz",
|
||||
"integrity": "sha512-11UocR7fFdMWw503bWCX2IOK15vbWfxT11Mn9xOiPBVO/UVcn57ywGrlLL4UaBlPgmUTvuzr2yYR2ElSqiN2wQ==",
|
||||
"dependencies": {
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/encoder": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/encoder/-/encoder-0.0.53.tgz",
|
||||
"integrity": "sha512-bAOcfVdm6U4H6G6tW+DZfwPEQm1w/snVBTwaFn9nJcEMW69M7/HZuwvEc/7Zo0rK1jRL32N/j60PwTAeky19fw==",
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.53",
|
||||
"@ag-ui/proto": "0.0.53"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/encoder/node_modules/@ag-ui/core": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/core/-/core-0.0.53.tgz",
|
||||
"integrity": "sha512-11UocR7fFdMWw503bWCX2IOK15vbWfxT11Mn9xOiPBVO/UVcn57ywGrlLL4UaBlPgmUTvuzr2yYR2ElSqiN2wQ==",
|
||||
"dependencies": {
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/proto": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/proto/-/proto-0.0.53.tgz",
|
||||
"integrity": "sha512-swjz22xWT8YUZt5OhmUwkARDQdwt8XM1hmGZbQrhRnNPXKwrKJX9ELlbnQ4iFUQIKkMWpphzE3vA3yNKs2bbKw==",
|
||||
"dependencies": {
|
||||
"@ag-ui/core": "0.0.53",
|
||||
"@bufbuild/protobuf": "^2.2.5",
|
||||
"@protobuf-ts/protoc": "^2.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@copilotkit/shared/node_modules/@ag-ui/proto/node_modules/@ag-ui/core": {
|
||||
"version": "0.0.53",
|
||||
"resolved": "https://registry.npmjs.org/@ag-ui/core/-/core-0.0.53.tgz",
|
||||
"integrity": "sha512-11UocR7fFdMWw503bWCX2IOK15vbWfxT11Mn9xOiPBVO/UVcn57ywGrlLL4UaBlPgmUTvuzr2yYR2ElSqiN2wQ==",
|
||||
"dependencies": {
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/core": {
|
||||
"version": "1.1.44",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.44.tgz",
|
||||
"integrity": "sha512-RePW1IjGCHr9ua2vcby3aE8mOOz3EnwDZxMEGbNDT91kf14eqkJqxDXvaZFviGdcN9DTrxM5RPQNAHmwSm4tbg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cfworker/json-schema": "^4.0.2",
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"ansi-styles": "^5.0.0",
|
||||
"camelcase": "6",
|
||||
"decamelize": "1.2.0",
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"langsmith": ">=0.5.0 <1.0.0",
|
||||
"mustache": "^4.2.0",
|
||||
"p-queue": "^6.6.2",
|
||||
"zod": "^3.25.76 || ^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.3.0.tgz",
|
||||
"integrity": "sha512-QvhTjiyqFPz81A+y6LHs223w6DTjv5+882DT4mup72bd72rRhNjTYo5fhes5um0swnKArvY/arc7KeFInfHHWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@langchain/langgraph-checkpoint": "^1.0.2",
|
||||
"@langchain/langgraph-sdk": "~1.9.0",
|
||||
"@langchain/protocol": "^0.0.15",
|
||||
"@standard-schema/spec": "1.1.0",
|
||||
"uuid": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.1.44",
|
||||
"zod": "^3.25.32 || ^4.2.0",
|
||||
"zod-to-json-schema": "^3.x"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"zod-to-json-schema": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-checkpoint": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-1.0.4.tgz",
|
||||
"integrity": "sha512-1y5MgZ0gXXrtmoy56e3kaBChI3GwFPIKl27xkrHwN+VE/3iUsyr9gO3Jtp7kdKAe6diZGbcas5bdC/r0yUwTZA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uuid": "^14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.1.44"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-checkpoint/node_modules/uuid": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz",
|
||||
"integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist-node/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk": {
|
||||
"version": "1.9.13",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.9.13.tgz",
|
||||
"integrity": "sha512-c3yq7kfGncMxJT9YCua5KGytTQbEyZhhjt6y3wSFHvuhNXGTJV5kBctK6jh1xFrWKwjFcdqRtVBE8pqz1GiSrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@langchain/protocol": "^0.0.16",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"p-queue": "^9.0.1",
|
||||
"p-retry": "^7.1.1",
|
||||
"uuid": "^14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.1.44",
|
||||
"react": "^18 || ^19",
|
||||
"react-dom": "^18 || ^19",
|
||||
"svelte": "^4.0.0 || ^5.0.0",
|
||||
"vue": "^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"svelte": {
|
||||
"optional": true
|
||||
},
|
||||
"vue": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk/node_modules/@langchain/protocol": {
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/protocol/-/protocol-0.0.16.tgz",
|
||||
"integrity": "sha512-ws+J7MaHyhO5dG7f0vdyHQiUn9hoCnki0f3crJPa4MCTGzcRC39jYSCghyrGtBPYQnZbUQiGyRVpW3z3M8IpJg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk/node_modules/eventemitter3": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
|
||||
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk/node_modules/p-queue": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz",
|
||||
"integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^5.0.4",
|
||||
"p-timeout": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk/node_modules/p-timeout": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz",
|
||||
"integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph-sdk/node_modules/uuid": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz",
|
||||
"integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist-node/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/langgraph/node_modules/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/openai": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-1.4.4.tgz",
|
||||
"integrity": "sha512-mRr/X5rvlwPj6cSXPxbL+CtOqYANO1/+CQ3Z+5t48kWnrlgPYOazmA+UAWvqQOuwJ6LaYn3SFrt43rR4lte/Ow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"openai": "^6.32.0",
|
||||
"zod": "^3.25.76 || ^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.1.39"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/protocol": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/protocol/-/protocol-0.0.15.tgz",
|
||||
"integrity": "sha512-MllvbpMjqHevUm+v94M422mH7XKN+wGCvJRBVROTWBotEDOATYB4Ktk2UheYP859y9o2LlhtPek5t1T9eyfAbQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lukeed/csprng": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
|
||||
"integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@lukeed/uuid": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/uuid/-/uuid-2.0.1.tgz",
|
||||
"integrity": "sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/csprng": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobuf-ts/protoc": {
|
||||
"version": "2.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz",
|
||||
"integrity": "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"protoc": "protoc.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-core": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.8.2.tgz",
|
||||
"integrity": "sha512-5FDy6l8chpzUfJcNlIcyqYQq4+JTUynlVoCeCUuVz+l+6W0PXg+ljKp34R4yLVCcY5VVZohuW+HH0VLWdwYVAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/uuid": "^2.0.0",
|
||||
"@segment/analytics-generic-utils": "1.2.0",
|
||||
"dset": "^3.1.4",
|
||||
"tslib": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-generic-utils": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-generic-utils/-/analytics-generic-utils-1.2.0.tgz",
|
||||
"integrity": "sha512-DfnW6mW3YQOLlDQQdR89k4EqfHb0g/3XvBXkovH1FstUN93eL1kfW9CsDcVQyH3bAC5ZsFyjA/o/1Q2j0QeoWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@segment/analytics-node": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@segment/analytics-node/-/analytics-node-2.3.0.tgz",
|
||||
"integrity": "sha512-fOXLL8uY0uAWw/sTLmezze80hj8YGgXXlAfvSS6TUmivk4D/SP0C0sxnbpFdkUzWg2zT64qWIZj26afEtSnxUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/uuid": "^2.0.0",
|
||||
"@segment/analytics-core": "1.8.2",
|
||||
"@segment/analytics-generic-utils": "1.2.0",
|
||||
"buffer": "^6.0.3",
|
||||
"jose": "^5.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"tslib": "^2.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/html-to-text": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz",
|
||||
"integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.19.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
|
||||
"integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/compare-versions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
|
||||
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dset": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
|
||||
"integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-json-patch": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz",
|
||||
"integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/graphql": {
|
||||
"version": "16.14.1",
|
||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.1.tgz",
|
||||
"integrity": "sha512-cQOsSMS/IrDz82PVyRDvf/Q1F/bRbBVjJlh+xYOkI1qw2bWRvWGiWc+m2O0d6l4Bt1fyY+8kzJ8JFWGJqNeDBg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/is-network-error": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz",
|
||||
"integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
|
||||
"integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tiktoken": {
|
||||
"version": "1.0.21",
|
||||
"resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
|
||||
"integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1"
|
||||
}
|
||||
},
|
||||
"node_modules/langchain": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/langchain/-/langchain-1.3.4.tgz",
|
||||
"integrity": "sha512-umrD+ZC6vr0Q0U1lC5PoIMMQqgnP+7QhaIdAXCeZiSX2GPVBiVR7Ed2ZR+3MPvz1yWrRtIm17wPaovkND+wOXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@langchain/langgraph": "^1.2.9",
|
||||
"@langchain/langgraph-checkpoint": "^1.0.1",
|
||||
"langsmith": ">=0.5.0 <1.0.0",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.25.76 || ^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.1.41"
|
||||
}
|
||||
},
|
||||
"node_modules/langsmith": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.7.3.tgz",
|
||||
"integrity": "sha512-Gg+IeRGoF1/aStu80aEnIXJCu+N6+4NoV4tAVFS51ZPRBsRa2KG0LkS7K7/ryZ/yES7O9xdqah5QuuWMIeMjQw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-queue": "6.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "*",
|
||||
"@opentelemetry/exporter-trace-otlp-proto": "*",
|
||||
"@opentelemetry/sdk-trace-base": "*",
|
||||
"openai": "*",
|
||||
"ws": ">=7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentelemetry/api": {
|
||||
"optional": true
|
||||
},
|
||||
"@opentelemetry/exporter-trace-otlp-proto": {
|
||||
"optional": true
|
||||
},
|
||||
"@opentelemetry/sdk-trace-base": {
|
||||
"optional": true
|
||||
},
|
||||
"openai": {
|
||||
"optional": true
|
||||
},
|
||||
"ws": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/mustache": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
|
||||
"integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mustache": "bin/mustache"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/openai": {
|
||||
"version": "6.41.0",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-6.41.0.tgz",
|
||||
"integrity": "sha512-IGWPopZq6Rjoynjfb3NSLf/z2MTw7UiOsm9TAjPGAjUESH7Uq41Trg4QWehBEn58p74i+m7uoRPV2vXcpPXhyA==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.25 || ^4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ws": {
|
||||
"optional": true
|
||||
},
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-queue": {
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
|
||||
"integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^4.0.4",
|
||||
"p-timeout": "^3.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-retry": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-7.1.1.tgz",
|
||||
"integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-network-error": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-timeout": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-finally": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/partial-json": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz",
|
||||
"integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/untruncate-json": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/untruncate-json/-/untruncate-json-0.0.1.tgz",
|
||||
"integrity": "sha512-4W9enDK4X1y1s2S/Rz7ysw6kDuMS3VmRjMFg7GZrNO+98OSe+x5Lh7PKYoVjy3lW/1wmhs6HW0lusnQRHgMarA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
|
||||
"integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/esm/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.76",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zod-to-json-schema": {
|
||||
"version": "3.25.2",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
|
||||
"integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.28 || ^4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ const integrationsDir = path.join(repoRoot, "examples", "integrations");
|
||||
const migratedIntegrations = [
|
||||
"crewai-flows",
|
||||
"llamaindex",
|
||||
"langgraph-fastapi",
|
||||
"pydantic-ai",
|
||||
"mcp-apps",
|
||||
"agent-spec",
|
||||
|
||||
Reference in New Issue
Block a user