@swarmclawai/swarmclaw 0.7.2 → 0.7.4

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.
Files changed (274) hide show
  1. package/README.md +116 -50
  2. package/bin/package-manager.js +157 -0
  3. package/bin/package-manager.test.js +90 -0
  4. package/bin/server-cmd.js +38 -7
  5. package/bin/swarmclaw.js +54 -4
  6. package/bin/update-cmd.js +48 -10
  7. package/bin/update-cmd.test.js +55 -0
  8. package/package.json +8 -3
  9. package/scripts/postinstall.mjs +26 -0
  10. package/src/app/api/agents/[id]/route.ts +43 -0
  11. package/src/app/api/agents/[id]/thread/route.ts +39 -8
  12. package/src/app/api/agents/route.ts +35 -2
  13. package/src/app/api/auth/route.ts +77 -8
  14. package/src/app/api/chatrooms/[id]/chat/route.ts +22 -6
  15. package/src/app/api/chatrooms/[id]/pins/route.ts +2 -1
  16. package/src/app/api/chatrooms/[id]/reactions/route.ts +2 -1
  17. package/src/app/api/chatrooms/[id]/route.ts +6 -0
  18. package/src/app/api/chats/[id]/browser/route.ts +5 -1
  19. package/src/app/api/chats/[id]/chat/route.ts +7 -3
  20. package/src/app/api/chats/[id]/messages/route.ts +19 -13
  21. package/src/app/api/chats/[id]/route.ts +30 -0
  22. package/src/app/api/chats/[id]/stop/route.ts +6 -1
  23. package/src/app/api/chats/heartbeat/route.ts +2 -1
  24. package/src/app/api/chats/route.ts +23 -1
  25. package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
  26. package/src/app/api/connectors/doctor/route.ts +13 -0
  27. package/src/app/api/external-agents/[id]/heartbeat/route.ts +33 -0
  28. package/src/app/api/external-agents/[id]/route.ts +31 -0
  29. package/src/app/api/external-agents/register/route.ts +3 -0
  30. package/src/app/api/external-agents/route.ts +66 -0
  31. package/src/app/api/files/open/route.ts +16 -14
  32. package/src/app/api/gateways/[id]/health/route.ts +28 -0
  33. package/src/app/api/gateways/[id]/route.ts +79 -0
  34. package/src/app/api/gateways/route.ts +57 -0
  35. package/src/app/api/memory/maintenance/route.ts +11 -1
  36. package/src/app/api/openclaw/agent-files/route.ts +27 -4
  37. package/src/app/api/openclaw/gateway/route.ts +10 -7
  38. package/src/app/api/openclaw/skills/route.ts +12 -4
  39. package/src/app/api/plugins/dependencies/route.ts +24 -0
  40. package/src/app/api/plugins/install/route.ts +15 -92
  41. package/src/app/api/plugins/route.ts +3 -26
  42. package/src/app/api/plugins/settings/route.ts +17 -12
  43. package/src/app/api/plugins/ui/route.ts +1 -0
  44. package/src/app/api/providers/[id]/discover-models/route.ts +27 -0
  45. package/src/app/api/schedules/[id]/route.ts +38 -9
  46. package/src/app/api/schedules/route.ts +51 -28
  47. package/src/app/api/settings/route.ts +55 -17
  48. package/src/app/api/setup/doctor/route.ts +6 -4
  49. package/src/app/api/tasks/[id]/route.ts +16 -6
  50. package/src/app/api/tasks/bulk/route.ts +3 -3
  51. package/src/app/api/tasks/route.ts +9 -4
  52. package/src/app/api/webhooks/[id]/route.ts +8 -1
  53. package/src/app/page.tsx +135 -17
  54. package/src/cli/binary.test.js +142 -0
  55. package/src/cli/index.js +38 -11
  56. package/src/cli/index.test.js +195 -0
  57. package/src/cli/index.ts +21 -12
  58. package/src/cli/server-cmd.test.js +59 -0
  59. package/src/cli/spec.js +20 -2
  60. package/src/components/agents/agent-card.tsx +15 -12
  61. package/src/components/agents/agent-chat-list.tsx +101 -1
  62. package/src/components/agents/agent-list.tsx +46 -9
  63. package/src/components/agents/agent-sheet.tsx +456 -23
  64. package/src/components/agents/inspector-panel.tsx +110 -49
  65. package/src/components/agents/sandbox-env-panel.tsx +4 -1
  66. package/src/components/auth/access-key-gate.tsx +36 -97
  67. package/src/components/auth/setup-wizard.tsx +970 -275
  68. package/src/components/chat/chat-area.tsx +70 -27
  69. package/src/components/chat/chat-card.tsx +6 -21
  70. package/src/components/chat/chat-header.tsx +263 -366
  71. package/src/components/chat/chat-list.tsx +62 -26
  72. package/src/components/chat/checkpoint-timeline.tsx +1 -1
  73. package/src/components/chat/message-list.tsx +145 -19
  74. package/src/components/chatrooms/chatroom-input.tsx +96 -33
  75. package/src/components/chatrooms/chatroom-list.tsx +141 -72
  76. package/src/components/chatrooms/chatroom-message.tsx +7 -6
  77. package/src/components/chatrooms/chatroom-sheet.tsx +13 -1
  78. package/src/components/chatrooms/chatroom-tool-request-banner.tsx +5 -2
  79. package/src/components/chatrooms/chatroom-view.tsx +422 -209
  80. package/src/components/chatrooms/reaction-picker.tsx +38 -33
  81. package/src/components/connectors/connector-list.tsx +265 -127
  82. package/src/components/connectors/connector-sheet.tsx +217 -0
  83. package/src/components/gateways/gateway-sheet.tsx +567 -0
  84. package/src/components/home/home-view.tsx +128 -4
  85. package/src/components/input/chat-input.tsx +135 -86
  86. package/src/components/layout/app-layout.tsx +385 -194
  87. package/src/components/layout/mobile-header.tsx +26 -8
  88. package/src/components/memory/memory-browser.tsx +71 -6
  89. package/src/components/memory/memory-card.tsx +18 -0
  90. package/src/components/memory/memory-detail.tsx +58 -31
  91. package/src/components/memory/memory-sheet.tsx +32 -4
  92. package/src/components/plugins/plugin-list.tsx +15 -3
  93. package/src/components/plugins/plugin-sheet.tsx +118 -9
  94. package/src/components/projects/project-detail.tsx +189 -1
  95. package/src/components/providers/provider-list.tsx +158 -2
  96. package/src/components/providers/provider-sheet.tsx +81 -70
  97. package/src/components/shared/agent-picker-list.tsx +2 -2
  98. package/src/components/shared/bottom-sheet.tsx +31 -15
  99. package/src/components/shared/command-palette.tsx +111 -24
  100. package/src/components/shared/confirm-dialog.tsx +45 -30
  101. package/src/components/shared/model-combobox.tsx +90 -8
  102. package/src/components/shared/settings/plugin-manager.tsx +20 -4
  103. package/src/components/shared/settings/section-capability-policy.tsx +105 -0
  104. package/src/components/shared/settings/section-heartbeat.tsx +88 -6
  105. package/src/components/shared/settings/section-orchestrator.tsx +6 -3
  106. package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
  107. package/src/components/shared/settings/section-secrets.tsx +6 -6
  108. package/src/components/shared/settings/section-user-preferences.tsx +1 -1
  109. package/src/components/shared/settings/section-voice.tsx +5 -1
  110. package/src/components/shared/settings/section-web-search.tsx +10 -2
  111. package/src/components/shared/settings/settings-page.tsx +248 -47
  112. package/src/components/tasks/approvals-panel.tsx +211 -18
  113. package/src/components/tasks/task-board.tsx +242 -46
  114. package/src/components/ui/dialog.tsx +2 -2
  115. package/src/components/usage/metrics-dashboard.tsx +74 -1
  116. package/src/components/wallets/wallet-approval-dialog.tsx +59 -54
  117. package/src/components/wallets/wallet-panel.tsx +17 -5
  118. package/src/components/webhooks/webhook-sheet.tsx +7 -7
  119. package/src/lib/auth.ts +17 -0
  120. package/src/lib/chat-streaming-state.test.ts +108 -0
  121. package/src/lib/chat-streaming-state.ts +108 -0
  122. package/src/lib/heartbeat-defaults.ts +48 -0
  123. package/src/lib/memory-presentation.ts +59 -0
  124. package/src/lib/openclaw-agent-id.test.ts +14 -0
  125. package/src/lib/openclaw-agent-id.ts +31 -0
  126. package/src/lib/provider-model-discovery-client.ts +29 -0
  127. package/src/lib/providers/index.ts +12 -5
  128. package/src/lib/runtime-loop.ts +105 -3
  129. package/src/lib/safe-storage.ts +6 -1
  130. package/src/lib/server/agent-assignment.test.ts +112 -0
  131. package/src/lib/server/agent-assignment.ts +169 -0
  132. package/src/lib/server/agent-runtime-config.test.ts +141 -0
  133. package/src/lib/server/agent-runtime-config.ts +277 -0
  134. package/src/lib/server/approval-connector-notify.test.ts +253 -0
  135. package/src/lib/server/approvals-auto-approve.test.ts +264 -0
  136. package/src/lib/server/approvals.ts +483 -75
  137. package/src/lib/server/autonomy-runtime.test.ts +341 -0
  138. package/src/lib/server/browser-state.test.ts +118 -0
  139. package/src/lib/server/browser-state.ts +123 -0
  140. package/src/lib/server/build-llm.test.ts +44 -0
  141. package/src/lib/server/build-llm.ts +11 -4
  142. package/src/lib/server/builtin-plugins.ts +34 -0
  143. package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
  144. package/src/lib/server/chat-execution-tool-events.test.ts +219 -0
  145. package/src/lib/server/chat-execution.ts +402 -125
  146. package/src/lib/server/chatroom-health.test.ts +26 -0
  147. package/src/lib/server/chatroom-health.ts +2 -3
  148. package/src/lib/server/chatroom-helpers.test.ts +74 -2
  149. package/src/lib/server/chatroom-helpers.ts +144 -11
  150. package/src/lib/server/chatroom-session-persistence.test.ts +87 -0
  151. package/src/lib/server/connectors/discord.ts +175 -11
  152. package/src/lib/server/connectors/doctor.test.ts +80 -0
  153. package/src/lib/server/connectors/doctor.ts +116 -0
  154. package/src/lib/server/connectors/manager.ts +994 -130
  155. package/src/lib/server/connectors/policy.test.ts +222 -0
  156. package/src/lib/server/connectors/policy.ts +452 -0
  157. package/src/lib/server/connectors/slack.ts +189 -10
  158. package/src/lib/server/connectors/telegram.ts +65 -15
  159. package/src/lib/server/connectors/thread-context.test.ts +44 -0
  160. package/src/lib/server/connectors/thread-context.ts +72 -0
  161. package/src/lib/server/connectors/types.ts +41 -11
  162. package/src/lib/server/daemon-state.ts +62 -3
  163. package/src/lib/server/data-dir.ts +13 -0
  164. package/src/lib/server/delegation-jobs.test.ts +140 -0
  165. package/src/lib/server/delegation-jobs.ts +248 -0
  166. package/src/lib/server/document-utils.test.ts +47 -0
  167. package/src/lib/server/document-utils.ts +397 -0
  168. package/src/lib/server/eval/agent-regression.test.ts +47 -0
  169. package/src/lib/server/eval/agent-regression.ts +1742 -0
  170. package/src/lib/server/eval/runner.ts +11 -1
  171. package/src/lib/server/eval/store.ts +2 -1
  172. package/src/lib/server/heartbeat-service.ts +23 -43
  173. package/src/lib/server/heartbeat-source.test.ts +22 -0
  174. package/src/lib/server/heartbeat-source.ts +7 -0
  175. package/src/lib/server/identity-continuity.test.ts +77 -0
  176. package/src/lib/server/identity-continuity.ts +127 -0
  177. package/src/lib/server/mailbox-utils.ts +347 -0
  178. package/src/lib/server/main-agent-loop.ts +31 -964
  179. package/src/lib/server/memory-db.ts +4 -6
  180. package/src/lib/server/memory-tiers.ts +40 -0
  181. package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
  182. package/src/lib/server/openclaw-agent-resolver.ts +128 -0
  183. package/src/lib/server/openclaw-exec-config.ts +6 -5
  184. package/src/lib/server/openclaw-gateway.ts +123 -36
  185. package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
  186. package/src/lib/server/openclaw-skills-normalize.ts +136 -0
  187. package/src/lib/server/openclaw-sync.ts +3 -2
  188. package/src/lib/server/orchestrator-lg.ts +18 -8
  189. package/src/lib/server/orchestrator.ts +5 -4
  190. package/src/lib/server/playwright-proxy.mjs +27 -3
  191. package/src/lib/server/plugins.test.ts +215 -0
  192. package/src/lib/server/plugins.ts +832 -69
  193. package/src/lib/server/provider-health.ts +33 -3
  194. package/src/lib/server/provider-model-discovery.ts +481 -0
  195. package/src/lib/server/queue.ts +4 -21
  196. package/src/lib/server/runtime-settings.test.ts +119 -0
  197. package/src/lib/server/runtime-settings.ts +12 -92
  198. package/src/lib/server/schedule-normalization.ts +187 -0
  199. package/src/lib/server/scheduler.ts +2 -0
  200. package/src/lib/server/session-archive-memory.test.ts +85 -0
  201. package/src/lib/server/session-archive-memory.ts +230 -0
  202. package/src/lib/server/session-mailbox.ts +8 -18
  203. package/src/lib/server/session-reset-policy.test.ts +99 -0
  204. package/src/lib/server/session-reset-policy.ts +311 -0
  205. package/src/lib/server/session-run-manager.ts +33 -80
  206. package/src/lib/server/session-tools/autonomy-tools.test.ts +128 -0
  207. package/src/lib/server/session-tools/calendar.ts +2 -12
  208. package/src/lib/server/session-tools/connector.ts +109 -8
  209. package/src/lib/server/session-tools/context.ts +14 -2
  210. package/src/lib/server/session-tools/crawl.ts +447 -0
  211. package/src/lib/server/session-tools/crud.ts +96 -34
  212. package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
  213. package/src/lib/server/session-tools/delegate.ts +406 -20
  214. package/src/lib/server/session-tools/discovery-approvals.test.ts +170 -0
  215. package/src/lib/server/session-tools/discovery.ts +40 -12
  216. package/src/lib/server/session-tools/document.ts +283 -0
  217. package/src/lib/server/session-tools/email.ts +1 -3
  218. package/src/lib/server/session-tools/extract.ts +137 -0
  219. package/src/lib/server/session-tools/file-normalize.test.ts +98 -0
  220. package/src/lib/server/session-tools/file-send.test.ts +84 -1
  221. package/src/lib/server/session-tools/file.ts +243 -24
  222. package/src/lib/server/session-tools/http.ts +9 -3
  223. package/src/lib/server/session-tools/human-loop.ts +227 -0
  224. package/src/lib/server/session-tools/image-gen.ts +1 -3
  225. package/src/lib/server/session-tools/index.ts +87 -2
  226. package/src/lib/server/session-tools/mailbox.ts +276 -0
  227. package/src/lib/server/session-tools/manage-schedules.test.ts +137 -0
  228. package/src/lib/server/session-tools/memory.ts +35 -3
  229. package/src/lib/server/session-tools/monitor.ts +162 -12
  230. package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
  231. package/src/lib/server/session-tools/openclaw-nodes.test.ts +111 -0
  232. package/src/lib/server/session-tools/openclaw-nodes.ts +86 -20
  233. package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
  234. package/src/lib/server/session-tools/platform.ts +142 -4
  235. package/src/lib/server/session-tools/plugin-creator.ts +95 -25
  236. package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
  237. package/src/lib/server/session-tools/replicate.ts +1 -3
  238. package/src/lib/server/session-tools/sandbox.ts +51 -92
  239. package/src/lib/server/session-tools/schedule.ts +20 -10
  240. package/src/lib/server/session-tools/session-info.ts +58 -4
  241. package/src/lib/server/session-tools/session-tools-wiring.test.ts +54 -17
  242. package/src/lib/server/session-tools/shell.ts +2 -2
  243. package/src/lib/server/session-tools/subagent.ts +195 -27
  244. package/src/lib/server/session-tools/table.ts +587 -0
  245. package/src/lib/server/session-tools/wallet.ts +13 -10
  246. package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
  247. package/src/lib/server/session-tools/web.ts +947 -108
  248. package/src/lib/server/storage.ts +255 -10
  249. package/src/lib/server/stream-agent-chat.test.ts +61 -0
  250. package/src/lib/server/stream-agent-chat.ts +185 -25
  251. package/src/lib/server/structured-extract.test.ts +72 -0
  252. package/src/lib/server/structured-extract.ts +373 -0
  253. package/src/lib/server/task-mention.test.ts +16 -2
  254. package/src/lib/server/task-mention.ts +61 -11
  255. package/src/lib/server/tool-aliases.ts +80 -12
  256. package/src/lib/server/tool-capability-policy.ts +7 -1
  257. package/src/lib/server/tool-retry.ts +2 -0
  258. package/src/lib/server/watch-jobs.test.ts +173 -0
  259. package/src/lib/server/watch-jobs.ts +532 -0
  260. package/src/lib/server/ws-hub.ts +5 -3
  261. package/src/lib/setup-defaults.ts +352 -11
  262. package/src/lib/tool-definitions.ts +3 -4
  263. package/src/lib/validation/schemas.test.ts +26 -0
  264. package/src/lib/validation/schemas.ts +62 -1
  265. package/src/lib/ws-client.ts +14 -12
  266. package/src/proxy.ts +5 -5
  267. package/src/stores/use-app-store.ts +43 -7
  268. package/src/stores/use-chat-store.ts +31 -2
  269. package/src/stores/use-chatroom-store.ts +153 -26
  270. package/src/types/index.ts +470 -44
  271. package/src/app/api/chats/[id]/main-loop/route.ts +0 -94
  272. package/src/components/chat/new-chat-sheet.tsx +0 -253
  273. package/src/lib/server/main-session.ts +0 -17
  274. package/src/lib/server/session-run-manager.test.ts +0 -26
@@ -1,94 +0,0 @@
1
- import { NextResponse } from 'next/server'
2
- import { enqueueSessionRun } from '@/lib/server/session-run-manager'
3
- import { loadSessions } from '@/lib/server/storage'
4
- import {
5
- buildMainLoopHeartbeatPrompt,
6
- getMainLoopStateForSession,
7
- isMainSession,
8
- pushMainLoopEventToMainSessions,
9
- setMainLoopStateForSession,
10
- } from '@/lib/server/main-agent-loop'
11
-
12
- export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
13
- const { id } = await params
14
- const sessions = loadSessions()
15
- const session = sessions[id]
16
- if (!session) return new NextResponse('Session not found', { status: 404 })
17
- if (!isMainSession(session)) return new NextResponse('Main-loop controls only apply to agent thread sessions', { status: 400 })
18
- const state = getMainLoopStateForSession(id)
19
- return NextResponse.json({ sessionId: id, state })
20
- }
21
-
22
- export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
23
- const { id } = await params
24
- const body = await req.json().catch(() => ({}))
25
- const action = typeof body.action === 'string' ? body.action.trim() : ''
26
-
27
- const sessions = loadSessions()
28
- const session = sessions[id]
29
- if (!session) return new NextResponse('Session not found', { status: 404 })
30
- if (!isMainSession(session)) return new NextResponse('Main-loop controls only apply to agent thread sessions', { status: 400 })
31
-
32
- if (action === 'pause') {
33
- const state = setMainLoopStateForSession(id, { paused: true })
34
- return NextResponse.json({ ok: true, action, state })
35
- }
36
-
37
- if (action === 'resume') {
38
- const state = setMainLoopStateForSession(id, { paused: false })
39
- return NextResponse.json({ ok: true, action, state })
40
- }
41
-
42
- if (action === 'set_goal') {
43
- const goal = typeof body.goal === 'string' ? body.goal.trim() : ''
44
- if (!goal) return new NextResponse('goal is required for set_goal', { status: 400 })
45
- const state = setMainLoopStateForSession(id, {
46
- goal,
47
- status: 'progress',
48
- paused: false,
49
- followupChainCount: 0,
50
- })
51
- pushMainLoopEventToMainSessions({
52
- type: 'operator_goal',
53
- text: `Operator set mission goal: ${goal}`,
54
- user: session.user || null,
55
- })
56
- return NextResponse.json({ ok: true, action, state })
57
- }
58
-
59
- if (action === 'set_mode') {
60
- const mode = body.mode === 'assist' ? 'assist' : body.mode === 'autonomous' ? 'autonomous' : null
61
- if (!mode) return new NextResponse('mode must be "assist" or "autonomous"', { status: 400 })
62
- const state = setMainLoopStateForSession(id, { autonomyMode: mode })
63
- return NextResponse.json({ ok: true, action, state })
64
- }
65
-
66
- if (action === 'clear_events') {
67
- const state = setMainLoopStateForSession(id, { pendingEvents: [] })
68
- return NextResponse.json({ ok: true, action, state })
69
- }
70
-
71
- if (action === 'nudge') {
72
- const state = getMainLoopStateForSession(id)
73
- if (state?.paused) {
74
- return new NextResponse('Mission loop is paused; resume first', { status: 409 })
75
- }
76
- const note = typeof body.note === 'string' ? body.note.trim() : ''
77
- const prompt = buildMainLoopHeartbeatPrompt(
78
- session,
79
- 'Operator requested manual nudge: execute one concrete next step now and report concise progress.',
80
- )
81
- const message = note ? `${prompt}\nOperator note: ${note.slice(0, 500)}` : prompt
82
- const run = enqueueSessionRun({
83
- sessionId: id,
84
- message,
85
- internal: true,
86
- source: 'mission-control',
87
- mode: 'collect',
88
- dedupeKey: `mission-control:nudge:${id}`,
89
- })
90
- return NextResponse.json({ ok: true, action, runId: run.runId, position: run.position, deduped: run.deduped || false, state })
91
- }
92
-
93
- return new NextResponse('Unknown action. Use pause, resume, set_goal, set_mode, clear_events, or nudge.', { status: 400 })
94
- }
@@ -1,253 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useMemo } from 'react'
4
- import { BottomSheet } from '@/components/shared/bottom-sheet'
5
- import { SectionLabel } from '@/components/shared/section-label'
6
- import { useAppStore } from '@/stores/use-app-store'
7
- import { api } from '@/lib/api-client'
8
- import { PROVIDERS } from '@/lib/providers'
9
- import { TOOL_LABELS, TOOL_DESCRIPTIONS } from '@/components/chat/tool-call-bubble'
10
- import { toast } from 'sonner'
11
- import { useRouter } from 'next/navigation'
12
- import { genId } from '@/lib/id'
13
- import type { ProviderType, SessionTool } from '@/types'
14
-
15
- interface Props {
16
- open: boolean
17
- onClose: () => void
18
- }
19
-
20
- export function NewChatSheet({ open, onClose }: Props) {
21
- const router = useRouter()
22
- const agents = useAppStore((s) => s.agents)
23
- const loadSessions = useAppStore((s) => s.loadSessions)
24
-
25
- const [selectedAgentId, setSelectedAgentId] = useState<string>('')
26
- const [provider, setProvider] = useState<ProviderType>('openai')
27
- const [model, setModel] = useState<string>('')
28
- const [endpoint, setEndpoint] = useState('')
29
- const [selectedTools, setSelectedTools] = useState<SessionTool[]>([])
30
- const [loading, setLoading] = useState(false)
31
-
32
- const agentList = useMemo(() => Object.values(agents).sort((a, b) => b.updatedAt - a.updatedAt), [agents])
33
- const currentProvider = PROVIDERS[provider]
34
-
35
- const reset = () => {
36
- setSelectedAgentId('')
37
- setProvider('openai')
38
- setModel('')
39
- setEndpoint('')
40
- setSelectedTools([])
41
- }
42
-
43
- const handleCreate = async () => {
44
- setLoading(true)
45
- try {
46
- const agent = selectedAgentId ? agents[selectedAgentId] : null
47
- const id = genId(8)
48
- const now = Date.now()
49
-
50
- const agentTools = agent?.plugins || (selectedTools.length ? selectedTools : undefined)
51
-
52
- const session = {
53
- id,
54
- name: agent ? `Chat with ${agent.name}` : `New Session (${model || provider})`,
55
- provider: agent ? agent.provider : provider,
56
- model: agent ? agent.model : model,
57
- apiEndpoint: agent ? agent.apiEndpoint : (endpoint || undefined),
58
- credentialId: agent ? agent.credentialId : undefined,
59
- plugins: agentTools || undefined,
60
- messages: [],
61
- createdAt: now,
62
- updatedAt: now,
63
- active: true,
64
- agentId: selectedAgentId || undefined,
65
- }
66
-
67
- await api('POST', '/chats', session)
68
- await loadSessions()
69
- router.push(`/chat?session=${id}`)
70
- onClose()
71
- reset()
72
- } catch (err: unknown) {
73
- toast.error(err instanceof Error ? err.message : 'Failed to create session')
74
- } finally {
75
- setLoading(false)
76
- }
77
- }
78
-
79
- const inputClass = "w-full py-3 px-4 rounded-[14px] bg-surface border border-white/[0.06] text-text placeholder:text-text-3/50 outline-none focus:border-accent-bright/30 transition-all"
80
-
81
- return (
82
- <BottomSheet open={open} onClose={onClose}>
83
- <div className="mb-10">
84
- <h2 className="font-display text-[28px] font-700 tracking-[-0.03em] mb-2">New Session</h2>
85
- <p className="text-[14px] text-text-3">Start a new conversation with an agent or a direct model.</p>
86
- </div>
87
-
88
- <div className="mb-8">
89
- <SectionLabel>Select Agent</SectionLabel>
90
- <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
91
- <button
92
- onClick={() => setSelectedAgentId('')}
93
- className={`flex flex-col items-center justify-center gap-2 p-4 rounded-[18px] border transition-all duration-200 cursor-pointer
94
- ${!selectedAgentId
95
- ? 'bg-accent-soft border-accent-bright/25 text-accent-bright shadow-[0_0_25px_rgba(99,102,241,0.12)]'
96
- : 'bg-surface border-white/[0.06] text-text-3 hover:bg-surface-2 hover:border-white/[0.08]'}`}
97
- >
98
- <div className={`w-10 h-10 rounded-full flex items-center justify-center ${!selectedAgentId ? 'bg-accent-bright/20' : 'bg-white/[0.04]'}`}>
99
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
100
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" />
101
- </svg>
102
- </div>
103
- <span className="text-[13px] font-600">Direct Model</span>
104
- </button>
105
-
106
- {agentList.map((a) => (
107
- <button
108
- key={a.id}
109
- onClick={() => setSelectedAgentId(a.id)}
110
- className={`flex flex-col items-center justify-center gap-2 p-4 rounded-[18px] border transition-all duration-200 cursor-pointer
111
- ${selectedAgentId === a.id
112
- ? 'bg-accent-soft border-accent-bright/25 text-accent-bright shadow-[0_0_25px_rgba(99,102,241,0.12)]'
113
- : 'bg-surface border-white/[0.06] text-text-3 hover:bg-surface-2 hover:border-white/[0.08]'}`}
114
- >
115
- <div className="w-10 h-10 rounded-full bg-accent-bright/10 overflow-hidden">
116
- {/* eslint-disable-next-line @next/next/no-img-element */}
117
- <img src={`https://api.dicebear.com/7.x/bottts-neutral/svg?seed=${a.avatarSeed || a.id}`} alt="" />
118
- </div>
119
- <span className="text-[13px] font-600 truncate w-full text-center px-1">{a.name}</span>
120
- </button>
121
- ))}
122
- </div>
123
- </div>
124
-
125
- {!selectedAgentId && (
126
- <>
127
- <div className="grid grid-cols-2 gap-4 mb-6">
128
- <div>
129
- <SectionLabel>Provider</SectionLabel>
130
- <select
131
- value={provider}
132
- onChange={(e) => {
133
- const p = e.target.value as ProviderType
134
- setProvider(p)
135
- setModel(PROVIDERS[p].models[0])
136
- }}
137
- className={`${inputClass} appearance-none cursor-pointer`}
138
- style={{ fontFamily: 'inherit' }}
139
- >
140
- {Object.values(PROVIDERS).map((p) => (
141
- <option key={p.id} value={p.id}>{p.name}</option>
142
- ))}
143
- </select>
144
- </div>
145
- <div>
146
- <SectionLabel>Model</SectionLabel>
147
- <select
148
- value={model}
149
- onChange={(e) => setModel(e.target.value)}
150
- className={`${inputClass} appearance-none cursor-pointer`}
151
- style={{ fontFamily: 'inherit' }}
152
- >
153
- {currentProvider.models.map((m) => (
154
- <option key={m} value={m}>{m}</option>
155
- ))}
156
- </select>
157
- </div>
158
- </div>
159
-
160
- {currentProvider.requiresEndpoint && (
161
- <div className="mb-8">
162
- <SectionLabel>{provider === 'openclaw' ? 'OpenClaw Endpoint' : 'Endpoint'}</SectionLabel>
163
- <input
164
- type="text"
165
- value={endpoint}
166
- onChange={(e) => setEndpoint(e.target.value)}
167
- placeholder={currentProvider.defaultEndpoint || 'http://localhost:11434'}
168
- className={`${inputClass} font-mono text-[14px]`}
169
- />
170
- {provider === 'openclaw' && (
171
- <p className="text-[11px] text-text-3/60 mt-2">
172
- The /v1 endpoint of your remote OpenClaw instance
173
- </p>
174
- )}
175
- </div>
176
- )}
177
-
178
- {/* Plugins (Capability enablement) */}
179
- <div className="mb-8">
180
- <label className="block font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-3">
181
- Plugins <span className="normal-case tracking-normal font-normal text-text-3">(optional)</span>
182
- </label>
183
- <p className="text-[12px] text-text-3/60 mb-3">Allow this model to execute commands and access files.</p>
184
- <div className="flex flex-wrap gap-2.5">
185
- {([
186
- { id: 'shell' as SessionTool, label: 'Shell' },
187
- { id: 'files' as SessionTool, label: 'Files' },
188
- { id: 'edit_file' as SessionTool, label: 'Edit File' },
189
- { id: 'web_search' as SessionTool, label: 'Web Search' },
190
- { id: 'web_fetch' as SessionTool, label: 'Web Fetch' },
191
- { id: 'claude_code' as SessionTool, label: 'Claude Code' },
192
- { id: 'codex_cli' as SessionTool, label: 'Codex CLI' },
193
- { id: 'opencode_cli' as SessionTool, label: 'OpenCode CLI' },
194
- ]).map(({ id, label }) => {
195
- const active = selectedTools.includes(id)
196
- return (
197
- <button
198
- key={id}
199
- onClick={() => {
200
- setSelectedTools((prev) =>
201
- active ? prev.filter((t) => t !== id) : [...prev, id],
202
- )
203
- }}
204
- className={`px-4 py-2.5 rounded-[12px] text-[13px] font-600 border cursor-pointer transition-all duration-200 active:scale-[0.97]
205
- ${active
206
- ? 'bg-accent-soft border-accent-bright/25 text-accent-bright shadow-[0_0_20px_rgba(99,102,241,0.1)]'
207
- : 'bg-surface border-white/[0.06] text-text-3 hover:bg-surface-2 hover:border-white/[0.08]'}`}
208
- style={{ fontFamily: 'inherit' }}
209
- >
210
- {label}
211
- </button>
212
- )
213
- })}
214
- </div>
215
- </div>
216
- </>
217
- )}
218
-
219
- {/* Summary when agent selected */}
220
- {selectedAgentId && agents[selectedAgentId] && (
221
- <div className="mb-8 px-4 py-3 rounded-[14px] bg-surface border border-white/[0.06]">
222
- <span className="text-[13px] text-text-3">
223
- Using <span className="text-text-2 font-600">{agents[selectedAgentId].provider}</span>
224
- {' / '}
225
- <span className="text-text-2 font-600">{agents[selectedAgentId].model}</span>
226
- {agents[selectedAgentId].plugins?.length ? (
227
- <>
228
- {' + '}
229
- {agents[selectedAgentId].plugins!.map((tool, i) => (
230
- <span key={tool}>
231
- {i > 0 && ', '}
232
- <span className="text-sky-400/70 font-600 cursor-help" title={TOOL_DESCRIPTIONS[tool] || tool}>
233
- {TOOL_LABELS[tool] || tool.replace(/_/g, ' ')}
234
- </span>
235
- </span>
236
- ))}
237
- </>
238
- ) : null}
239
- </span>
240
- </div>
241
- )}
242
-
243
- <button
244
- onClick={handleCreate}
245
- disabled={loading || (!selectedAgentId && !model)}
246
- className="w-full py-4 rounded-[18px] bg-accent-bright text-white font-display text-[15px] font-700 shadow-[0_0_30px_rgba(56,189,248,0.3)] hover:shadow-[0_0_40px_rgba(56,189,248,0.45)] hover:scale-[1.01] active:scale-[0.99] transition-all disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:shadow-none"
247
- style={{ fontFamily: 'inherit' }}
248
- >
249
- {loading ? 'Creating...' : 'Start Session'}
250
- </button>
251
- </BottomSheet>
252
- )
253
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Returns true for sessions that participate in the main-agent-loop
3
- * (autonomous followups, mission tracking, etc).
4
- * This includes agent thread sessions and orchestrated task sessions.
5
- */
6
- export function isMainLoopSession(session: any): boolean {
7
- if (!session || typeof session !== 'object') return false
8
- if (session.sessionType === 'orchestrated') return true
9
-
10
- const id = typeof session.id === 'string' ? session.id.trim() : ''
11
- if (id.startsWith('agent-thread-')) return true
12
-
13
- const name = typeof session.name === 'string' ? session.name.trim() : ''
14
- if (name.startsWith('agent-thread:')) return true
15
-
16
- return false
17
- }
@@ -1,26 +0,0 @@
1
- import { describe, it } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { isMainMissionSession } from './session-run-manager'
4
-
5
- describe('isMainMissionSession', () => {
6
- it('accepts agent-thread sessions', () => {
7
- assert.equal(
8
- isMainMissionSession({ id: 'agent-thread-agent_coder-123', name: 'agent-thread:agent_coder', sessionType: 'human' }),
9
- true,
10
- )
11
- })
12
-
13
- it('accepts orchestrated sessions', () => {
14
- assert.equal(
15
- isMainMissionSession({ id: 'agent-thread-worker-1', name: 'agent-thread:worker', sessionType: 'orchestrated' }),
16
- true,
17
- )
18
- })
19
-
20
- it('rejects regular chat sessions', () => {
21
- assert.equal(
22
- isMainMissionSession({ id: 'abc123', name: 'New Chat', sessionType: 'human' }),
23
- false,
24
- )
25
- })
26
- })