@swarmclawai/swarmclaw 1.2.8 → 1.2.9
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 +30 -6
- package/package.json +2 -2
- package/src/app/agents/[id]/page.tsx +1 -18
- package/src/app/api/agents/thread-route.test.ts +0 -1
- package/src/app/api/approvals/route.test.ts +6 -22
- package/src/app/api/connectors/route.ts +2 -2
- package/src/app/api/portability/export/route.ts +8 -0
- package/src/app/api/portability/import/route.test.ts +80 -0
- package/src/app/api/portability/import/route.ts +28 -0
- package/src/app/api/settings/route.ts +0 -2
- package/src/app/api/wallets/[id]/route.ts +15 -157
- package/src/app/api/wallets/generate/route.ts +22 -0
- package/src/app/api/wallets/route.test.ts +147 -0
- package/src/app/api/wallets/route.ts +13 -95
- package/src/app/autonomy/page.tsx +2 -57
- package/src/app/protocols/page.tsx +2 -21
- package/src/app/settings/page.tsx +0 -9
- package/src/app/wallets/page.tsx +105 -5
- package/src/cli/index.js +21 -33
- package/src/cli/spec.js +19 -30
- package/src/components/agents/agent-sheet.tsx +2 -40
- package/src/components/agents/inspector-panel.tsx +0 -83
- package/src/components/chat/chat-card.tsx +0 -31
- package/src/components/chat/message-bubble.tsx +1 -108
- package/src/components/connectors/connector-sheet.tsx +25 -1
- package/src/components/layout/sidebar-rail.tsx +6 -10
- package/src/components/projects/project-detail.tsx +3 -35
- package/src/components/projects/tabs/overview-tab.tsx +3 -59
- package/src/components/projects/tabs/work-tab.tsx +7 -77
- package/src/components/protocols/structured-session-launcher.tsx +1 -22
- package/src/components/shared/connector-platform-icon.tsx +1 -0
- package/src/components/tasks/task-card.tsx +4 -34
- package/src/components/tasks/task-sheet.tsx +6 -36
- package/src/components/wallets/wallet-list.tsx +150 -0
- package/src/lib/app/navigation.test.ts +0 -13
- package/src/lib/app/navigation.ts +2 -7
- package/src/lib/app/view-constants.ts +14 -19
- package/src/lib/server/agents/agent-thread-session.ts +0 -1
- package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
- package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
- package/src/lib/server/agents/delegation-jobs.ts +0 -25
- package/src/lib/server/agents/main-agent-loop.ts +1 -49
- package/src/lib/server/agents/subagent-runtime.ts +0 -1
- package/src/lib/server/approval-match.ts +0 -85
- package/src/lib/server/approvals.test.ts +6 -6
- package/src/lib/server/approvals.ts +0 -6
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
- package/src/lib/server/builtin-extensions.ts +0 -2
- package/src/lib/server/capability-router.test.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
- package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
- package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
- package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
- package/src/lib/server/chat-execution/message-classifier.ts +1 -16
- package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
- package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
- package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
- package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
- package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
- package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
- package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
- package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
- package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
- package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
- package/src/lib/server/chats/chat-session-service.ts +3 -5
- package/src/lib/server/connectors/connector-inbound.ts +0 -1
- package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
- package/src/lib/server/connectors/connector-service.ts +39 -9
- package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
- package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
- package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
- package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
- package/src/lib/server/connectors/swarmdock-tasks.ts +119 -0
- package/src/lib/server/connectors/swarmdock.ts +255 -0
- package/src/lib/server/execution-brief.test.ts +2 -25
- package/src/lib/server/execution-brief.ts +12 -35
- package/src/lib/server/execution-engine/task-attempt.ts +0 -1
- package/src/lib/server/persistence/storage-context.ts +0 -5
- package/src/lib/server/portability/export.ts +109 -0
- package/src/lib/server/portability/import.ts +159 -0
- package/src/lib/server/protocols/protocol-normalization.ts +0 -4
- package/src/lib/server/protocols/protocol-queries.ts +0 -6
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
- package/src/lib/server/protocols/protocol-service.ts +0 -1
- package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
- package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
- package/src/lib/server/protocols/protocol-swarm.ts +0 -2
- package/src/lib/server/protocols/protocol-types.ts +0 -2
- package/src/lib/server/provider-health.ts +0 -9
- package/src/lib/server/runtime/daemon-state/core.ts +0 -9
- package/src/lib/server/runtime/daemon-state.test.ts +0 -35
- package/src/lib/server/runtime/heartbeat-service.ts +3 -23
- package/src/lib/server/runtime/queue/core.ts +11 -33
- package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
- package/src/lib/server/runtime/scheduler.ts +0 -13
- package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
- package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
- package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
- package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
- package/src/lib/server/session-tools/crud.ts +0 -14
- package/src/lib/server/session-tools/delegate.ts +0 -4
- package/src/lib/server/session-tools/index.ts +0 -4
- package/src/lib/server/session-tools/team-context.ts +0 -3
- package/src/lib/server/storage-normalization.ts +8 -0
- package/src/lib/server/storage.ts +18 -45
- package/src/lib/server/tasks/task-checkout.ts +59 -0
- package/src/lib/server/tasks/task-lifecycle.ts +2 -0
- package/src/lib/server/tasks/task-route-service.ts +4 -26
- package/src/lib/server/tasks/task-service.ts +0 -7
- package/src/lib/server/tool-aliases.ts +0 -1
- package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
- package/src/lib/server/tool-capability-policy.ts +0 -2
- package/src/lib/server/tool-planning.ts +0 -12
- package/src/lib/server/universal-tool-access.ts +0 -1
- package/src/lib/server/wallets/wallet-crypto.ts +33 -0
- package/src/lib/server/wallets/wallet-repository.ts +24 -0
- package/src/lib/server/wallets/wallet-service.ts +119 -0
- package/src/lib/server/working-state/extraction.ts +8 -42
- package/src/lib/server/working-state/normalization.ts +10 -103
- package/src/lib/server/working-state/service.ts +12 -21
- package/src/lib/strip-internal-metadata.test.ts +1 -1
- package/src/lib/strip-internal-metadata.ts +1 -1
- package/src/lib/tool-definitions.ts +0 -1
- package/src/lib/validation/schemas.ts +33 -2
- package/src/stores/slices/data-slice.ts +5 -1
- package/src/stores/slices/ui-slice.ts +0 -4
- package/src/types/agent.ts +0 -84
- package/src/types/app-settings.ts +0 -2
- package/src/types/approval.ts +0 -2
- package/src/types/connector.ts +1 -0
- package/src/types/index.ts +1 -1
- package/src/types/message.ts +0 -1
- package/src/types/misc.ts +0 -2
- package/src/types/protocol.ts +0 -2
- package/src/types/run.ts +0 -3
- package/src/types/session.ts +1 -51
- package/src/types/swarmdock.ts +29 -0
- package/src/types/task.ts +7 -3
- package/src/types/working-state.ts +2 -9
- package/src/views/settings/section-runtime-loop.tsx +0 -14
- package/src/app/api/canvas/[sessionId]/route.ts +0 -35
- package/src/app/api/missions/[id]/actions/route.ts +0 -31
- package/src/app/api/missions/[id]/events/route.ts +0 -14
- package/src/app/api/missions/[id]/route.ts +0 -10
- package/src/app/api/missions/route.test.ts +0 -244
- package/src/app/api/missions/route.ts +0 -57
- package/src/app/api/wallets/[id]/approve/route.ts +0 -79
- package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
- package/src/app/api/wallets/[id]/send/route.ts +0 -113
- package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
- package/src/app/missions/[id]/page.tsx +0 -3
- package/src/app/missions/page.tsx +0 -685
- package/src/components/canvas/canvas-panel.tsx +0 -267
- package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
- package/src/components/wallets/wallet-panel.tsx +0 -1010
- package/src/components/wallets/wallet-section.tsx +0 -260
- package/src/features/missions/queries.ts +0 -23
- package/src/lib/canvas-content.test.ts +0 -360
- package/src/lib/canvas-content.ts +0 -198
- package/src/lib/server/canvas-content.test.ts +0 -32
- package/src/lib/server/canvas-content.ts +0 -6
- package/src/lib/server/ethereum.ts +0 -591
- package/src/lib/server/evm-swap.ts +0 -476
- package/src/lib/server/missions/mission-intent.test.ts +0 -63
- package/src/lib/server/missions/mission-intent.ts +0 -569
- package/src/lib/server/missions/mission-repository.ts +0 -74
- package/src/lib/server/missions/mission-service/actions.ts +0 -6
- package/src/lib/server/missions/mission-service/bindings.ts +0 -9
- package/src/lib/server/missions/mission-service/context.ts +0 -4
- package/src/lib/server/missions/mission-service/core.ts +0 -2271
- package/src/lib/server/missions/mission-service/queries.ts +0 -12
- package/src/lib/server/missions/mission-service/recovery.ts +0 -5
- package/src/lib/server/missions/mission-service/ticks.ts +0 -9
- package/src/lib/server/missions/mission-service.test.ts +0 -888
- package/src/lib/server/missions/mission-service.ts +0 -6
- package/src/lib/server/session-tools/canvas.ts +0 -105
- package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
- package/src/lib/server/session-tools/wallet.ts +0 -1287
- package/src/lib/server/solana.ts +0 -327
- package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
- package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
- package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
- package/src/lib/server/wallet/wallet-service.test.ts +0 -81
- package/src/lib/server/wallet/wallet-service.ts +0 -225
- package/src/lib/wallet/wallet-transactions.test.ts +0 -75
- package/src/lib/wallet/wallet-transactions.ts +0 -43
- package/src/lib/wallet/wallet.test.ts +0 -333
- package/src/lib/wallet/wallet.ts +0 -183
- package/src/types/mission.ts +0 -185
- package/src/views/settings/section-wallets.tsx +0 -35
|
@@ -8,7 +8,7 @@ import { OverviewTab } from './tabs/overview-tab'
|
|
|
8
8
|
import { WorkTab } from './tabs/work-tab'
|
|
9
9
|
import { OperationsTab } from './tabs/operations-tab'
|
|
10
10
|
import { ActivityTab } from './tabs/activity-tab'
|
|
11
|
-
import type { BoardTask
|
|
11
|
+
import type { BoardTask } from '@/types'
|
|
12
12
|
|
|
13
13
|
export function ProjectDetail() {
|
|
14
14
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
@@ -17,43 +17,11 @@ export function ProjectDetail() {
|
|
|
17
17
|
const activeTab = useAppStore((s) => s.projectDetailTab)
|
|
18
18
|
const loadSecrets = useAppStore((s) => s.loadSecrets)
|
|
19
19
|
|
|
20
|
-
const [projectMissionSnapshot, setProjectMissionSnapshot] = useState<{ projectId: string | null; missions: Mission[] }>({
|
|
21
|
-
projectId: null,
|
|
22
|
-
missions: [],
|
|
23
|
-
})
|
|
24
|
-
|
|
25
20
|
useEffect(() => {
|
|
26
21
|
if (!activeProjectFilter) return
|
|
27
22
|
void loadSecrets()
|
|
28
23
|
}, [activeProjectFilter, loadSecrets])
|
|
29
24
|
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
let cancelled = false
|
|
32
|
-
if (!activeProjectFilter) return
|
|
33
|
-
void api<Mission[]>('GET', `/missions?projectId=${encodeURIComponent(activeProjectFilter)}&status=non_terminal&limit=8`)
|
|
34
|
-
.then((missions) => {
|
|
35
|
-
if (!cancelled) {
|
|
36
|
-
setProjectMissionSnapshot({
|
|
37
|
-
projectId: activeProjectFilter,
|
|
38
|
-
missions: Array.isArray(missions) ? missions : [],
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
.catch(() => {
|
|
43
|
-
if (!cancelled) {
|
|
44
|
-
setProjectMissionSnapshot({
|
|
45
|
-
projectId: activeProjectFilter,
|
|
46
|
-
missions: [],
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
return () => { cancelled = true }
|
|
51
|
-
}, [activeProjectFilter])
|
|
52
|
-
|
|
53
|
-
const projectMissions = projectMissionSnapshot.projectId === activeProjectFilter
|
|
54
|
-
? projectMissionSnapshot.missions
|
|
55
|
-
: []
|
|
56
|
-
|
|
57
25
|
const project = activeProjectFilter ? projects[activeProjectFilter] : null
|
|
58
26
|
|
|
59
27
|
const projectTasks = useMemo(
|
|
@@ -107,10 +75,10 @@ export function ProjectDetail() {
|
|
|
107
75
|
/>
|
|
108
76
|
<div className="flex-1 overflow-y-auto">
|
|
109
77
|
{activeTab === 'overview' && (
|
|
110
|
-
<OverviewTab project={project}
|
|
78
|
+
<OverviewTab project={project} />
|
|
111
79
|
)}
|
|
112
80
|
{activeTab === 'work' && (
|
|
113
|
-
<WorkTab
|
|
81
|
+
<WorkTab />
|
|
114
82
|
)}
|
|
115
83
|
{activeTab === 'operations' && (
|
|
116
84
|
<OperationsTab project={project} />
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react'
|
|
4
|
-
import { useRouter } from 'next/navigation'
|
|
5
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
5
|
import { relativeDate } from '../project-utils'
|
|
7
|
-
import {
|
|
8
|
-
import type { BoardTask, Mission, Project, Schedule } from '@/types'
|
|
6
|
+
import type { BoardTask, Project, Schedule } from '@/types'
|
|
9
7
|
|
|
10
8
|
interface OverviewTabProps {
|
|
11
9
|
project: Project
|
|
12
|
-
missions: Mission[]
|
|
13
10
|
}
|
|
14
11
|
|
|
15
|
-
export function OverviewTab({ project
|
|
16
|
-
const router = useRouter()
|
|
12
|
+
export function OverviewTab({ project }: OverviewTabProps) {
|
|
17
13
|
const tasks = useAppStore((s) => s.tasks) as Record<string, BoardTask>
|
|
18
14
|
const schedules = useAppStore((s) => s.schedules) as Record<string, Schedule>
|
|
19
15
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
@@ -66,8 +62,6 @@ export function OverviewTab({ project, missions }: OverviewTabProps) {
|
|
|
66
62
|
{ label: 'Stale', value: staleCount, tone: 'text-sky-400', hint: 'No meaningful progress in 3+ days' },
|
|
67
63
|
]
|
|
68
64
|
|
|
69
|
-
const displayedMissions = missions.slice(0, 5)
|
|
70
|
-
|
|
71
65
|
return (
|
|
72
66
|
<div className="max-w-3xl mx-auto px-8 py-6 space-y-6">
|
|
73
67
|
{/* Section 1: Project Identity */}
|
|
@@ -110,57 +104,7 @@ export function OverviewTab({ project, missions }: OverviewTabProps) {
|
|
|
110
104
|
</div>
|
|
111
105
|
</div>
|
|
112
106
|
|
|
113
|
-
{/* Section 3:
|
|
114
|
-
<div>
|
|
115
|
-
<h3 className="text-[12px] font-700 uppercase tracking-[0.08em] text-text-3/60 mb-3">Active Missions</h3>
|
|
116
|
-
{displayedMissions.length === 0 ? (
|
|
117
|
-
<p className="text-[12px] text-text-3/45">No active missions.</p>
|
|
118
|
-
) : (
|
|
119
|
-
<div className="flex flex-col gap-2">
|
|
120
|
-
{displayedMissions.map((mission) => (
|
|
121
|
-
<button
|
|
122
|
-
key={mission.id}
|
|
123
|
-
onClick={() => router.push(getMissionPath(mission.id))}
|
|
124
|
-
className="w-full flex items-center justify-between gap-3 px-4 py-3 rounded-[12px] border border-white/[0.06] bg-white/[0.02] hover:bg-white/[0.04] transition-all cursor-pointer text-left"
|
|
125
|
-
style={{ fontFamily: 'inherit' }}
|
|
126
|
-
>
|
|
127
|
-
<div className="min-w-0 flex-1">
|
|
128
|
-
<div className="text-[13px] font-600 text-text truncate">{mission.objective}</div>
|
|
129
|
-
<div className="flex items-center gap-2 mt-1 flex-wrap">
|
|
130
|
-
<span className={`text-[9px] font-600 uppercase tracking-wider px-1.5 py-0.5 rounded-[4px] ${
|
|
131
|
-
mission.status === 'active' ? 'bg-sky-500/15 text-sky-400'
|
|
132
|
-
: mission.status === 'waiting' ? 'bg-amber-500/15 text-amber-400'
|
|
133
|
-
: 'bg-white/[0.06] text-text-3'
|
|
134
|
-
}`}>
|
|
135
|
-
{mission.status}
|
|
136
|
-
</span>
|
|
137
|
-
{mission.status === 'waiting' && (
|
|
138
|
-
<span className="text-[9px] font-600 px-1.5 py-0.5 rounded-[4px] bg-amber-500/10 text-amber-400/70">waiting</span>
|
|
139
|
-
)}
|
|
140
|
-
{mission.status === 'failed' && (
|
|
141
|
-
<span className="text-[9px] font-600 px-1.5 py-0.5 rounded-[4px] bg-red-500/10 text-red-400/70">blocked</span>
|
|
142
|
-
)}
|
|
143
|
-
{(mission.childMissionIds?.length || 0) > 0 && (
|
|
144
|
-
<span className="text-[9px] font-600 px-1.5 py-0.5 rounded-[4px] bg-sky-500/10 text-sky-400/70">{mission.childMissionIds?.length} children</span>
|
|
145
|
-
)}
|
|
146
|
-
{(mission.taskIds?.length || 0) > 0 && (
|
|
147
|
-
<span className="text-[9px] font-600 px-1.5 py-0.5 rounded-[4px] bg-white/[0.06] text-text-3/60">{mission.taskIds?.length} task{mission.taskIds?.length === 1 ? '' : 's'}</span>
|
|
148
|
-
)}
|
|
149
|
-
</div>
|
|
150
|
-
</div>
|
|
151
|
-
<span className="text-[10px] text-text-3/35 shrink-0">{relativeDate(mission.updatedAt)}</span>
|
|
152
|
-
</button>
|
|
153
|
-
))}
|
|
154
|
-
{missions.length > 5 && (
|
|
155
|
-
<p className="text-[11px] text-accent-bright/70 text-center py-1">
|
|
156
|
-
{missions.length - 5} more mission{missions.length - 5 === 1 ? '' : 's'}
|
|
157
|
-
</p>
|
|
158
|
-
)}
|
|
159
|
-
</div>
|
|
160
|
-
)}
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
|
-
{/* Section 4: Progress */}
|
|
107
|
+
{/* Section 3: Progress */}
|
|
164
108
|
{totalTasks > 0 && (
|
|
165
109
|
<div className="rounded-[12px] border border-white/[0.06] bg-white/[0.02] px-5 py-4">
|
|
166
110
|
<div className="flex items-center justify-between mb-2.5">
|
|
@@ -4,7 +4,7 @@ import { useMemo, useState } from 'react'
|
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
6
6
|
import { relativeDate, STATUS_STYLES } from '../project-utils'
|
|
7
|
-
import type { Agent, BoardTask
|
|
7
|
+
import type { Agent, BoardTask } from '@/types'
|
|
8
8
|
|
|
9
9
|
type SortKey = 'status' | 'updated' | 'agent'
|
|
10
10
|
type StatusFilter = 'all' | 'backlog' | 'queued' | 'running' | 'completed' | 'failed'
|
|
@@ -13,11 +13,7 @@ const STATUS_PRIORITY: Record<string, number> = {
|
|
|
13
13
|
failed: 0, running: 1, queued: 2, backlog: 3, deferred: 4, completed: 5, cancelled: 6, archived: 7,
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
missions: Mission[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function WorkTab({ missions }: WorkTabProps) {
|
|
16
|
+
export function WorkTab() {
|
|
21
17
|
const tasks = useAppStore((s) => s.tasks) as Record<string, BoardTask>
|
|
22
18
|
const agents = useAppStore((s) => s.agents) as Record<string, Agent>
|
|
23
19
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
@@ -27,37 +23,20 @@ export function WorkTab({ missions }: WorkTabProps) {
|
|
|
27
23
|
const [sortKey, setSortKey] = useState<SortKey>('status')
|
|
28
24
|
const [statusFilter, setStatusFilter] = useState<StatusFilter>('all')
|
|
29
25
|
const [agentFilter, setAgentFilter] = useState<string | null>(null)
|
|
30
|
-
const [missionFilter, setMissionFilter] = useState<string | null>(null)
|
|
31
|
-
const [missionSummaryOpen, setMissionSummaryOpen] = useState(false)
|
|
32
26
|
|
|
33
27
|
const projectTasks = useMemo(
|
|
34
28
|
() => Object.values(tasks).filter((t) => t.projectId === activeProjectFilter),
|
|
35
29
|
[tasks, activeProjectFilter],
|
|
36
30
|
)
|
|
37
31
|
|
|
38
|
-
// Build taskId -> mission lookup from Mission.taskIds
|
|
39
|
-
const taskIdToMission = useMemo(() => {
|
|
40
|
-
const lookup: Record<string, Mission> = {}
|
|
41
|
-
for (const m of missions) {
|
|
42
|
-
for (const tid of m.taskIds || []) {
|
|
43
|
-
lookup[tid] = m
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return lookup
|
|
47
|
-
}, [missions])
|
|
48
|
-
|
|
49
32
|
// Filter
|
|
50
33
|
const filteredTasks = useMemo(() => {
|
|
51
34
|
return projectTasks.filter((t) => {
|
|
52
35
|
if (statusFilter !== 'all' && t.status !== statusFilter) return false
|
|
53
36
|
if (agentFilter && t.agentId !== agentFilter) return false
|
|
54
|
-
if (missionFilter) {
|
|
55
|
-
const m = taskIdToMission[t.id]
|
|
56
|
-
if (!m || m.id !== missionFilter) return false
|
|
57
|
-
}
|
|
58
37
|
return true
|
|
59
38
|
})
|
|
60
|
-
}, [projectTasks, statusFilter, agentFilter
|
|
39
|
+
}, [projectTasks, statusFilter, agentFilter])
|
|
61
40
|
|
|
62
41
|
// Sort
|
|
63
42
|
const sortedTasks = useMemo(() => {
|
|
@@ -78,56 +57,8 @@ export function WorkTab({ missions }: WorkTabProps) {
|
|
|
78
57
|
return Array.from(ids)
|
|
79
58
|
}, [projectTasks])
|
|
80
59
|
|
|
81
|
-
// Mission status summary
|
|
82
|
-
const missionStatusSummary = useMemo(() => {
|
|
83
|
-
const counts: Record<string, number> = {}
|
|
84
|
-
for (const m of missions) {
|
|
85
|
-
counts[m.status] = (counts[m.status] || 0) + 1
|
|
86
|
-
}
|
|
87
|
-
return counts
|
|
88
|
-
}, [missions])
|
|
89
|
-
|
|
90
60
|
return (
|
|
91
61
|
<div className="max-w-3xl mx-auto px-8 py-6 space-y-4">
|
|
92
|
-
{/* Mission summary (collapsible) */}
|
|
93
|
-
{missions.length > 0 && (
|
|
94
|
-
<div className="rounded-[12px] border border-white/[0.06] bg-white/[0.02] overflow-hidden">
|
|
95
|
-
<button
|
|
96
|
-
onClick={() => setMissionSummaryOpen(!missionSummaryOpen)}
|
|
97
|
-
className="w-full flex items-center justify-between px-4 py-3 cursor-pointer bg-transparent border-none text-left"
|
|
98
|
-
style={{ fontFamily: 'inherit' }}
|
|
99
|
-
>
|
|
100
|
-
<span className="text-[12px] font-600 text-text-2">
|
|
101
|
-
Missions: {Object.entries(missionStatusSummary).map(([s, c]) => `${c} ${s}`).join(', ')}
|
|
102
|
-
</span>
|
|
103
|
-
<svg
|
|
104
|
-
width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
|
105
|
-
className={`text-text-3/40 transition-transform ${missionSummaryOpen ? 'rotate-180' : ''}`}
|
|
106
|
-
>
|
|
107
|
-
<polyline points="6 9 12 15 18 9" />
|
|
108
|
-
</svg>
|
|
109
|
-
</button>
|
|
110
|
-
{missionSummaryOpen && (
|
|
111
|
-
<div className="border-t border-white/[0.06] px-4 py-2 space-y-1">
|
|
112
|
-
{missions.map((m) => (
|
|
113
|
-
<button
|
|
114
|
-
key={m.id}
|
|
115
|
-
onClick={() => setMissionFilter(missionFilter === m.id ? null : m.id)}
|
|
116
|
-
className={`w-full flex items-center justify-between px-2 py-1.5 rounded-[8px] text-left cursor-pointer bg-transparent border-none transition-colors
|
|
117
|
-
${missionFilter === m.id ? 'bg-accent-soft' : 'hover:bg-white/[0.04]'}`}
|
|
118
|
-
style={{ fontFamily: 'inherit' }}
|
|
119
|
-
>
|
|
120
|
-
<span className="text-[12px] text-text truncate">{m.objective}</span>
|
|
121
|
-
<span className={`text-[9px] font-600 uppercase tracking-wider px-1.5 py-0.5 rounded-[4px] shrink-0 ${
|
|
122
|
-
m.status === 'active' ? 'bg-sky-500/15 text-sky-400' : 'bg-white/[0.06] text-text-3'
|
|
123
|
-
}`}>{m.status}</span>
|
|
124
|
-
</button>
|
|
125
|
-
))}
|
|
126
|
-
</div>
|
|
127
|
-
)}
|
|
128
|
-
</div>
|
|
129
|
-
)}
|
|
130
|
-
|
|
131
62
|
{/* Controls row */}
|
|
132
63
|
<div className="flex items-center justify-between gap-3">
|
|
133
64
|
<div className="flex items-center gap-2">
|
|
@@ -174,9 +105,9 @@ export function WorkTab({ missions }: WorkTabProps) {
|
|
|
174
105
|
)}
|
|
175
106
|
|
|
176
107
|
{/* Clear filters */}
|
|
177
|
-
{(statusFilter !== 'all' || agentFilter
|
|
108
|
+
{(statusFilter !== 'all' || agentFilter) && (
|
|
178
109
|
<button
|
|
179
|
-
onClick={() => { setStatusFilter('all'); setAgentFilter(null)
|
|
110
|
+
onClick={() => { setStatusFilter('all'); setAgentFilter(null) }}
|
|
180
111
|
className="text-[10px] text-accent-bright/70 hover:text-accent-bright cursor-pointer bg-transparent border-none"
|
|
181
112
|
style={{ fontFamily: 'inherit' }}
|
|
182
113
|
>
|
|
@@ -212,7 +143,6 @@ export function WorkTab({ missions }: WorkTabProps) {
|
|
|
212
143
|
<div className="flex flex-col gap-1.5">
|
|
213
144
|
{sortedTasks.map((task) => {
|
|
214
145
|
const agent = task.agentId ? agents[task.agentId] : null
|
|
215
|
-
const mission = taskIdToMission[task.id]
|
|
216
146
|
return (
|
|
217
147
|
<button
|
|
218
148
|
key={task.id}
|
|
@@ -225,8 +155,8 @@ export function WorkTab({ missions }: WorkTabProps) {
|
|
|
225
155
|
</span>
|
|
226
156
|
<div className="flex-1 min-w-0">
|
|
227
157
|
<span className="text-[13px] text-text truncate block">{task.title}</span>
|
|
228
|
-
{
|
|
229
|
-
<span className="text-[10px] text-text-3/40 truncate block mt-0.5">{
|
|
158
|
+
{task.objective && (
|
|
159
|
+
<span className="text-[10px] text-text-3/40 truncate block mt-0.5">{task.objective}</span>
|
|
230
160
|
)}
|
|
231
161
|
</div>
|
|
232
162
|
{agent && (
|
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import { useAgentsQuery } from '@/features/agents/queries'
|
|
5
5
|
import { useChatroomsQuery } from '@/features/chatrooms/queries'
|
|
6
|
-
import { useMissionsQuery } from '@/features/missions/queries'
|
|
7
6
|
import { useCreateProtocolRunMutation, useProtocolTemplatesQuery } from '@/features/protocols/queries'
|
|
8
7
|
import { useTasksQuery } from '@/features/tasks/queries'
|
|
9
8
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
10
9
|
import { SheetFooter } from '@/components/shared/sheet-footer'
|
|
11
|
-
import type { BoardTask, Chatroom,
|
|
10
|
+
import type { BoardTask, Chatroom, ProtocolRun, ProtocolTemplate } from '@/types'
|
|
12
11
|
|
|
13
12
|
export type StructuredSessionLaunchContext = {
|
|
14
13
|
templateId?: string | null
|
|
@@ -21,8 +20,6 @@ export type StructuredSessionLaunchContext = {
|
|
|
21
20
|
sessionLabel?: string | null
|
|
22
21
|
parentChatroomId?: string | null
|
|
23
22
|
parentChatroomLabel?: string | null
|
|
24
|
-
missionId?: string | null
|
|
25
|
-
missionLabel?: string | null
|
|
26
23
|
taskId?: string | null
|
|
27
24
|
taskLabel?: string | null
|
|
28
25
|
autoStart?: boolean
|
|
@@ -52,7 +49,6 @@ type FormState = {
|
|
|
52
49
|
facilitatorAgentId: string
|
|
53
50
|
sessionId: string
|
|
54
51
|
parentChatroomId: string
|
|
55
|
-
missionId: string
|
|
56
52
|
taskId: string
|
|
57
53
|
autoStart: boolean
|
|
58
54
|
createTranscript: boolean
|
|
@@ -62,7 +58,6 @@ const DEFAULT_TEMPLATE_ID = 'facilitated_discussion'
|
|
|
62
58
|
|
|
63
59
|
function buildDefaultTitle(context: StructuredSessionLaunchContext | null | undefined): string {
|
|
64
60
|
if (context?.title?.trim()) return context.title.trim()
|
|
65
|
-
if (context?.missionLabel?.trim()) return `Structured session: ${context.missionLabel.trim()}`
|
|
66
61
|
if (context?.taskLabel?.trim()) return `Structured session: ${context.taskLabel.trim()}`
|
|
67
62
|
if (context?.parentChatroomLabel?.trim()) return `Structured session: ${context.parentChatroomLabel.trim()}`
|
|
68
63
|
if (context?.sessionLabel?.trim()) return `Structured session: ${context.sessionLabel.trim()}`
|
|
@@ -81,7 +76,6 @@ function buildInitialState(context: StructuredSessionLaunchContext | null | unde
|
|
|
81
76
|
facilitatorAgentId: context?.facilitatorAgentId?.trim() || '',
|
|
82
77
|
sessionId: context?.sessionId?.trim() || '',
|
|
83
78
|
parentChatroomId: context?.parentChatroomId?.trim() || '',
|
|
84
|
-
missionId: context?.missionId?.trim() || '',
|
|
85
79
|
taskId: context?.taskId?.trim() || '',
|
|
86
80
|
autoStart: context?.autoStart !== false,
|
|
87
81
|
createTranscript: context?.createTranscript !== false,
|
|
@@ -108,19 +102,16 @@ export function StructuredSessionLauncher({
|
|
|
108
102
|
const templatesQuery = useProtocolTemplatesQuery({ enabled: open })
|
|
109
103
|
const agentsQuery = useAgentsQuery({ enabled: open })
|
|
110
104
|
const chatroomsQuery = useChatroomsQuery({ enabled: open && allowContextSelection })
|
|
111
|
-
const missionsQuery = useMissionsQuery({ enabled: open && allowContextSelection, limit: 80 })
|
|
112
105
|
const tasksQuery = useTasksQuery({ includeArchived: true, enabled: open && allowContextSelection })
|
|
113
106
|
const createRunMutation = useCreateProtocolRunMutation()
|
|
114
107
|
const templates = templatesQuery.data ?? []
|
|
115
108
|
const agents = agentsQuery.data ?? {}
|
|
116
109
|
const chatrooms = chatroomsQuery.data ?? {}
|
|
117
|
-
const missions = missionsQuery.data ?? []
|
|
118
110
|
const tasks = tasksQuery.data ?? {}
|
|
119
111
|
const loading = (
|
|
120
112
|
templatesQuery.isLoading
|
|
121
113
|
|| agentsQuery.isLoading
|
|
122
114
|
|| chatroomsQuery.isLoading
|
|
123
|
-
|| missionsQuery.isLoading
|
|
124
115
|
|| tasksQuery.isLoading
|
|
125
116
|
)
|
|
126
117
|
const breakoutMode = variant === 'breakout'
|
|
@@ -145,7 +136,6 @@ export function StructuredSessionLauncher({
|
|
|
145
136
|
() => [
|
|
146
137
|
contextChip('Chat', initialContext?.sessionLabel),
|
|
147
138
|
contextChip('Chatroom', initialContext?.parentChatroomLabel),
|
|
148
|
-
contextChip('Mission', initialContext?.missionLabel),
|
|
149
139
|
contextChip('Task', initialContext?.taskLabel),
|
|
150
140
|
].filter(Boolean) as Array<{ label: string; value: string }>,
|
|
151
141
|
[initialContext],
|
|
@@ -180,7 +170,6 @@ export function StructuredSessionLauncher({
|
|
|
180
170
|
facilitatorAgentId: form.facilitatorAgentId || null,
|
|
181
171
|
sessionId: form.sessionId || null,
|
|
182
172
|
parentChatroomId: form.parentChatroomId || null,
|
|
183
|
-
missionId: form.missionId || null,
|
|
184
173
|
taskId: form.taskId || null,
|
|
185
174
|
autoStart: form.autoStart,
|
|
186
175
|
createTranscript: form.createTranscript,
|
|
@@ -413,16 +402,6 @@ export function StructuredSessionLauncher({
|
|
|
413
402
|
<option key={chatroom.id} value={chatroom.id}>{chatroom.name}</option>
|
|
414
403
|
))}
|
|
415
404
|
</select>
|
|
416
|
-
<select
|
|
417
|
-
value={form.missionId}
|
|
418
|
-
onChange={(event) => setForm((current) => ({ ...current, missionId: event.target.value }))}
|
|
419
|
-
className="rounded-[12px] border border-white/[0.06] bg-black/20 px-3 py-2.5 text-[14px] text-text outline-none"
|
|
420
|
-
>
|
|
421
|
-
<option value="">No linked mission</option>
|
|
422
|
-
{missions.map((mission) => (
|
|
423
|
-
<option key={mission.id} value={mission.id}>{mission.objective}</option>
|
|
424
|
-
))}
|
|
425
|
-
</select>
|
|
426
405
|
<select
|
|
427
406
|
value={form.taskId}
|
|
428
407
|
onChange={(event) => setForm((current) => ({ ...current, taskId: event.target.value }))}
|
|
@@ -26,6 +26,7 @@ export const CONNECTOR_PLATFORM_META: Record<ConnectorPlatform, { label: string;
|
|
|
26
26
|
email: { label: 'Email', color: '#EA4335' },
|
|
27
27
|
webchat: { label: 'Web Chat', color: '#0EA5E9' },
|
|
28
28
|
mockmail: { label: 'MockMail', color: '#7C3AED' },
|
|
29
|
+
swarmdock: { label: 'SwarmDock', color: '#F59E0B' },
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
const FALLBACK_CONNECTOR_PLATFORM_META = { label: 'Connector', color: '#64748B' } as const
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { useState, useCallback, useEffect } from 'react'
|
|
4
|
-
import { useRouter } from 'next/navigation'
|
|
5
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
6
|
-
import {
|
|
5
|
+
import { useNavigate } from '@/lib/app/navigation'
|
|
7
6
|
import { useUpdateTaskMutation } from '@/features/tasks/queries'
|
|
8
7
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
9
8
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
@@ -36,7 +35,6 @@ export function TaskCard({
|
|
|
36
35
|
const setTaskSheetOpen = useAppStore((s) => s.setTaskSheetOpen)
|
|
37
36
|
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
38
37
|
const navigateTo = useNavigate()
|
|
39
|
-
const router = useRouter()
|
|
40
38
|
const updateTaskMutation = useUpdateTaskMutation()
|
|
41
39
|
const [dragging, setDragging] = useState(false)
|
|
42
40
|
const [confirmArchive, setConfirmArchive] = useState(false)
|
|
@@ -175,38 +173,10 @@ export function TaskCard({
|
|
|
175
173
|
<p className="text-[12px] text-text-3 line-clamp-2 mb-3">{task.description}</p>
|
|
176
174
|
)}
|
|
177
175
|
|
|
178
|
-
{task.
|
|
176
|
+
{task.objective && (
|
|
179
177
|
<div className="mb-3 rounded-[12px] border border-white/[0.06] bg-white/[0.02] px-3 py-2">
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
<div className="flex items-center gap-2">
|
|
183
|
-
<span className={`rounded-full px-2 py-0.5 text-[10px] font-700 uppercase tracking-[0.08em] ${
|
|
184
|
-
task.missionSummary.status === 'waiting' || task.missionSummary.status === 'failed' || task.missionSummary.status === 'cancelled'
|
|
185
|
-
? 'bg-amber-500/12 text-amber-300'
|
|
186
|
-
: task.missionSummary.status === 'completed'
|
|
187
|
-
? 'bg-emerald-500/12 text-emerald-300'
|
|
188
|
-
: 'bg-sky-500/12 text-sky-300'
|
|
189
|
-
}`}>
|
|
190
|
-
{task.missionSummary.status}
|
|
191
|
-
</span>
|
|
192
|
-
<button
|
|
193
|
-
type="button"
|
|
194
|
-
onClick={(event) => {
|
|
195
|
-
event.stopPropagation()
|
|
196
|
-
router.push(getMissionPath(task.missionSummary?.id || null))
|
|
197
|
-
}}
|
|
198
|
-
className="rounded-[8px] border border-white/[0.08] px-2 py-1 text-[10px] font-700 uppercase tracking-[0.08em] text-text-2 transition-colors hover:bg-white/[0.05]"
|
|
199
|
-
>
|
|
200
|
-
Open
|
|
201
|
-
</button>
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
<div className="text-[12px] font-600 text-text line-clamp-2">{task.missionSummary.objective}</div>
|
|
205
|
-
{(task.missionSummary.waitingReason || task.missionSummary.currentStep) && (
|
|
206
|
-
<div className="mt-1 text-[11px] text-text-3/70 line-clamp-2">
|
|
207
|
-
{task.missionSummary.waitingReason || task.missionSummary.currentStep}
|
|
208
|
-
</div>
|
|
209
|
-
)}
|
|
178
|
+
<span className="text-[10px] font-700 uppercase tracking-[0.08em] text-text-3/68">Objective</span>
|
|
179
|
+
<div className="text-[12px] font-600 text-text line-clamp-2 mt-1">{task.objective}</div>
|
|
210
180
|
</div>
|
|
211
181
|
)}
|
|
212
182
|
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
import { useProjectsQuery } from '@/features/projects/queries'
|
|
16
16
|
import { useAppSettingsQuery } from '@/features/settings/queries'
|
|
17
17
|
import { useProtocolRunsQuery } from '@/features/protocols/queries'
|
|
18
|
-
import { getMissionPath } from '@/lib/app/navigation'
|
|
19
18
|
import { BottomSheet } from '@/components/shared/bottom-sheet'
|
|
20
19
|
import { AgentPickerList } from '@/components/shared/agent-picker-list'
|
|
21
20
|
import { DirBrowser } from '@/components/shared/dir-browser'
|
|
@@ -342,28 +341,11 @@ export function TaskSheet() {
|
|
|
342
341
|
</div>
|
|
343
342
|
)}
|
|
344
343
|
|
|
345
|
-
{editing.
|
|
344
|
+
{editing.objective && (
|
|
346
345
|
<div className="mb-8">
|
|
347
|
-
<SectionLabel>
|
|
346
|
+
<SectionLabel>Objective</SectionLabel>
|
|
348
347
|
<div className="rounded-[14px] border border-white/[0.06] bg-surface px-4 py-3">
|
|
349
|
-
<div className="
|
|
350
|
-
<div className="text-[14px] font-600 text-text">{editing.missionSummary.objective}</div>
|
|
351
|
-
<div className="flex items-center gap-2">
|
|
352
|
-
<span className="rounded-full bg-sky-500/10 px-2.5 py-1 text-[10px] font-700 uppercase tracking-[0.08em] text-sky-300">
|
|
353
|
-
{editing.missionSummary.status}
|
|
354
|
-
</span>
|
|
355
|
-
<button
|
|
356
|
-
type="button"
|
|
357
|
-
onClick={() => router.push(getMissionPath(editing.missionSummary?.id || null))}
|
|
358
|
-
className="rounded-[8px] border border-white/[0.08] px-2 py-1 text-[10px] font-700 uppercase tracking-[0.08em] text-text-2 transition-colors hover:bg-white/[0.05]"
|
|
359
|
-
>
|
|
360
|
-
Open
|
|
361
|
-
</button>
|
|
362
|
-
</div>
|
|
363
|
-
</div>
|
|
364
|
-
<div className="text-[12px] leading-[1.7] text-text-3/72">
|
|
365
|
-
{editing.missionSummary.waitingReason || editing.missionSummary.currentStep || 'Mission linked to this task.'}
|
|
366
|
-
</div>
|
|
348
|
+
<div className="text-[14px] font-600 text-text">{editing.objective}</div>
|
|
367
349
|
</div>
|
|
368
350
|
</div>
|
|
369
351
|
)}
|
|
@@ -691,23 +673,11 @@ export function TaskSheet() {
|
|
|
691
673
|
/>
|
|
692
674
|
</div>
|
|
693
675
|
|
|
694
|
-
{editing?.
|
|
676
|
+
{editing?.objective && (
|
|
695
677
|
<div className="mb-8">
|
|
696
|
-
<SectionLabel>
|
|
678
|
+
<SectionLabel>Objective</SectionLabel>
|
|
697
679
|
<div className="rounded-[14px] border border-white/[0.06] bg-surface px-4 py-3 text-[12px] leading-[1.7] text-text-3/75">
|
|
698
|
-
<div className="
|
|
699
|
-
<div className="font-600 text-text">{editing.missionSummary.objective}</div>
|
|
700
|
-
<button
|
|
701
|
-
type="button"
|
|
702
|
-
onClick={() => router.push(getMissionPath(editing.missionSummary?.id || null))}
|
|
703
|
-
className="rounded-[8px] border border-white/[0.08] px-2 py-1 text-[10px] font-700 uppercase tracking-[0.08em] text-text-2 transition-colors hover:bg-white/[0.05]"
|
|
704
|
-
>
|
|
705
|
-
Open
|
|
706
|
-
</button>
|
|
707
|
-
</div>
|
|
708
|
-
<div className="mt-1">
|
|
709
|
-
{editing.missionSummary.waitingReason || editing.missionSummary.currentStep || `Status: ${editing.missionSummary.status}`}
|
|
710
|
-
</div>
|
|
680
|
+
<div className="font-600 text-text">{editing.objective}</div>
|
|
711
681
|
</div>
|
|
712
682
|
</div>
|
|
713
683
|
)}
|