@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.
Files changed (237) hide show
  1. package/README.md +155 -150
  2. package/package.json +1 -1
  3. package/src/app/api/agents/[id]/route.ts +26 -0
  4. package/src/app/api/agents/[id]/thread/route.ts +37 -9
  5. package/src/app/api/agents/route.ts +13 -2
  6. package/src/app/api/auth/route.ts +76 -7
  7. package/src/app/api/chatrooms/[id]/chat/route.ts +7 -2
  8. package/src/app/api/{sessions → chats}/[id]/browser/route.ts +5 -1
  9. package/src/app/api/{sessions → chats}/[id]/chat/route.ts +7 -3
  10. package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
  11. package/src/app/api/chats/[id]/main-loop/route.ts +13 -0
  12. package/src/app/api/{sessions → chats}/[id]/messages/route.ts +19 -13
  13. package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
  14. package/src/app/api/{sessions → chats}/[id]/route.ts +22 -52
  15. package/src/app/api/{sessions → chats}/[id]/stop/route.ts +6 -1
  16. package/src/app/api/{sessions → chats}/route.ts +21 -7
  17. package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
  18. package/src/app/api/connectors/doctor/route.ts +13 -0
  19. package/src/app/api/files/open/route.ts +16 -14
  20. package/src/app/api/memory/maintenance/route.ts +11 -1
  21. package/src/app/api/openclaw/agent-files/route.ts +27 -4
  22. package/src/app/api/openclaw/skills/route.ts +11 -3
  23. package/src/app/api/plugins/dependencies/route.ts +24 -0
  24. package/src/app/api/plugins/install/route.ts +15 -92
  25. package/src/app/api/plugins/route.ts +6 -26
  26. package/src/app/api/plugins/settings/route.ts +40 -0
  27. package/src/app/api/plugins/ui/route.ts +1 -0
  28. package/src/app/api/settings/route.ts +49 -7
  29. package/src/app/api/tasks/[id]/route.ts +15 -6
  30. package/src/app/api/tasks/bulk/route.ts +2 -2
  31. package/src/app/api/tasks/route.ts +9 -4
  32. package/src/app/api/usage/route.ts +30 -0
  33. package/src/app/api/webhooks/[id]/route.ts +8 -1
  34. package/src/app/page.tsx +9 -2
  35. package/src/cli/index.js +39 -33
  36. package/src/cli/index.ts +43 -49
  37. package/src/cli/spec.js +29 -27
  38. package/src/components/agents/agent-card.tsx +16 -13
  39. package/src/components/agents/agent-chat-list.tsx +104 -4
  40. package/src/components/agents/agent-list.tsx +54 -22
  41. package/src/components/agents/agent-sheet.tsx +209 -18
  42. package/src/components/agents/cron-job-form.tsx +3 -3
  43. package/src/components/agents/inspector-panel.tsx +110 -50
  44. package/src/components/auth/access-key-gate.tsx +36 -97
  45. package/src/components/auth/setup-wizard.tsx +5 -38
  46. package/src/components/chat/chat-area.tsx +39 -27
  47. package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +7 -23
  48. package/src/components/chat/chat-header.tsx +299 -314
  49. package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +11 -14
  50. package/src/components/chat/chat-tool-toggles.tsx +26 -17
  51. package/src/components/chat/checkpoint-timeline.tsx +4 -4
  52. package/src/components/chat/message-bubble.tsx +4 -1
  53. package/src/components/chat/message-list.tsx +5 -3
  54. package/src/components/chat/session-debug-panel.tsx +1 -1
  55. package/src/components/chat/tool-request-banner.tsx +3 -3
  56. package/src/components/chatrooms/agent-hover-card.tsx +3 -3
  57. package/src/components/chatrooms/chatroom-tool-request-banner.tsx +2 -2
  58. package/src/components/chatrooms/chatroom-view.tsx +347 -205
  59. package/src/components/connectors/connector-list.tsx +265 -127
  60. package/src/components/connectors/connector-sheet.tsx +218 -1
  61. package/src/components/home/home-view.tsx +129 -5
  62. package/src/components/layout/app-layout.tsx +392 -182
  63. package/src/components/layout/mobile-header.tsx +26 -8
  64. package/src/components/plugins/plugin-list.tsx +487 -254
  65. package/src/components/plugins/plugin-sheet.tsx +236 -13
  66. package/src/components/projects/project-detail.tsx +183 -0
  67. package/src/components/settings/gateway-connection-panel.tsx +1 -1
  68. package/src/components/shared/agent-picker-list.tsx +2 -2
  69. package/src/components/shared/command-palette.tsx +111 -25
  70. package/src/components/shared/settings/plugin-manager.tsx +20 -4
  71. package/src/components/shared/settings/section-capability-policy.tsx +105 -0
  72. package/src/components/shared/settings/section-heartbeat.tsx +78 -1
  73. package/src/components/shared/settings/section-orchestrator.tsx +3 -3
  74. package/src/components/shared/settings/section-providers.tsx +1 -1
  75. package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
  76. package/src/components/shared/settings/section-secrets.tsx +6 -6
  77. package/src/components/shared/settings/section-user-preferences.tsx +1 -1
  78. package/src/components/shared/settings/section-voice.tsx +5 -1
  79. package/src/components/shared/settings/section-web-search.tsx +10 -2
  80. package/src/components/shared/settings/settings-page.tsx +244 -56
  81. package/src/components/tasks/approvals-panel.tsx +205 -18
  82. package/src/components/tasks/task-board.tsx +242 -46
  83. package/src/components/usage/metrics-dashboard.tsx +147 -1
  84. package/src/components/wallets/wallet-panel.tsx +17 -5
  85. package/src/components/webhooks/webhook-sheet.tsx +8 -8
  86. package/src/lib/auth.ts +17 -0
  87. package/src/lib/chat-streaming-state.test.ts +108 -0
  88. package/src/lib/chat-streaming-state.ts +108 -0
  89. package/src/lib/chat.ts +1 -1
  90. package/src/lib/{sessions.ts → chats.ts} +28 -18
  91. package/src/lib/openclaw-agent-id.test.ts +14 -0
  92. package/src/lib/openclaw-agent-id.ts +31 -0
  93. package/src/lib/providers/claude-cli.ts +1 -1
  94. package/src/lib/server/agent-assignment.test.ts +112 -0
  95. package/src/lib/server/agent-assignment.ts +169 -0
  96. package/src/lib/server/approval-connector-notify.test.ts +253 -0
  97. package/src/lib/server/approvals-auto-approve.test.ts +205 -0
  98. package/src/lib/server/approvals.ts +483 -75
  99. package/src/lib/server/autonomy-runtime.test.ts +341 -0
  100. package/src/lib/server/browser-state.test.ts +118 -0
  101. package/src/lib/server/browser-state.ts +123 -0
  102. package/src/lib/server/build-llm.test.ts +36 -0
  103. package/src/lib/server/build-llm.ts +11 -4
  104. package/src/lib/server/builtin-plugins.ts +34 -0
  105. package/src/lib/server/capability-router.ts +10 -8
  106. package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
  107. package/src/lib/server/chat-execution-tool-events.test.ts +134 -0
  108. package/src/lib/server/chat-execution.ts +285 -165
  109. package/src/lib/server/chatroom-health.test.ts +26 -0
  110. package/src/lib/server/chatroom-health.ts +2 -3
  111. package/src/lib/server/chatroom-helpers.test.ts +67 -2
  112. package/src/lib/server/chatroom-helpers.ts +48 -8
  113. package/src/lib/server/connectors/discord.ts +175 -11
  114. package/src/lib/server/connectors/doctor.test.ts +80 -0
  115. package/src/lib/server/connectors/doctor.ts +116 -0
  116. package/src/lib/server/connectors/manager.ts +948 -112
  117. package/src/lib/server/connectors/policy.test.ts +222 -0
  118. package/src/lib/server/connectors/policy.ts +452 -0
  119. package/src/lib/server/connectors/slack.ts +188 -9
  120. package/src/lib/server/connectors/telegram.ts +65 -15
  121. package/src/lib/server/connectors/thread-context.test.ts +44 -0
  122. package/src/lib/server/connectors/thread-context.ts +72 -0
  123. package/src/lib/server/connectors/types.ts +41 -11
  124. package/src/lib/server/cost.ts +34 -1
  125. package/src/lib/server/daemon-state.ts +61 -3
  126. package/src/lib/server/data-dir.ts +13 -0
  127. package/src/lib/server/delegation-jobs.test.ts +140 -0
  128. package/src/lib/server/delegation-jobs.ts +248 -0
  129. package/src/lib/server/document-utils.test.ts +47 -0
  130. package/src/lib/server/document-utils.ts +397 -0
  131. package/src/lib/server/heartbeat-service.ts +14 -40
  132. package/src/lib/server/heartbeat-source.test.ts +22 -0
  133. package/src/lib/server/heartbeat-source.ts +7 -0
  134. package/src/lib/server/identity-continuity.test.ts +77 -0
  135. package/src/lib/server/identity-continuity.ts +127 -0
  136. package/src/lib/server/mailbox-utils.ts +347 -0
  137. package/src/lib/server/main-agent-loop.ts +28 -1103
  138. package/src/lib/server/memory-db.ts +4 -6
  139. package/src/lib/server/memory-tiers.ts +40 -0
  140. package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
  141. package/src/lib/server/openclaw-agent-resolver.ts +128 -0
  142. package/src/lib/server/openclaw-exec-config.ts +5 -6
  143. package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
  144. package/src/lib/server/openclaw-skills-normalize.ts +136 -0
  145. package/src/lib/server/openclaw-sync.ts +3 -2
  146. package/src/lib/server/orchestrator-lg.ts +20 -9
  147. package/src/lib/server/orchestrator.ts +7 -7
  148. package/src/lib/server/playwright-proxy.mjs +27 -3
  149. package/src/lib/server/plugins.test.ts +207 -0
  150. package/src/lib/server/plugins.ts +927 -66
  151. package/src/lib/server/provider-health.ts +38 -6
  152. package/src/lib/server/queue.ts +13 -28
  153. package/src/lib/server/scheduler.ts +2 -0
  154. package/src/lib/server/session-archive-memory.test.ts +85 -0
  155. package/src/lib/server/session-archive-memory.ts +230 -0
  156. package/src/lib/server/session-mailbox.ts +8 -18
  157. package/src/lib/server/session-reset-policy.test.ts +99 -0
  158. package/src/lib/server/session-reset-policy.ts +311 -0
  159. package/src/lib/server/session-run-manager.ts +33 -82
  160. package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
  161. package/src/lib/server/session-tools/calendar.ts +366 -0
  162. package/src/lib/server/session-tools/canvas.ts +1 -1
  163. package/src/lib/server/session-tools/chatroom.ts +4 -2
  164. package/src/lib/server/session-tools/connector.ts +114 -10
  165. package/src/lib/server/session-tools/context.ts +21 -5
  166. package/src/lib/server/session-tools/crawl.ts +447 -0
  167. package/src/lib/server/session-tools/crud.ts +74 -28
  168. package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
  169. package/src/lib/server/session-tools/delegate.ts +497 -24
  170. package/src/lib/server/session-tools/discovery.ts +24 -6
  171. package/src/lib/server/session-tools/document.ts +283 -0
  172. package/src/lib/server/session-tools/edit_file.ts +4 -2
  173. package/src/lib/server/session-tools/email.ts +320 -0
  174. package/src/lib/server/session-tools/extract.ts +137 -0
  175. package/src/lib/server/session-tools/file-normalize.test.ts +93 -0
  176. package/src/lib/server/session-tools/file-send.test.ts +84 -1
  177. package/src/lib/server/session-tools/file.ts +241 -25
  178. package/src/lib/server/session-tools/git.ts +1 -1
  179. package/src/lib/server/session-tools/http.ts +1 -1
  180. package/src/lib/server/session-tools/human-loop.ts +227 -0
  181. package/src/lib/server/session-tools/image-gen.ts +380 -0
  182. package/src/lib/server/session-tools/index.ts +130 -50
  183. package/src/lib/server/session-tools/mailbox.ts +276 -0
  184. package/src/lib/server/session-tools/memory.ts +172 -3
  185. package/src/lib/server/session-tools/monitor.ts +151 -8
  186. package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
  187. package/src/lib/server/session-tools/openclaw-nodes.ts +1 -1
  188. package/src/lib/server/session-tools/openclaw-workspace.ts +1 -1
  189. package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
  190. package/src/lib/server/session-tools/platform.ts +148 -7
  191. package/src/lib/server/session-tools/plugin-creator.ts +89 -26
  192. package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
  193. package/src/lib/server/session-tools/replicate.ts +301 -0
  194. package/src/lib/server/session-tools/sample-ui.ts +1 -1
  195. package/src/lib/server/session-tools/sandbox.ts +4 -2
  196. package/src/lib/server/session-tools/schedule.ts +24 -12
  197. package/src/lib/server/session-tools/session-info.ts +43 -7
  198. package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
  199. package/src/lib/server/session-tools/shell.ts +5 -2
  200. package/src/lib/server/session-tools/subagent.ts +194 -28
  201. package/src/lib/server/session-tools/table.ts +587 -0
  202. package/src/lib/server/session-tools/wallet.ts +42 -12
  203. package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
  204. package/src/lib/server/session-tools/web.ts +926 -91
  205. package/src/lib/server/storage.ts +255 -16
  206. package/src/lib/server/stream-agent-chat.ts +116 -268
  207. package/src/lib/server/structured-extract.test.ts +72 -0
  208. package/src/lib/server/structured-extract.ts +373 -0
  209. package/src/lib/server/task-mention.test.ts +16 -2
  210. package/src/lib/server/task-mention.ts +61 -10
  211. package/src/lib/server/tool-aliases.ts +66 -18
  212. package/src/lib/server/tool-capability-policy.test.ts +9 -9
  213. package/src/lib/server/tool-capability-policy.ts +38 -27
  214. package/src/lib/server/tool-retry.ts +2 -0
  215. package/src/lib/server/watch-jobs.test.ts +173 -0
  216. package/src/lib/server/watch-jobs.ts +532 -0
  217. package/src/lib/server/ws-hub.ts +5 -3
  218. package/src/lib/tool-definitions.ts +4 -0
  219. package/src/lib/validation/schemas.test.ts +26 -0
  220. package/src/lib/validation/schemas.ts +10 -1
  221. package/src/lib/ws-client.ts +14 -12
  222. package/src/proxy.ts +5 -5
  223. package/src/stores/use-app-store.ts +5 -11
  224. package/src/stores/use-chat-store.ts +38 -9
  225. package/src/types/index.ts +352 -47
  226. package/src/app/api/sessions/[id]/main-loop/route.ts +0 -94
  227. package/src/components/sessions/new-session-sheet.tsx +0 -253
  228. package/src/lib/server/main-session.ts +0 -24
  229. package/src/lib/server/session-run-manager.test.ts +0 -23
  230. /package/src/app/api/{sessions → chats}/[id]/clear/route.ts +0 -0
  231. /package/src/app/api/{sessions → chats}/[id]/deploy/route.ts +0 -0
  232. /package/src/app/api/{sessions → chats}/[id]/devserver/route.ts +0 -0
  233. /package/src/app/api/{sessions → chats}/[id]/edit-resend/route.ts +0 -0
  234. /package/src/app/api/{sessions → chats}/[id]/fork/route.ts +0 -0
  235. /package/src/app/api/{sessions → chats}/[id]/mailbox/route.ts +0 -0
  236. /package/src/app/api/{sessions → chats}/[id]/retry/route.ts +0 -0
  237. /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { genId } from '@/lib/id'
3
- import { loadTasks, saveTasks, loadSettings, loadAgents, logActivity } from '@/lib/server/storage'
3
+ import { deleteTask, loadAgents, loadSettings, loadTasks, logActivity, upsertTask } from '@/lib/server/storage'
4
4
  import { TaskCreateSchema, formatZodError } from '@/lib/validation/schemas'
5
5
  import { z } from 'zod'
6
6
  import { enqueueTask, recoverStalledRunningTasks, validateCompletedTasksQueue } from '@/lib/server/queue'
@@ -13,6 +13,7 @@ import { resolveTaskAgentFromDescription } from '@/lib/server/task-mention'
13
13
  import { validateDag } from '@/lib/server/dag-validation'
14
14
  import { getPluginManager } from '@/lib/server/plugins'
15
15
  import { normalizeTaskQualityGate } from '@/lib/server/task-quality-gate'
16
+ import '@/lib/server/builtin-plugins'
16
17
 
17
18
  export async function GET(req: Request) {
18
19
  // Keep completed queue integrity even if daemon is not running.
@@ -49,7 +50,6 @@ export async function DELETE(req: Request) {
49
50
  (filter === 'done' && (task.status === 'completed' || task.status === 'failed')) ||
50
51
  (!filter && task.status === 'archived')
51
52
 
52
- const { deleteTask } = await import('@/lib/server/storage')
53
53
  for (const [id, task] of Object.entries(tasks)) {
54
54
  if (shouldRemove(task as { status: string; sourceType?: string })) {
55
55
  deleteTask(id)
@@ -169,7 +169,12 @@ export async function POST(req: Request) {
169
169
  if (validation.ok) {
170
170
  tasks[id].completedAt = Date.now()
171
171
  tasks[id].error = null
172
- getPluginManager().runHook('onTaskComplete', { taskId: id, result: tasks[id].result })
172
+ const agentPlugins = resolvedAgentId ? (loadAgents()[resolvedAgentId]?.plugins || []) : []
173
+ getPluginManager().runHook(
174
+ 'onTaskComplete',
175
+ { taskId: id, result: tasks[id].result },
176
+ { enabledIds: agentPlugins },
177
+ )
173
178
  } else {
174
179
  tasks[id].status = 'failed'
175
180
  tasks[id].completedAt = null
@@ -177,7 +182,7 @@ export async function POST(req: Request) {
177
182
  }
178
183
  }
179
184
 
180
- saveTasks(tasks)
185
+ upsertTask(id, tasks[id])
181
186
  logActivity({ entityType: 'task', entityId: id, action: 'created', actor: 'user', summary: `Task created: "${tasks[id].title}"` })
182
187
  pushMainLoopEventToMainSessions({
183
188
  type: 'task_created',
@@ -50,6 +50,7 @@ export async function GET(req: Request) {
50
50
  let totalCost = 0
51
51
  const byAgent: Record<string, { name: string; cost: number; tokens: number; count: number }> = {}
52
52
  const byProvider: Record<string, { tokens: number; cost: number }> = {}
53
+ const byPlugin: Record<string, { definitionTokens: number; invocationTokens: number; invocations: number; estimatedCost: number }> = {}
53
54
  const bucketMap: Record<string, { tokens: number; cost: number }> = {}
54
55
 
55
56
  for (const r of records) {
@@ -75,6 +76,26 @@ export async function GET(req: Request) {
75
76
  byAgent[agentId].tokens += tokens
76
77
  byAgent[agentId].count += 1
77
78
 
79
+ // by plugin — definition costs (context overhead per LLM call)
80
+ if (Array.isArray(r.pluginDefinitionCosts)) {
81
+ for (const dc of r.pluginDefinitionCosts) {
82
+ if (!dc.pluginId) continue
83
+ if (!byPlugin[dc.pluginId]) byPlugin[dc.pluginId] = { definitionTokens: 0, invocationTokens: 0, invocations: 0, estimatedCost: 0 }
84
+ byPlugin[dc.pluginId].definitionTokens += dc.estimatedTokens || 0
85
+ }
86
+ }
87
+
88
+ // by plugin — invocation costs (actual tool calls)
89
+ if (Array.isArray(r.pluginInvocations)) {
90
+ for (const inv of r.pluginInvocations) {
91
+ if (!inv.pluginId) continue
92
+ if (!byPlugin[inv.pluginId]) byPlugin[inv.pluginId] = { definitionTokens: 0, invocationTokens: 0, invocations: 0, estimatedCost: 0 }
93
+ const p = byPlugin[inv.pluginId]
94
+ p.invocationTokens += (inv.inputTokens || 0) + (inv.outputTokens || 0)
95
+ p.invocations += 1
96
+ }
97
+ }
98
+
78
99
  // time series bucketing
79
100
  const bk = bucketKey(r.timestamp || now, range)
80
101
  if (!bucketMap[bk]) bucketMap[bk] = { tokens: 0, cost: 0 }
@@ -82,6 +103,14 @@ export async function GET(req: Request) {
82
103
  bucketMap[bk].cost += cost
83
104
  }
84
105
 
106
+ // Estimate per-plugin cost using the average input token rate from total usage
107
+ if (totalTokens > 0 && totalCost > 0) {
108
+ const avgCostPerToken = totalCost / totalTokens
109
+ for (const p of Object.values(byPlugin)) {
110
+ p.estimatedCost = Math.round((p.definitionTokens + p.invocationTokens) * avgCostPerToken * 10000) / 10000
111
+ }
112
+ }
113
+
85
114
  // Sort time series
86
115
  const timeSeries = Object.entries(bucketMap)
87
116
  .sort(([a], [b]) => a.localeCompare(b))
@@ -144,6 +173,7 @@ export async function GET(req: Request) {
144
173
  totalCost: Math.round(totalCost * 10000) / 10000,
145
174
  byAgent,
146
175
  byProvider,
176
+ byPlugin,
147
177
  timeSeries,
148
178
  providerHealth,
149
179
  })
@@ -8,6 +8,7 @@ import { enqueueSystemEvent } from '@/lib/server/system-events'
8
8
  import { requestHeartbeatNow } from '@/lib/server/heartbeat-wake'
9
9
  import { mutateItem, deleteItem, notFound, type CollectionOps } from '@/lib/server/collection-helpers'
10
10
  import type { WebhookRetryEntry } from '@/types'
11
+ import { triggerWebhookWatchJobs } from '@/lib/server/watch-jobs'
11
12
 
12
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
14
  const ops: CollectionOps<any> = { load: loadWebhooks, save: saveWebhooks }
@@ -126,6 +127,12 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
126
127
  })
127
128
  }
128
129
 
130
+ triggerWebhookWatchJobs({
131
+ webhookId: id,
132
+ event: incomingEvent,
133
+ payloadPreview: rawBody,
134
+ })
135
+
129
136
  const agents = loadAgents()
130
137
  const agent = webhook.agentId ? agents[webhook.agentId] : null
131
138
  if (!agent) {
@@ -165,7 +172,7 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
165
172
  messages: [],
166
173
  createdAt: now,
167
174
  lastActiveAt: now,
168
- sessionType: 'orchestrated',
175
+ sessionType: 'human',
169
176
  agentId: agent.id,
170
177
  parentSessionId: null,
171
178
  tools: agent.tools || [],
package/src/app/page.tsx CHANGED
@@ -158,8 +158,15 @@ export default function Home() {
158
158
  const checkAuth = useCallback(async () => {
159
159
  const key = getStoredAccessKey()
160
160
  if (!key) {
161
- setAuthChecked(true)
162
- setAuthenticated(false)
161
+ try {
162
+ const res = await fetchWithTimeout('/api/auth', {}, AUTH_CHECK_TIMEOUT_MS)
163
+ const data = await res.json().catch(() => ({}))
164
+ setAuthenticated(data?.authenticated === true)
165
+ } catch {
166
+ setAuthenticated(false)
167
+ } finally {
168
+ setAuthChecked(true)
169
+ }
163
170
  return
164
171
  }
165
172
 
package/src/cli/index.js CHANGED
@@ -120,6 +120,9 @@ const COMMAND_GROUPS = [
120
120
  defaultBody: { action: 'repair' },
121
121
  }),
122
122
  cmd('health', 'GET', '/connectors/:id/health', 'Get connector health status'),
123
+ cmd('doctor', 'GET', '/connectors/:id/doctor', 'Get connector doctor diagnostics'),
124
+ cmd('doctor-preview', 'POST', '/connectors/:id/doctor', 'Preview connector doctor diagnostics with temporary overrides', { expectsJsonBody: true }),
125
+ cmd('doctor-draft', 'POST', '/connectors/doctor', 'Preview connector doctor diagnostics before saving a connector', { expectsJsonBody: true }),
123
126
  ],
124
127
  },
125
128
  {
@@ -344,7 +347,10 @@ const COMMAND_GROUPS = [
344
347
  cmd('delete', 'DELETE', '/plugins', 'Delete an external plugin (use --query filename=plugin.js)'),
345
348
  cmd('update', 'PATCH', '/plugins', 'Update a plugin (use --query id=plugin.js or --query all=true)'),
346
349
  cmd('install', 'POST', '/plugins/install', 'Install plugin from URL', { expectsJsonBody: true }),
350
+ cmd('install-deps', 'POST', '/plugins/dependencies', 'Install or refresh plugin workspace dependencies', { expectsJsonBody: true }),
347
351
  cmd('marketplace', 'GET', '/plugins/marketplace', 'Get marketplace catalog'),
352
+ cmd('settings-get', 'GET', '/plugins/settings', 'Get plugin settings (use --query pluginId=plugin_name)'),
353
+ cmd('settings-set', 'PUT', '/plugins/settings', 'Set plugin settings (use --query pluginId=plugin_name and --data JSON)', { expectsJsonBody: true }),
348
354
  cmd('ui', 'GET', '/plugins/ui', 'List plugin UI extensions (use --query type=sidebar|header|chat_actions|connectors)'),
349
355
  ],
350
356
  },
@@ -369,7 +375,7 @@ const COMMAND_GROUPS = [
369
375
  name: 'search',
370
376
  description: 'Global search across app resources',
371
377
  commands: [
372
- cmd('query', 'GET', '/search', 'Search agents/tasks/sessions/schedules/webhooks/skills (use --query q=term)'),
378
+ cmd('query', 'GET', '/search', 'Search agents/tasks/chats/schedules/webhooks/skills (use --query q=term)'),
373
379
  ],
374
380
  },
375
381
  {
@@ -404,56 +410,56 @@ const COMMAND_GROUPS = [
404
410
  ],
405
411
  },
406
412
  {
407
- name: 'sessions',
408
- description: 'Manage chat sessions and runtime controls',
413
+ name: 'chats',
414
+ description: 'Manage agent chats and runtime controls',
409
415
  commands: [
410
- cmd('list', 'GET', '/sessions', 'List sessions'),
411
- cmd('get', 'GET', '/sessions/:id', 'Get session by id', { virtual: true, clientGetRoute: '/sessions' }),
412
- cmd('create', 'POST', '/sessions', 'Create session', { expectsJsonBody: true }),
413
- cmd('update', 'PUT', '/sessions/:id', 'Update session', { expectsJsonBody: true }),
414
- cmd('delete', 'DELETE', '/sessions/:id', 'Delete session'),
415
- cmd('delete-many', 'DELETE', '/sessions', 'Delete multiple sessions (body: {"ids":[...]})', { expectsJsonBody: true }),
416
- cmd('heartbeat-disable-all', 'POST', '/sessions/heartbeat', 'Disable all session heartbeats and cancel queued heartbeat runs', {
416
+ cmd('list', 'GET', '/chats', 'List chats'),
417
+ cmd('get', 'GET', '/chats/:id', 'Get chat by id', { virtual: true, clientGetRoute: '/chats' }),
418
+ cmd('create', 'POST', '/chats', 'Create chat', { expectsJsonBody: true }),
419
+ cmd('update', 'PUT', '/chats/:id', 'Update chat', { expectsJsonBody: true }),
420
+ cmd('delete', 'DELETE', '/chats/:id', 'Delete chat'),
421
+ cmd('delete-many', 'DELETE', '/chats', 'Delete multiple chats (body: {"ids":[...]})', { expectsJsonBody: true }),
422
+ cmd('heartbeat-disable-all', 'POST', '/chats/heartbeat', 'Disable all chat heartbeats and cancel queued heartbeat runs', {
417
423
  expectsJsonBody: true,
418
424
  defaultBody: { action: 'disable_all' },
419
425
  }),
420
- cmd('messages', 'GET', '/sessions/:id/messages', 'Get session messages'),
421
- cmd('messages-update', 'PUT', '/sessions/:id/messages', 'Update session message metadata (e.g. bookmark)', { expectsJsonBody: true }),
422
- cmd('messages-send', 'POST', '/sessions/:id/messages', 'Append a user/system message to a session', { expectsJsonBody: true }),
423
- cmd('messages-delete', 'DELETE', '/sessions/:id/messages', 'Delete a message from a session', { expectsJsonBody: true }),
424
- cmd('fork', 'POST', '/sessions/:id/fork', 'Fork session from a specific message index', { expectsJsonBody: true }),
425
- cmd('edit-resend', 'POST', '/sessions/:id/edit-resend', 'Edit and resend from a specific message index', { expectsJsonBody: true }),
426
- cmd('main-loop', 'GET', '/sessions/:id/main-loop', 'Get main mission loop state'),
427
- cmd('main-loop-action', 'POST', '/sessions/:id/main-loop', 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', {
426
+ cmd('messages', 'GET', '/chats/:id/messages', 'Get chat messages'),
427
+ cmd('messages-update', 'PUT', '/chats/:id/messages', 'Update chat message metadata (e.g. bookmark)', { expectsJsonBody: true }),
428
+ cmd('messages-send', 'POST', '/chats/:id/messages', 'Append a user/system message to a chat', { expectsJsonBody: true }),
429
+ cmd('messages-delete', 'DELETE', '/chats/:id/messages', 'Delete a message from a chat', { expectsJsonBody: true }),
430
+ cmd('fork', 'POST', '/chats/:id/fork', 'Fork chat from a specific message index', { expectsJsonBody: true }),
431
+ cmd('edit-resend', 'POST', '/chats/:id/edit-resend', 'Edit and resend from a specific message index', { expectsJsonBody: true }),
432
+ cmd('main-loop', 'GET', '/chats/:id/main-loop', 'Get main mission loop state'),
433
+ cmd('main-loop-action', 'POST', '/chats/:id/main-loop', 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', {
428
434
  expectsJsonBody: true,
429
435
  }),
430
- cmd('chat', 'POST', '/sessions/:id/chat', 'Send chat message (streaming)', {
436
+ cmd('chat', 'POST', '/chats/:id/chat', 'Send chat message (streaming)', {
431
437
  expectsJsonBody: true,
432
438
  responseType: 'sse',
433
439
  }),
434
- cmd('stop', 'POST', '/sessions/:id/stop', 'Stop session run(s)'),
435
- cmd('clear', 'POST', '/sessions/:id/clear', 'Clear session messages'),
436
- cmd('browser-status', 'GET', '/sessions/:id/browser', 'Check browser status'),
437
- cmd('browser-close', 'DELETE', '/sessions/:id/browser', 'Close browser session'),
438
- cmd('mailbox', 'GET', '/sessions/:id/mailbox', 'List session mailbox envelopes'),
439
- cmd('mailbox-action', 'POST', '/sessions/:id/mailbox', 'Send/ack/clear mailbox envelopes', { expectsJsonBody: true }),
440
- cmd('retry', 'POST', '/sessions/:id/retry', 'Retry last assistant message'),
441
- cmd('deploy', 'POST', '/sessions/:id/deploy', 'Deploy current session branch', { expectsJsonBody: true }),
442
- cmd('devserver', 'POST', '/sessions/:id/devserver', 'Dev server action via JSON body', { expectsJsonBody: true }),
443
- cmd('devserver-start', 'POST', '/sessions/:id/devserver', 'Start session dev server', {
440
+ cmd('stop', 'POST', '/chats/:id/stop', 'Stop chat run(s)'),
441
+ cmd('clear', 'POST', '/chats/:id/clear', 'Clear chat messages'),
442
+ cmd('browser-status', 'GET', '/chats/:id/browser', 'Check browser status'),
443
+ cmd('browser-close', 'DELETE', '/chats/:id/browser', 'Close browser'),
444
+ cmd('mailbox', 'GET', '/chats/:id/mailbox', 'List chat mailbox envelopes'),
445
+ cmd('mailbox-action', 'POST', '/chats/:id/mailbox', 'Send/ack/clear mailbox envelopes', { expectsJsonBody: true }),
446
+ cmd('retry', 'POST', '/chats/:id/retry', 'Retry last assistant message'),
447
+ cmd('deploy', 'POST', '/chats/:id/deploy', 'Deploy current chat branch', { expectsJsonBody: true }),
448
+ cmd('devserver', 'POST', '/chats/:id/devserver', 'Dev server action via JSON body', { expectsJsonBody: true }),
449
+ cmd('devserver-start', 'POST', '/chats/:id/devserver', 'Start chat dev server', {
444
450
  expectsJsonBody: true,
445
451
  defaultBody: { action: 'start' },
446
452
  }),
447
- cmd('devserver-stop', 'POST', '/sessions/:id/devserver', 'Stop session dev server', {
453
+ cmd('devserver-stop', 'POST', '/chats/:id/devserver', 'Stop chat dev server', {
448
454
  expectsJsonBody: true,
449
455
  defaultBody: { action: 'stop' },
450
456
  }),
451
- cmd('devserver-status', 'POST', '/sessions/:id/devserver', 'Check session dev server status', {
457
+ cmd('devserver-status', 'POST', '/chats/:id/devserver', 'Check chat dev server status', {
452
458
  expectsJsonBody: true,
453
459
  defaultBody: { action: 'status' },
454
460
  }),
455
- cmd('checkpoints', 'GET', '/sessions/:id/checkpoints', 'List checkpoint history for a session'),
456
- cmd('restore', 'POST', '/sessions/:id/restore', 'Restore session to a previous checkpoint', { expectsJsonBody: true }),
461
+ cmd('checkpoints', 'GET', '/chats/:id/checkpoints', 'List checkpoint history for a chat'),
462
+ cmd('restore', 'POST', '/chats/:id/restore', 'Restore chat to a previous checkpoint', { expectsJsonBody: true }),
457
463
  ],
458
464
  },
459
465
  {
package/src/cli/index.ts CHANGED
@@ -17,7 +17,6 @@ interface CliContext {
17
17
 
18
18
  interface SetupAuthStatus {
19
19
  firstTime?: boolean
20
- key?: string
21
20
  }
22
21
 
23
22
  interface SetupProviderCheckResponse {
@@ -208,19 +207,13 @@ async function resolveSetupAccessKey(ctx: CliContext): Promise<{
208
207
  }
209
208
 
210
209
  const status = await apiRequestWithAccessKey<SetupAuthStatus>(ctx, 'GET', '/auth', undefined)
211
- const discoveredKey = typeof status?.key === 'string' ? status.key.trim() : ''
212
210
  const firstTime = status?.firstTime === true
213
211
 
214
- if (!firstTime || !discoveredKey) {
215
- throw new Error('No access key provided. Pass --key (or SWARMCLAW_ACCESS_KEY), or run setup on a fresh first-time instance.')
212
+ if (firstTime) {
213
+ throw new Error('No access key provided. Read the generated key from the launch terminal or .env.local, then pass --key (or SWARMCLAW_ACCESS_KEY).')
216
214
  }
217
215
 
218
- await apiRequestWithAccessKey(ctx, 'POST', '/auth', discoveredKey, { key: discoveredKey })
219
- return {
220
- accessKey: discoveredKey,
221
- firstTime: true,
222
- autoDiscovered: true,
223
- }
216
+ throw new Error('No access key provided. Pass --key (or SWARMCLAW_ACCESS_KEY).')
224
217
  }
225
218
 
226
219
  function printResult(value: unknown, rawOutput: boolean): void {
@@ -657,27 +650,28 @@ export function buildProgram(): Command {
657
650
  await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/runs/${encodeURIComponent(id)}`))
658
651
  })
659
652
 
660
- const sessions = program.command('sessions').description('Manage sessions')
653
+ const chats = program.command('chats').description('Manage chats')
654
+ program.command('sessions').description('Manage chats (alias)').action(() => chats.help())
661
655
 
662
- sessions
656
+ chats
663
657
  .command('list')
664
- .description('List sessions')
658
+ .description('List chats')
665
659
  .action(async function () {
666
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', '/sessions'))
660
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', '/chats'))
667
661
  })
668
662
 
669
- sessions
663
+ chats
670
664
  .command('get')
671
- .description('Get session by id')
672
- .argument('<id>', 'Session id')
665
+ .description('Get chat by id')
666
+ .argument('<id>', 'Chat id')
673
667
  .action(async function (id: string) {
674
- await runWithHandler(this as Command, (ctx) => resolveByIdFromCollection(ctx, '/sessions', id))
668
+ await runWithHandler(this as Command, (ctx) => resolveByIdFromCollection(ctx, '/chats', id))
675
669
  })
676
670
 
677
- sessions
671
+ chats
678
672
  .command('create')
679
- .description('Create session')
680
- .option('--name <name>', 'Session name', 'New Session')
673
+ .description('Create chat')
674
+ .option('--name <name>', 'Chat name', 'New Chat')
681
675
  .option('--user <user>', 'User name')
682
676
  .option('--cwd <cwd>', 'Working directory')
683
677
  .option('--provider <provider>', 'Provider id')
@@ -706,7 +700,7 @@ export function buildProgram(): Command {
706
700
  if (opts.heartbeatIntervalSec && (!Number.isFinite(heartbeatIntervalSec) || heartbeatIntervalSec! < 0)) {
707
701
  throw new Error(`Invalid --heartbeat-interval-sec value: ${opts.heartbeatIntervalSec}`)
708
702
  }
709
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', '/sessions', compactObject({
703
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', '/chats', compactObject({
710
704
  name: opts.name,
711
705
  user: opts.user,
712
706
  cwd: opts.cwd,
@@ -720,14 +714,14 @@ export function buildProgram(): Command {
720
714
  })))
721
715
  })
722
716
 
723
- sessions
717
+ chats
724
718
  .command('update')
725
- .description('Update session')
726
- .argument('<id>', 'Session id')
727
- .option('--name <name>', 'Session name')
719
+ .description('Update chat')
720
+ .argument('<id>', 'Chat id')
721
+ .option('--name <name>', 'Chat name')
728
722
  .option('--cwd <cwd>', 'Working directory')
729
723
  .option('--agent-id <agentId>', 'Agent id')
730
- .option('--tools <json>', 'Tools JSON array, e.g. ["shell","memory"]')
724
+ .option('--plugins <json>', 'Plugins JSON array, e.g. ["shell","memory"]')
731
725
  .option('--heartbeat-enabled <heartbeatEnabled>', 'Heartbeat enabled (true|false)')
732
726
  .option('--heartbeat-interval-sec <heartbeatIntervalSec>', 'Heartbeat interval seconds')
733
727
  .action(async function (
@@ -736,7 +730,7 @@ export function buildProgram(): Command {
736
730
  name?: string
737
731
  cwd?: string
738
732
  agentId?: string
739
- tools?: string
733
+ plugins?: string
740
734
  heartbeatEnabled?: string
741
735
  heartbeatIntervalSec?: string
742
736
  },
@@ -748,40 +742,40 @@ export function buildProgram(): Command {
748
742
  if (opts.heartbeatIntervalSec && (!Number.isFinite(heartbeatIntervalSec) || heartbeatIntervalSec! < 0)) {
749
743
  throw new Error(`Invalid --heartbeat-interval-sec value: ${opts.heartbeatIntervalSec}`)
750
744
  }
751
- const tools = parseJsonValue(opts.tools, '--tools')
752
- if (tools !== undefined && !Array.isArray(tools)) {
753
- throw new Error('--tools must be a JSON array')
745
+ const plugins = parseJsonValue(opts.plugins, '--plugins')
746
+ if (plugins !== undefined && !Array.isArray(plugins)) {
747
+ throw new Error('--plugins must be a JSON array')
754
748
  }
755
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'PUT', `/sessions/${encodeURIComponent(id)}`, compactObject({
749
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'PUT', `/chats/${encodeURIComponent(id)}`, compactObject({
756
750
  name: opts.name,
757
751
  cwd: opts.cwd,
758
752
  agentId: opts.agentId,
759
- tools,
753
+ plugins,
760
754
  heartbeatEnabled: typeof opts.heartbeatEnabled === 'string' ? heartbeatEnabled : undefined,
761
755
  heartbeatIntervalSec,
762
756
  })))
763
757
  })
764
758
 
765
- sessions
759
+ chats
766
760
  .command('delete')
767
- .description('Delete session')
768
- .argument('<id>', 'Session id')
761
+ .description('Delete chat')
762
+ .argument('<id>', 'Chat id')
769
763
  .action(async function (id: string) {
770
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'DELETE', `/sessions/${encodeURIComponent(id)}`))
764
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'DELETE', `/chats/${encodeURIComponent(id)}`))
771
765
  })
772
766
 
773
- sessions
767
+ chats
774
768
  .command('history')
775
- .description('Get session message history')
776
- .argument('<id>', 'Session id')
769
+ .description('Get chat message history')
770
+ .argument('<id>', 'Chat id')
777
771
  .action(async function (id: string) {
778
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/sessions/${encodeURIComponent(id)}/messages`))
772
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/chats/${encodeURIComponent(id)}/messages`))
779
773
  })
780
774
 
781
- sessions
775
+ chats
782
776
  .command('mailbox')
783
- .description('List session mailbox envelopes')
784
- .argument('<id>', 'Session id')
777
+ .description('List chat mailbox envelopes')
778
+ .argument('<id>', 'Chat id')
785
779
  .option('--limit <limit>', 'Max envelopes to return (default: 50)')
786
780
  .option('--include-acked', 'Include acknowledged envelopes')
787
781
  .action(async function (
@@ -799,16 +793,16 @@ export function buildProgram(): Command {
799
793
  const params = new URLSearchParams()
800
794
  if (typeof limit === 'number') params.set('limit', String(limit))
801
795
  if (opts.includeAcked) params.set('includeAcked', '1')
802
- return apiRequest(ctx, 'GET', `/sessions/${encodeURIComponent(id)}/mailbox`, undefined, params)
796
+ return apiRequest(ctx, 'GET', `/chats/${encodeURIComponent(id)}/mailbox`, undefined, params)
803
797
  })
804
798
  })
805
799
 
806
- sessions
800
+ chats
807
801
  .command('stop')
808
- .description('Stop running work for a session')
809
- .argument('<id>', 'Session id')
802
+ .description('Stop running work for a chat')
803
+ .argument('<id>', 'Chat id')
810
804
  .action(async function (id: string) {
811
- await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', `/sessions/${encodeURIComponent(id)}/stop`))
805
+ await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', `/chats/${encodeURIComponent(id)}/stop`))
812
806
  })
813
807
 
814
808
  const memory = program.command('memory').description('Manage memory')
package/src/cli/spec.js CHANGED
@@ -228,6 +228,8 @@ const COMMAND_GROUPS = {
228
228
  update: { description: 'Enable/disable plugin (body: {"filename":"x.js","enabled":true})', method: 'POST', path: '/plugins' },
229
229
  marketplace: { description: 'Get plugin marketplace registry', method: 'GET', path: '/plugins/marketplace' },
230
230
  install: { description: 'Install plugin by URL', method: 'POST', path: '/plugins/install' },
231
+ 'settings-get': { description: 'Read plugin settings (supports --query pluginId=...)', method: 'GET', path: '/plugins/settings' },
232
+ 'settings-set': { description: 'Write plugin settings (supports --query pluginId=... and --data JSON)', method: 'PUT', path: '/plugins/settings' },
231
233
  },
232
234
  },
233
235
  providers: {
@@ -249,7 +251,7 @@ const COMMAND_GROUPS = {
249
251
  search: {
250
252
  description: 'Global search across app resources',
251
253
  commands: {
252
- query: { description: 'Search agents/tasks/sessions/schedules/webhooks/skills (supports --query q=term)', method: 'GET', path: '/search' },
254
+ query: { description: 'Search agents/tasks/chats/schedules/webhooks/skills (supports --query q=term)', method: 'GET', path: '/search' },
253
255
  },
254
256
  },
255
257
  schedules: {
@@ -273,33 +275,33 @@ const COMMAND_GROUPS = {
273
275
  delete: { description: 'Delete secret', method: 'DELETE', path: '/secrets/:id', params: ['id'] },
274
276
  },
275
277
  },
276
- sessions: {
277
- description: 'Interactive chat sessions',
278
+ chats: {
279
+ description: 'Agent chats',
278
280
  commands: {
279
- list: { description: 'List sessions', method: 'GET', path: '/sessions' },
280
- create: { description: 'Create session', method: 'POST', path: '/sessions' },
281
- get: { description: 'Get session by id (from list)', virtualGet: true, collectionPath: '/sessions', params: ['id'] },
282
- update: { description: 'Update session fields', method: 'PUT', path: '/sessions/:id', params: ['id'] },
283
- delete: { description: 'Delete one session', method: 'DELETE', path: '/sessions/:id', params: ['id'] },
284
- 'delete-many': { description: 'Delete multiple sessions (body: {"ids":[...]})', method: 'DELETE', path: '/sessions' },
285
- 'heartbeat-disable-all': { description: 'Disable all session heartbeats and cancel queued heartbeat runs', method: 'POST', path: '/sessions/heartbeat' },
286
- messages: { description: 'Get session message history', method: 'GET', path: '/sessions/:id/messages', params: ['id'] },
287
- 'messages-update': { description: 'Update session message metadata (e.g. bookmark)', method: 'PUT', path: '/sessions/:id/messages', params: ['id'] },
288
- 'messages-send': { description: 'Append a user/system message to a session', method: 'POST', path: '/sessions/:id/messages', params: ['id'] },
289
- 'messages-delete': { description: 'Delete a message from a session', method: 'DELETE', path: '/sessions/:id/messages', params: ['id'] },
290
- fork: { description: 'Fork session from a specific message index', method: 'POST', path: '/sessions/:id/fork', params: ['id'] },
291
- 'edit-resend': { description: 'Edit and resend from a specific message index', method: 'POST', path: '/sessions/:id/edit-resend', params: ['id'] },
292
- 'main-loop': { description: 'Get main mission loop state for a session', method: 'GET', path: '/sessions/:id/main-loop', params: ['id'] },
293
- 'main-loop-action': { description: 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', method: 'POST', path: '/sessions/:id/main-loop', params: ['id'] },
294
- chat: { description: 'Send chat message (SSE stream)', method: 'POST', path: '/sessions/:id/chat', params: ['id'], stream: true, waitable: true },
295
- stop: { description: 'Cancel active/running session work', method: 'POST', path: '/sessions/:id/stop', params: ['id'] },
296
- clear: { description: 'Clear session history', method: 'POST', path: '/sessions/:id/clear', params: ['id'] },
297
- mailbox: { description: 'List mailbox envelopes for a session', method: 'GET', path: '/sessions/:id/mailbox', params: ['id'] },
298
- 'mailbox-action': { description: 'Send/ack/clear mailbox envelopes', method: 'POST', path: '/sessions/:id/mailbox', params: ['id'] },
299
- deploy: { description: 'Deploy session workspace git changes', method: 'POST', path: '/sessions/:id/deploy', params: ['id'] },
300
- devserver: { description: 'Start/stop/status dev server (body: {"action":"start|stop|status"})', method: 'POST', path: '/sessions/:id/devserver', params: ['id'] },
301
- browser: { description: 'Check browser runtime for session', method: 'GET', path: '/sessions/:id/browser', params: ['id'] },
302
- 'browser-clear': { description: 'Close browser runtime for session', method: 'DELETE', path: '/sessions/:id/browser', params: ['id'] },
281
+ list: { description: 'List chats', method: 'GET', path: '/chats' },
282
+ create: { description: 'Create chat', method: 'POST', path: '/chats' },
283
+ get: { description: 'Get chat by id (from list)', virtualGet: true, collectionPath: '/chats', params: ['id'] },
284
+ update: { description: 'Update chat fields', method: 'PUT', path: '/chats/:id', params: ['id'] },
285
+ delete: { description: 'Delete one chat', method: 'DELETE', path: '/chats/:id', params: ['id'] },
286
+ 'delete-many': { description: 'Delete multiple chats (body: {"ids":[...]})', method: 'DELETE', path: '/chats' },
287
+ 'heartbeat-disable-all': { description: 'Disable all chat heartbeats and cancel queued heartbeat runs', method: 'POST', path: '/chats/heartbeat' },
288
+ messages: { description: 'Get chat message history', method: 'GET', path: '/chats/:id/messages', params: ['id'] },
289
+ 'messages-update': { description: 'Update chat message metadata (e.g. bookmark)', method: 'PUT', path: '/chats/:id/messages', params: ['id'] },
290
+ 'messages-send': { description: 'Append a user/system message to a chat', method: 'POST', path: '/chats/:id/messages', params: ['id'] },
291
+ 'messages-delete': { description: 'Delete a message from a chat', method: 'DELETE', path: '/chats/:id/messages', params: ['id'] },
292
+ fork: { description: 'Fork chat from a specific message index', method: 'POST', path: '/chats/:id/fork', params: ['id'] },
293
+ 'edit-resend': { description: 'Edit and resend from a specific message index', method: 'POST', path: '/chats/:id/edit-resend', params: ['id'] },
294
+ 'main-loop': { description: 'Get main mission loop state for a chat', method: 'GET', path: '/chats/:id/main-loop', params: ['id'] },
295
+ 'main-loop-action': { description: 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', method: 'POST', path: '/chats/:id/main-loop', params: ['id'] },
296
+ chat: { description: 'Send chat message (SSE stream)', method: 'POST', path: '/chats/:id/chat', params: ['id'], stream: true, waitable: true },
297
+ stop: { description: 'Cancel active/running chat work', method: 'POST', path: '/chats/:id/stop', params: ['id'] },
298
+ clear: { description: 'Clear chat history', method: 'POST', path: '/chats/:id/clear', params: ['id'] },
299
+ mailbox: { description: 'List mailbox envelopes for a chat', method: 'GET', path: '/chats/:id/mailbox', params: ['id'] },
300
+ 'mailbox-action': { description: 'Send/ack/clear mailbox envelopes', method: 'POST', path: '/chats/:id/mailbox', params: ['id'] },
301
+ deploy: { description: 'Deploy chat workspace git changes', method: 'POST', path: '/chats/:id/deploy', params: ['id'] },
302
+ devserver: { description: 'Start/stop/status dev server (body: {"action":"start|stop|status"})', method: 'POST', path: '/chats/:id/devserver', params: ['id'] },
303
+ browser: { description: 'Check browser runtime for chat', method: 'GET', path: '/chats/:id/browser', params: ['id'] },
304
+ 'browser-clear': { description: 'Close browser runtime for chat', method: 'DELETE', path: '/chats/:id/browser', params: ['id'] },
303
305
  },
304
306
  },
305
307
  settings: {