@swarmclawai/swarmclaw 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -150
- package/package.json +1 -1
- package/src/app/api/agents/[id]/route.ts +26 -0
- package/src/app/api/agents/[id]/thread/route.ts +37 -9
- package/src/app/api/agents/route.ts +13 -2
- package/src/app/api/auth/route.ts +76 -7
- package/src/app/api/chatrooms/[id]/chat/route.ts +7 -2
- package/src/app/api/{sessions → chats}/[id]/browser/route.ts +5 -1
- package/src/app/api/{sessions → chats}/[id]/chat/route.ts +7 -3
- package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
- package/src/app/api/chats/[id]/main-loop/route.ts +13 -0
- package/src/app/api/{sessions → chats}/[id]/messages/route.ts +19 -13
- package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/route.ts +22 -52
- package/src/app/api/{sessions → chats}/[id]/stop/route.ts +6 -1
- package/src/app/api/{sessions → chats}/route.ts +21 -7
- package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
- package/src/app/api/connectors/doctor/route.ts +13 -0
- package/src/app/api/files/open/route.ts +16 -14
- package/src/app/api/memory/maintenance/route.ts +11 -1
- package/src/app/api/openclaw/agent-files/route.ts +27 -4
- package/src/app/api/openclaw/skills/route.ts +11 -3
- package/src/app/api/plugins/dependencies/route.ts +24 -0
- package/src/app/api/plugins/install/route.ts +15 -92
- package/src/app/api/plugins/route.ts +6 -26
- package/src/app/api/plugins/settings/route.ts +40 -0
- package/src/app/api/plugins/ui/route.ts +1 -0
- package/src/app/api/settings/route.ts +49 -7
- package/src/app/api/tasks/[id]/route.ts +15 -6
- package/src/app/api/tasks/bulk/route.ts +2 -2
- package/src/app/api/tasks/route.ts +9 -4
- package/src/app/api/usage/route.ts +30 -0
- package/src/app/api/webhooks/[id]/route.ts +8 -1
- package/src/app/page.tsx +9 -2
- package/src/cli/index.js +39 -33
- package/src/cli/index.ts +43 -49
- package/src/cli/spec.js +29 -27
- package/src/components/agents/agent-card.tsx +16 -13
- package/src/components/agents/agent-chat-list.tsx +104 -4
- package/src/components/agents/agent-list.tsx +54 -22
- package/src/components/agents/agent-sheet.tsx +209 -18
- package/src/components/agents/cron-job-form.tsx +3 -3
- package/src/components/agents/inspector-panel.tsx +110 -50
- package/src/components/auth/access-key-gate.tsx +36 -97
- package/src/components/auth/setup-wizard.tsx +5 -38
- package/src/components/chat/chat-area.tsx +39 -27
- package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +7 -23
- package/src/components/chat/chat-header.tsx +299 -314
- package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +11 -14
- package/src/components/chat/chat-tool-toggles.tsx +26 -17
- package/src/components/chat/checkpoint-timeline.tsx +4 -4
- package/src/components/chat/message-bubble.tsx +4 -1
- package/src/components/chat/message-list.tsx +5 -3
- package/src/components/chat/session-debug-panel.tsx +1 -1
- package/src/components/chat/tool-request-banner.tsx +3 -3
- package/src/components/chatrooms/agent-hover-card.tsx +3 -3
- package/src/components/chatrooms/chatroom-tool-request-banner.tsx +2 -2
- package/src/components/chatrooms/chatroom-view.tsx +347 -205
- package/src/components/connectors/connector-list.tsx +265 -127
- package/src/components/connectors/connector-sheet.tsx +218 -1
- package/src/components/home/home-view.tsx +129 -5
- package/src/components/layout/app-layout.tsx +392 -182
- package/src/components/layout/mobile-header.tsx +26 -8
- package/src/components/plugins/plugin-list.tsx +487 -254
- package/src/components/plugins/plugin-sheet.tsx +236 -13
- package/src/components/projects/project-detail.tsx +183 -0
- package/src/components/settings/gateway-connection-panel.tsx +1 -1
- package/src/components/shared/agent-picker-list.tsx +2 -2
- package/src/components/shared/command-palette.tsx +111 -25
- package/src/components/shared/settings/plugin-manager.tsx +20 -4
- package/src/components/shared/settings/section-capability-policy.tsx +105 -0
- package/src/components/shared/settings/section-heartbeat.tsx +78 -1
- package/src/components/shared/settings/section-orchestrator.tsx +3 -3
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
- package/src/components/shared/settings/section-secrets.tsx +6 -6
- package/src/components/shared/settings/section-user-preferences.tsx +1 -1
- package/src/components/shared/settings/section-voice.tsx +5 -1
- package/src/components/shared/settings/section-web-search.tsx +10 -2
- package/src/components/shared/settings/settings-page.tsx +244 -56
- package/src/components/tasks/approvals-panel.tsx +205 -18
- package/src/components/tasks/task-board.tsx +242 -46
- package/src/components/usage/metrics-dashboard.tsx +147 -1
- package/src/components/wallets/wallet-panel.tsx +17 -5
- package/src/components/webhooks/webhook-sheet.tsx +8 -8
- package/src/lib/auth.ts +17 -0
- package/src/lib/chat-streaming-state.test.ts +108 -0
- package/src/lib/chat-streaming-state.ts +108 -0
- package/src/lib/chat.ts +1 -1
- package/src/lib/{sessions.ts → chats.ts} +28 -18
- package/src/lib/openclaw-agent-id.test.ts +14 -0
- package/src/lib/openclaw-agent-id.ts +31 -0
- package/src/lib/providers/claude-cli.ts +1 -1
- package/src/lib/server/agent-assignment.test.ts +112 -0
- package/src/lib/server/agent-assignment.ts +169 -0
- package/src/lib/server/approval-connector-notify.test.ts +253 -0
- package/src/lib/server/approvals-auto-approve.test.ts +205 -0
- package/src/lib/server/approvals.ts +483 -75
- package/src/lib/server/autonomy-runtime.test.ts +341 -0
- package/src/lib/server/browser-state.test.ts +118 -0
- package/src/lib/server/browser-state.ts +123 -0
- package/src/lib/server/build-llm.test.ts +36 -0
- package/src/lib/server/build-llm.ts +11 -4
- package/src/lib/server/builtin-plugins.ts +34 -0
- package/src/lib/server/capability-router.ts +10 -8
- package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
- package/src/lib/server/chat-execution-tool-events.test.ts +134 -0
- package/src/lib/server/chat-execution.ts +285 -165
- package/src/lib/server/chatroom-health.test.ts +26 -0
- package/src/lib/server/chatroom-health.ts +2 -3
- package/src/lib/server/chatroom-helpers.test.ts +67 -2
- package/src/lib/server/chatroom-helpers.ts +48 -8
- package/src/lib/server/connectors/discord.ts +175 -11
- package/src/lib/server/connectors/doctor.test.ts +80 -0
- package/src/lib/server/connectors/doctor.ts +116 -0
- package/src/lib/server/connectors/manager.ts +948 -112
- package/src/lib/server/connectors/policy.test.ts +222 -0
- package/src/lib/server/connectors/policy.ts +452 -0
- package/src/lib/server/connectors/slack.ts +188 -9
- package/src/lib/server/connectors/telegram.ts +65 -15
- package/src/lib/server/connectors/thread-context.test.ts +44 -0
- package/src/lib/server/connectors/thread-context.ts +72 -0
- package/src/lib/server/connectors/types.ts +41 -11
- package/src/lib/server/cost.ts +34 -1
- package/src/lib/server/daemon-state.ts +61 -3
- package/src/lib/server/data-dir.ts +13 -0
- package/src/lib/server/delegation-jobs.test.ts +140 -0
- package/src/lib/server/delegation-jobs.ts +248 -0
- package/src/lib/server/document-utils.test.ts +47 -0
- package/src/lib/server/document-utils.ts +397 -0
- package/src/lib/server/heartbeat-service.ts +14 -40
- package/src/lib/server/heartbeat-source.test.ts +22 -0
- package/src/lib/server/heartbeat-source.ts +7 -0
- package/src/lib/server/identity-continuity.test.ts +77 -0
- package/src/lib/server/identity-continuity.ts +127 -0
- package/src/lib/server/mailbox-utils.ts +347 -0
- package/src/lib/server/main-agent-loop.ts +28 -1103
- package/src/lib/server/memory-db.ts +4 -6
- package/src/lib/server/memory-tiers.ts +40 -0
- package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
- package/src/lib/server/openclaw-agent-resolver.ts +128 -0
- package/src/lib/server/openclaw-exec-config.ts +5 -6
- package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
- package/src/lib/server/openclaw-skills-normalize.ts +136 -0
- package/src/lib/server/openclaw-sync.ts +3 -2
- package/src/lib/server/orchestrator-lg.ts +20 -9
- package/src/lib/server/orchestrator.ts +7 -7
- package/src/lib/server/playwright-proxy.mjs +27 -3
- package/src/lib/server/plugins.test.ts +207 -0
- package/src/lib/server/plugins.ts +927 -66
- package/src/lib/server/provider-health.ts +38 -6
- package/src/lib/server/queue.ts +13 -28
- package/src/lib/server/scheduler.ts +2 -0
- package/src/lib/server/session-archive-memory.test.ts +85 -0
- package/src/lib/server/session-archive-memory.ts +230 -0
- package/src/lib/server/session-mailbox.ts +8 -18
- package/src/lib/server/session-reset-policy.test.ts +99 -0
- package/src/lib/server/session-reset-policy.ts +311 -0
- package/src/lib/server/session-run-manager.ts +33 -82
- package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
- package/src/lib/server/session-tools/calendar.ts +366 -0
- package/src/lib/server/session-tools/canvas.ts +1 -1
- package/src/lib/server/session-tools/chatroom.ts +4 -2
- package/src/lib/server/session-tools/connector.ts +114 -10
- package/src/lib/server/session-tools/context.ts +21 -5
- package/src/lib/server/session-tools/crawl.ts +447 -0
- package/src/lib/server/session-tools/crud.ts +74 -28
- package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
- package/src/lib/server/session-tools/delegate.ts +497 -24
- package/src/lib/server/session-tools/discovery.ts +24 -6
- package/src/lib/server/session-tools/document.ts +283 -0
- package/src/lib/server/session-tools/edit_file.ts +4 -2
- package/src/lib/server/session-tools/email.ts +320 -0
- package/src/lib/server/session-tools/extract.ts +137 -0
- package/src/lib/server/session-tools/file-normalize.test.ts +93 -0
- package/src/lib/server/session-tools/file-send.test.ts +84 -1
- package/src/lib/server/session-tools/file.ts +241 -25
- package/src/lib/server/session-tools/git.ts +1 -1
- package/src/lib/server/session-tools/http.ts +1 -1
- package/src/lib/server/session-tools/human-loop.ts +227 -0
- package/src/lib/server/session-tools/image-gen.ts +380 -0
- package/src/lib/server/session-tools/index.ts +130 -50
- package/src/lib/server/session-tools/mailbox.ts +276 -0
- package/src/lib/server/session-tools/memory.ts +172 -3
- package/src/lib/server/session-tools/monitor.ts +151 -8
- package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
- package/src/lib/server/session-tools/openclaw-nodes.ts +1 -1
- package/src/lib/server/session-tools/openclaw-workspace.ts +1 -1
- package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
- package/src/lib/server/session-tools/platform.ts +148 -7
- package/src/lib/server/session-tools/plugin-creator.ts +89 -26
- package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
- package/src/lib/server/session-tools/replicate.ts +301 -0
- package/src/lib/server/session-tools/sample-ui.ts +1 -1
- package/src/lib/server/session-tools/sandbox.ts +4 -2
- package/src/lib/server/session-tools/schedule.ts +24 -12
- package/src/lib/server/session-tools/session-info.ts +43 -7
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
- package/src/lib/server/session-tools/shell.ts +5 -2
- package/src/lib/server/session-tools/subagent.ts +194 -28
- package/src/lib/server/session-tools/table.ts +587 -0
- package/src/lib/server/session-tools/wallet.ts +42 -12
- package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
- package/src/lib/server/session-tools/web.ts +926 -91
- package/src/lib/server/storage.ts +255 -16
- package/src/lib/server/stream-agent-chat.ts +116 -268
- package/src/lib/server/structured-extract.test.ts +72 -0
- package/src/lib/server/structured-extract.ts +373 -0
- package/src/lib/server/task-mention.test.ts +16 -2
- package/src/lib/server/task-mention.ts +61 -10
- package/src/lib/server/tool-aliases.ts +66 -18
- package/src/lib/server/tool-capability-policy.test.ts +9 -9
- package/src/lib/server/tool-capability-policy.ts +38 -27
- package/src/lib/server/tool-retry.ts +2 -0
- package/src/lib/server/watch-jobs.test.ts +173 -0
- package/src/lib/server/watch-jobs.ts +532 -0
- package/src/lib/server/ws-hub.ts +5 -3
- package/src/lib/tool-definitions.ts +4 -0
- package/src/lib/validation/schemas.test.ts +26 -0
- package/src/lib/validation/schemas.ts +10 -1
- package/src/lib/ws-client.ts +14 -12
- package/src/proxy.ts +5 -5
- package/src/stores/use-app-store.ts +5 -11
- package/src/stores/use-chat-store.ts +38 -9
- package/src/types/index.ts +352 -47
- package/src/app/api/sessions/[id]/main-loop/route.ts +0 -94
- package/src/components/sessions/new-session-sheet.tsx +0 -253
- package/src/lib/server/main-session.ts +0 -24
- package/src/lib/server/session-run-manager.test.ts +0 -23
- /package/src/app/api/{sessions → chats}/[id]/clear/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/deploy/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/devserver/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/edit-resend/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/fork/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/mailbox/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/retry/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
6
|
-
import {
|
|
7
|
-
import { fetchMessages } from '@/lib/
|
|
6
|
+
import { ChatCard } from './chat-card'
|
|
7
|
+
import { fetchMessages } from '@/lib/chats'
|
|
8
8
|
import { toast } from 'sonner'
|
|
9
9
|
import { Skeleton } from '@/components/shared/skeleton'
|
|
10
10
|
import { EmptyState } from '@/components/shared/empty-state'
|
|
@@ -14,17 +14,17 @@ interface Props {
|
|
|
14
14
|
onSelect?: () => void
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
type SessionFilter = 'all' | 'active'
|
|
17
|
+
type SessionFilter = 'all' | 'active'
|
|
18
18
|
type SortMode = 'lastActive' | 'name' | 'messages'
|
|
19
19
|
|
|
20
|
-
export function
|
|
20
|
+
export function ChatList({ inSidebar, onSelect }: Props) {
|
|
21
21
|
const sessions = useAppStore((s) => s.sessions)
|
|
22
22
|
const currentUser = useAppStore((s) => s.currentUser)
|
|
23
23
|
const currentSessionId = useAppStore((s) => s.currentSessionId)
|
|
24
24
|
const setCurrentSession = useAppStore((s) => s.setCurrentSession)
|
|
25
25
|
const loadSessions = useAppStore((s) => s.loadSessions)
|
|
26
26
|
const loadConnectors = useAppStore((s) => s.loadConnectors)
|
|
27
|
-
const
|
|
27
|
+
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
28
28
|
const clearSessions = useAppStore((s) => s.clearSessions)
|
|
29
29
|
const togglePinSession = useAppStore((s) => s.togglePinSession)
|
|
30
30
|
const markChatRead = useAppStore((s) => s.markChatRead)
|
|
@@ -44,7 +44,6 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
44
44
|
|
|
45
45
|
const allUserSessions = useMemo(() => {
|
|
46
46
|
return Object.values(sessions).filter((s) => {
|
|
47
|
-
if (s.name === '__main__') return false
|
|
48
47
|
const owner = (s.user || '').toLowerCase()
|
|
49
48
|
const isPlatformOwned = owner === 'system' || owner === 'connector' || owner === 'swarm'
|
|
50
49
|
const isCurrentUserOwned = !!currentUser && owner === currentUser.toLowerCase()
|
|
@@ -59,8 +58,6 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
59
58
|
.filter((s) => {
|
|
60
59
|
if (search && !s.name.toLowerCase().includes(search.toLowerCase())) return false
|
|
61
60
|
if (typeFilter === 'active' && !s.active) return false
|
|
62
|
-
if (typeFilter === 'human' && s.sessionType === 'orchestrated') return false
|
|
63
|
-
if (typeFilter === 'orchestrated' && s.sessionType !== 'orchestrated') return false
|
|
64
61
|
return true
|
|
65
62
|
})
|
|
66
63
|
.sort((a, b) => {
|
|
@@ -116,8 +113,8 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
116
113
|
</svg>
|
|
117
114
|
}
|
|
118
115
|
title="No chats yet"
|
|
119
|
-
subtitle="Create
|
|
120
|
-
action={!inSidebar ? { label: '+ New
|
|
116
|
+
subtitle="Create an agent to open its persistent thread"
|
|
117
|
+
action={!inSidebar ? { label: '+ New Agent', onClick: () => setAgentSheetOpen(true) } : undefined}
|
|
121
118
|
/>
|
|
122
119
|
)
|
|
123
120
|
}
|
|
@@ -126,7 +123,7 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
126
123
|
<div className="flex-1 flex flex-col overflow-y-auto">
|
|
127
124
|
{/* Filter tabs — always visible when sessions exist */}
|
|
128
125
|
<div className="flex items-center gap-1 px-4 pt-2 pb-1 shrink-0">
|
|
129
|
-
{(['all', 'active'
|
|
126
|
+
{(['all', 'active'] as SessionFilter[]).map((f) => (
|
|
130
127
|
<button
|
|
131
128
|
key={f}
|
|
132
129
|
onClick={() => setTypeFilter(f)}
|
|
@@ -134,7 +131,7 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
134
131
|
${typeFilter === f ? 'bg-accent-soft text-accent-bright' : 'bg-transparent text-text-3 hover:text-text-2'}`}
|
|
135
132
|
style={{ fontFamily: 'inherit' }}
|
|
136
133
|
>
|
|
137
|
-
{f === 'all' ? 'All' :
|
|
134
|
+
{f === 'all' ? 'All' : 'Active'}
|
|
138
135
|
</button>
|
|
139
136
|
))}
|
|
140
137
|
{filtered.length > 0 && (
|
|
@@ -186,7 +183,7 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
186
183
|
<div className="flex flex-col gap-1 px-2 pb-4">
|
|
187
184
|
{filtered.map((s) => (
|
|
188
185
|
<div key={s.id} className="group/pin relative">
|
|
189
|
-
<
|
|
186
|
+
<ChatCard
|
|
190
187
|
session={s}
|
|
191
188
|
active={s.id === currentSessionId}
|
|
192
189
|
onClick={() => handleSelect(s.id)}
|
|
@@ -210,7 +207,7 @@ export function SessionList({ inSidebar, onSelect }: Props) {
|
|
|
210
207
|
) : (
|
|
211
208
|
<div className="flex-1 flex flex-col items-center justify-center gap-3 text-text-3 p-8 text-center">
|
|
212
209
|
<p className="text-[13px] text-text-3/50">
|
|
213
|
-
No {typeFilter === '
|
|
210
|
+
No {typeFilter === 'active' ? 'active' : typeFilter} chats{search ? ` matching "${search}"` : ''}
|
|
214
211
|
</p>
|
|
215
212
|
</div>
|
|
216
213
|
)}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import { useState, useRef, useEffect } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { api } from '@/lib/api-client'
|
|
6
|
-
import { AVAILABLE_TOOLS, PLATFORM_TOOLS
|
|
6
|
+
import { AVAILABLE_TOOLS, PLATFORM_TOOLS } from '@/lib/tool-definitions'
|
|
7
7
|
import type { ToolDefinition } from '@/lib/tool-definitions'
|
|
8
8
|
import type { Session } from '@/types'
|
|
9
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@/components/ui/tooltip'
|
|
9
10
|
|
|
10
11
|
const TOOL_GROUPS: { label: string; tools: ToolDefinition[] }[] = [
|
|
11
12
|
{ label: 'Plugins', tools: AVAILABLE_TOOLS },
|
|
@@ -26,7 +27,7 @@ export function ChatToolToggles({ session }: Props) {
|
|
|
26
27
|
const skills = useAppStore((s) => s.skills)
|
|
27
28
|
|
|
28
29
|
const agent = session.agentId ? agents[session.agentId] : null
|
|
29
|
-
const sessionTools: string[] = session.
|
|
30
|
+
const sessionTools: string[] = session.plugins || []
|
|
30
31
|
|
|
31
32
|
// Agent's skill IDs
|
|
32
33
|
const agentSkillIds: string[] = agent?.skillIds || []
|
|
@@ -44,7 +45,7 @@ export function ChatToolToggles({ session }: Props) {
|
|
|
44
45
|
const updated = sessionTools.includes(toolId)
|
|
45
46
|
? sessionTools.filter((t) => t !== toolId)
|
|
46
47
|
: [...sessionTools, toolId]
|
|
47
|
-
await api('PUT', `/
|
|
48
|
+
await api('PUT', `/chats/${session.id}`, { plugins: updated })
|
|
48
49
|
loadSessions()
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -69,26 +70,33 @@ export function ChatToolToggles({ session }: Props) {
|
|
|
69
70
|
{open && (
|
|
70
71
|
<div className="absolute top-full left-0 mt-1.5 w-[260px] max-h-[420px] overflow-y-auto rounded-[12px] border border-white/[0.08] shadow-xl z-[120] overflow-hidden"
|
|
71
72
|
style={{ animation: 'fade-in 0.15s ease', backgroundColor: '#171a2b' }}>
|
|
72
|
-
|
|
73
|
+
<TooltipProvider delayDuration={300}>
|
|
73
74
|
{TOOL_GROUPS.map((group, gi) => (
|
|
74
75
|
<div key={group.label} className={`px-3 pb-1 ${gi === 0 ? 'pt-3' : 'pt-1 border-t border-white/[0.04]'}`}>
|
|
75
76
|
<p className="text-[10px] font-600 text-text-3/60 uppercase tracking-wider mb-2">{group.label}</p>
|
|
76
77
|
{group.tools.map((tool) => {
|
|
77
78
|
const enabled = sessionTools.includes(tool.id)
|
|
78
79
|
return (
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
<Tooltip key={tool.id}>
|
|
81
|
+
<TooltipTrigger asChild>
|
|
82
|
+
<label className="flex items-center gap-2.5 py-1.5 cursor-pointer">
|
|
83
|
+
<div
|
|
84
|
+
onClick={() => toggleTool(tool.id)}
|
|
85
|
+
className={`w-8 h-[18px] rounded-full transition-all duration-200 relative cursor-pointer shrink-0
|
|
86
|
+
${enabled ? 'bg-accent-bright' : 'bg-white/[0.12]'}`}
|
|
87
|
+
>
|
|
88
|
+
<div className={`absolute top-[2px] w-[14px] h-[14px] rounded-full bg-white transition-all duration-200
|
|
89
|
+
${enabled ? 'left-[16px]' : 'left-[2px]'}`} />
|
|
90
|
+
</div>
|
|
91
|
+
<span className={`text-[12px] ${enabled ? 'text-text-2' : 'text-text-3/70'}`}>
|
|
92
|
+
{tool.label}
|
|
93
|
+
</span>
|
|
94
|
+
</label>
|
|
95
|
+
</TooltipTrigger>
|
|
96
|
+
<TooltipContent side="right" sideOffset={8} className="max-w-[200px] bg-[#1e2140] text-text-2 border border-white/[0.08] text-[11px] leading-snug px-2.5 py-1.5">
|
|
97
|
+
{tool.description}
|
|
98
|
+
</TooltipContent>
|
|
99
|
+
</Tooltip>
|
|
92
100
|
)
|
|
93
101
|
})}
|
|
94
102
|
</div>
|
|
@@ -110,6 +118,7 @@ export function ChatToolToggles({ session }: Props) {
|
|
|
110
118
|
</div>
|
|
111
119
|
)}
|
|
112
120
|
|
|
121
|
+
</TooltipProvider>
|
|
113
122
|
<div className="px-3 py-2 border-t border-white/[0.04] bg-white/[0.02]">
|
|
114
123
|
<p className="text-[10px] text-text-3/70">Changes apply to the next message</p>
|
|
115
124
|
</div>
|
|
@@ -26,7 +26,7 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
26
26
|
const load = async () => {
|
|
27
27
|
setLoading(true)
|
|
28
28
|
try {
|
|
29
|
-
const data = await api<Checkpoint[]>('GET', `/
|
|
29
|
+
const data = await api<Checkpoint[]>('GET', `/chats/${sessionId}/checkpoints`)
|
|
30
30
|
setCheckpoints(data)
|
|
31
31
|
} catch (err) {
|
|
32
32
|
console.error('Failed to load checkpoints', err)
|
|
@@ -45,7 +45,7 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
45
45
|
|
|
46
46
|
setRestoringId(checkpoint.checkpointId)
|
|
47
47
|
try {
|
|
48
|
-
await api('POST', `/
|
|
48
|
+
await api('POST', `/chats/${sessionId}/restore`, {
|
|
49
49
|
checkpointId: checkpoint.checkpointId,
|
|
50
50
|
timestamp: checkpoint.createdAt
|
|
51
51
|
})
|
|
@@ -67,8 +67,8 @@ export function CheckpointTimeline({ sessionId }: Props) {
|
|
|
67
67
|
if (checkpoints.length === 0) {
|
|
68
68
|
return (
|
|
69
69
|
<div className="p-8 text-center">
|
|
70
|
-
<p className="text-text-3 text-[13px]">No checkpoints found for this
|
|
71
|
-
<p className="text-[11px] text-text-3/50 mt-1">
|
|
70
|
+
<p className="text-text-3 text-[13px]">No checkpoints found for this chat.</p>
|
|
71
|
+
<p className="text-[11px] text-text-3/50 mt-1">Checkpoint restore is only available when a backend created checkpoints for this chat.</p>
|
|
72
72
|
</div>
|
|
73
73
|
)
|
|
74
74
|
}
|
|
@@ -243,7 +243,10 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
243
243
|
const delegationSource = !isUser && message.kind === 'system' ? parseDelegationSource(message.text || '') : null
|
|
244
244
|
// Detect task completion system messages (delegated or direct)
|
|
245
245
|
const taskCompletion = !isUser && message.kind === 'system' ? parseTaskCompletion(message.text || '') : null
|
|
246
|
-
const
|
|
246
|
+
const rawDisplayText = delegationSource ? delegationSource.rest : message.text
|
|
247
|
+
const displayText = rawDisplayText
|
|
248
|
+
? rawDisplayText.split('\n').filter((l) => !/\[(MAIN_LOOP_META|MAIN_LOOP_PLAN|MAIN_LOOP_REVIEW|AGENT_HEARTBEAT_META)\]/.test(l)).join('\n').trim()
|
|
249
|
+
: ''
|
|
247
250
|
|
|
248
251
|
const handleCopy = useCallback(() => {
|
|
249
252
|
void copyTextToClipboard(message.text).then((copiedText) => {
|
|
@@ -5,6 +5,7 @@ import type { Message } from '@/types'
|
|
|
5
5
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
6
6
|
import { useAppStore } from '@/stores/use-app-store'
|
|
7
7
|
import { api } from '@/lib/api-client'
|
|
8
|
+
import { shouldHidePersistedStreamingAssistantMessage } from '@/lib/chat-streaming-state'
|
|
8
9
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
9
10
|
import { MessageBubble } from './message-bubble'
|
|
10
11
|
import { StreamingBubble } from './streaming-bubble'
|
|
@@ -129,7 +130,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
129
130
|
if (!msg) return
|
|
130
131
|
const next = !msg.bookmarked
|
|
131
132
|
try {
|
|
132
|
-
await api('PUT', `/
|
|
133
|
+
await api('PUT', `/chats/${sessionId}/messages`, { messageIndex: index, bookmarked: next })
|
|
133
134
|
const updated = [...messages]
|
|
134
135
|
updated[index] = { ...updated[index], bookmarked: next }
|
|
135
136
|
setMessages(updated)
|
|
@@ -164,6 +165,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
164
165
|
|
|
165
166
|
const displayedMessages: Message[] = []
|
|
166
167
|
for (const msg of messages) {
|
|
168
|
+
if (shouldHidePersistedStreamingAssistantMessage(msg, { localStreaming: streaming, displayText })) continue
|
|
167
169
|
const isHeartbeat = isHeartbeatMessage(msg)
|
|
168
170
|
|
|
169
171
|
// Visibility filtering based on settings
|
|
@@ -469,7 +471,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
469
471
|
type="button"
|
|
470
472
|
onClick={async () => {
|
|
471
473
|
try {
|
|
472
|
-
await api('DELETE', `/
|
|
474
|
+
await api('DELETE', `/chats/${sessionId}/messages`, { messageIndex: originalIndex })
|
|
473
475
|
setMessages(messages.filter((_: Message, idx: number) => idx !== originalIndex))
|
|
474
476
|
} catch { /* best-effort */ }
|
|
475
477
|
}}
|
|
@@ -514,7 +516,7 @@ export function MessageList({ messages, streaming, connectorFilter = null }: Pro
|
|
|
514
516
|
|
|
515
517
|
return (
|
|
516
518
|
<div
|
|
517
|
-
key={`${sessionId}-${msg.
|
|
519
|
+
key={`${sessionId}-${msg.role}-${originalIndex >= 0 ? originalIndex : i}`}
|
|
518
520
|
data-message-index={i}
|
|
519
521
|
style={{
|
|
520
522
|
animation: `${msg.role === 'user' ? 'msg-in-right' : 'msg-in-left'} 0.4s var(--ease-spring) both`,
|
|
@@ -209,7 +209,7 @@ export function SessionDebugPanel({ messages, open, onClose }: Props) {
|
|
|
209
209
|
{currentSessionId ? (
|
|
210
210
|
<CheckpointTimeline sessionId={currentSessionId} />
|
|
211
211
|
) : (
|
|
212
|
-
<div className="p-12 text-center text-text-3">No active
|
|
212
|
+
<div className="p-12 text-center text-text-3">No active chat</div>
|
|
213
213
|
)}
|
|
214
214
|
</div>
|
|
215
215
|
)}
|
|
@@ -62,13 +62,13 @@ export function ToolRequestBanner({ text, toolOutputs = [] }: Props) {
|
|
|
62
62
|
|
|
63
63
|
const handleGrant = async (toolId: string) => {
|
|
64
64
|
if (!sid || !session) return
|
|
65
|
-
const currentTools: string[] = session.
|
|
65
|
+
const currentTools: string[] = session.plugins || []
|
|
66
66
|
if (currentTools.includes(toolId)) {
|
|
67
67
|
setGranted((prev) => new Set(prev).add(toolId))
|
|
68
68
|
return
|
|
69
69
|
}
|
|
70
70
|
const updated = [...currentTools, toolId]
|
|
71
|
-
await api('PUT', `/
|
|
71
|
+
await api('PUT', `/chats/${sid}`, { plugins: updated })
|
|
72
72
|
await loadSessions()
|
|
73
73
|
const newGranted = new Set(granted).add(toolId)
|
|
74
74
|
setGranted(newGranted)
|
|
@@ -108,7 +108,7 @@ export function ToolRequestBanner({ text, toolOutputs = [] }: Props) {
|
|
|
108
108
|
return (
|
|
109
109
|
<div className="max-w-[85%] md:max-w-[72%] flex flex-col gap-2 mt-2">
|
|
110
110
|
{pluginRequests.map(({ pluginId, reason }) => {
|
|
111
|
-
const isGranted = granted.has(pluginId) || (session?.
|
|
111
|
+
const isGranted = granted.has(pluginId) || (session?.plugins || []).includes(pluginId)
|
|
112
112
|
const isDenied = denied.has(pluginId)
|
|
113
113
|
const label = TOOL_LABELS[pluginId] || pluginId
|
|
114
114
|
return (
|
|
@@ -19,7 +19,7 @@ const ALL_TOOL_IDS = [...AVAILABLE_TOOLS, ...PLATFORM_TOOLS].map((t) => t.id)
|
|
|
19
19
|
export function AgentHoverCard({ agent, children, status }: Props) {
|
|
20
20
|
const [showAll, setShowAll] = useState(false)
|
|
21
21
|
const [busy, setBusy] = useState(false)
|
|
22
|
-
const tools = agent.
|
|
22
|
+
const tools = agent.plugins ?? []
|
|
23
23
|
|
|
24
24
|
const displayTools = showAll ? ALL_TOOL_IDS : tools
|
|
25
25
|
|
|
@@ -27,11 +27,11 @@ export function AgentHoverCard({ agent, children, status }: Props) {
|
|
|
27
27
|
if (busy) return
|
|
28
28
|
setBusy(true)
|
|
29
29
|
try {
|
|
30
|
-
const current = agent.
|
|
30
|
+
const current = agent.plugins || []
|
|
31
31
|
const updated = current.includes(toolId)
|
|
32
32
|
? current.filter((t) => t !== toolId)
|
|
33
33
|
: [...current, toolId]
|
|
34
|
-
await api('PUT', `/agents/${agent.id}`, {
|
|
34
|
+
await api('PUT', `/agents/${agent.id}`, { plugins: updated })
|
|
35
35
|
useAppStore.getState().loadAgents()
|
|
36
36
|
} finally {
|
|
37
37
|
setBusy(false)
|
|
@@ -44,7 +44,7 @@ export function ChatroomToolRequestBanner({ agentId, agentName, text, toolOutput
|
|
|
44
44
|
if (toolRequests.length === 0) return null
|
|
45
45
|
|
|
46
46
|
const agent = agents[agentId]
|
|
47
|
-
const agentTools: string[] = agent?.
|
|
47
|
+
const agentTools: string[] = agent?.plugins || []
|
|
48
48
|
|
|
49
49
|
const handleGrant = async (toolId: string) => {
|
|
50
50
|
if (agentTools.includes(toolId)) {
|
|
@@ -52,7 +52,7 @@ export function ChatroomToolRequestBanner({ agentId, agentName, text, toolOutput
|
|
|
52
52
|
return
|
|
53
53
|
}
|
|
54
54
|
const updated = [...agentTools, toolId]
|
|
55
|
-
await api('PUT', `/agents/${agentId}`, {
|
|
55
|
+
await api('PUT', `/agents/${agentId}`, { plugins: updated })
|
|
56
56
|
await loadAgents()
|
|
57
57
|
const newGranted = new Set(granted).add(toolId)
|
|
58
58
|
setGranted(newGranted)
|