@swarmclawai/swarmclaw 0.7.2 → 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 (197) hide show
  1. package/README.md +81 -22
  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 +36 -7
  5. package/src/app/api/agents/route.ts +12 -1
  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/chats/[id]/browser/route.ts +5 -1
  9. package/src/app/api/chats/[id]/chat/route.ts +7 -3
  10. package/src/app/api/chats/[id]/main-loop/route.ts +7 -88
  11. package/src/app/api/chats/[id]/messages/route.ts +19 -13
  12. package/src/app/api/chats/[id]/route.ts +18 -0
  13. package/src/app/api/chats/[id]/stop/route.ts +6 -1
  14. package/src/app/api/chats/route.ts +16 -0
  15. package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
  16. package/src/app/api/connectors/doctor/route.ts +13 -0
  17. package/src/app/api/files/open/route.ts +16 -14
  18. package/src/app/api/memory/maintenance/route.ts +11 -1
  19. package/src/app/api/openclaw/agent-files/route.ts +27 -4
  20. package/src/app/api/openclaw/skills/route.ts +11 -3
  21. package/src/app/api/plugins/dependencies/route.ts +24 -0
  22. package/src/app/api/plugins/install/route.ts +15 -92
  23. package/src/app/api/plugins/route.ts +3 -26
  24. package/src/app/api/plugins/settings/route.ts +17 -12
  25. package/src/app/api/plugins/ui/route.ts +1 -0
  26. package/src/app/api/settings/route.ts +49 -7
  27. package/src/app/api/tasks/[id]/route.ts +15 -6
  28. package/src/app/api/tasks/bulk/route.ts +2 -2
  29. package/src/app/api/tasks/route.ts +9 -4
  30. package/src/app/api/webhooks/[id]/route.ts +8 -1
  31. package/src/app/page.tsx +9 -2
  32. package/src/cli/index.js +4 -0
  33. package/src/cli/index.ts +3 -10
  34. package/src/components/agents/agent-card.tsx +15 -12
  35. package/src/components/agents/agent-chat-list.tsx +101 -1
  36. package/src/components/agents/agent-list.tsx +46 -9
  37. package/src/components/agents/agent-sheet.tsx +207 -16
  38. package/src/components/agents/inspector-panel.tsx +108 -48
  39. package/src/components/auth/access-key-gate.tsx +36 -97
  40. package/src/components/chat/chat-area.tsx +29 -13
  41. package/src/components/chat/chat-card.tsx +4 -20
  42. package/src/components/chat/chat-header.tsx +255 -353
  43. package/src/components/chat/chat-list.tsx +7 -9
  44. package/src/components/chat/checkpoint-timeline.tsx +1 -1
  45. package/src/components/chat/message-list.tsx +3 -1
  46. package/src/components/chatrooms/chatroom-view.tsx +347 -205
  47. package/src/components/connectors/connector-list.tsx +265 -127
  48. package/src/components/connectors/connector-sheet.tsx +217 -0
  49. package/src/components/home/home-view.tsx +128 -4
  50. package/src/components/layout/app-layout.tsx +383 -194
  51. package/src/components/layout/mobile-header.tsx +26 -8
  52. package/src/components/plugins/plugin-list.tsx +15 -3
  53. package/src/components/plugins/plugin-sheet.tsx +118 -9
  54. package/src/components/projects/project-detail.tsx +183 -0
  55. package/src/components/shared/agent-picker-list.tsx +2 -2
  56. package/src/components/shared/command-palette.tsx +111 -24
  57. package/src/components/shared/settings/plugin-manager.tsx +20 -4
  58. package/src/components/shared/settings/section-capability-policy.tsx +105 -0
  59. package/src/components/shared/settings/section-heartbeat.tsx +77 -0
  60. package/src/components/shared/settings/section-orchestrator.tsx +3 -3
  61. package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
  62. package/src/components/shared/settings/section-secrets.tsx +6 -6
  63. package/src/components/shared/settings/section-user-preferences.tsx +1 -1
  64. package/src/components/shared/settings/section-voice.tsx +5 -1
  65. package/src/components/shared/settings/section-web-search.tsx +10 -2
  66. package/src/components/shared/settings/settings-page.tsx +245 -46
  67. package/src/components/tasks/approvals-panel.tsx +205 -18
  68. package/src/components/tasks/task-board.tsx +242 -46
  69. package/src/components/usage/metrics-dashboard.tsx +74 -1
  70. package/src/components/wallets/wallet-panel.tsx +17 -5
  71. package/src/components/webhooks/webhook-sheet.tsx +7 -7
  72. package/src/lib/auth.ts +17 -0
  73. package/src/lib/chat-streaming-state.test.ts +108 -0
  74. package/src/lib/chat-streaming-state.ts +108 -0
  75. package/src/lib/openclaw-agent-id.test.ts +14 -0
  76. package/src/lib/openclaw-agent-id.ts +31 -0
  77. package/src/lib/server/agent-assignment.test.ts +112 -0
  78. package/src/lib/server/agent-assignment.ts +169 -0
  79. package/src/lib/server/approval-connector-notify.test.ts +253 -0
  80. package/src/lib/server/approvals-auto-approve.test.ts +205 -0
  81. package/src/lib/server/approvals.ts +483 -75
  82. package/src/lib/server/autonomy-runtime.test.ts +341 -0
  83. package/src/lib/server/browser-state.test.ts +118 -0
  84. package/src/lib/server/browser-state.ts +123 -0
  85. package/src/lib/server/build-llm.test.ts +36 -0
  86. package/src/lib/server/build-llm.ts +11 -4
  87. package/src/lib/server/builtin-plugins.ts +34 -0
  88. package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
  89. package/src/lib/server/chat-execution-tool-events.test.ts +134 -0
  90. package/src/lib/server/chat-execution.ts +250 -61
  91. package/src/lib/server/chatroom-health.test.ts +26 -0
  92. package/src/lib/server/chatroom-health.ts +2 -3
  93. package/src/lib/server/chatroom-helpers.test.ts +67 -2
  94. package/src/lib/server/chatroom-helpers.ts +45 -5
  95. package/src/lib/server/connectors/discord.ts +175 -11
  96. package/src/lib/server/connectors/doctor.test.ts +80 -0
  97. package/src/lib/server/connectors/doctor.ts +116 -0
  98. package/src/lib/server/connectors/manager.ts +946 -110
  99. package/src/lib/server/connectors/policy.test.ts +222 -0
  100. package/src/lib/server/connectors/policy.ts +452 -0
  101. package/src/lib/server/connectors/slack.ts +188 -9
  102. package/src/lib/server/connectors/telegram.ts +65 -15
  103. package/src/lib/server/connectors/thread-context.test.ts +44 -0
  104. package/src/lib/server/connectors/thread-context.ts +72 -0
  105. package/src/lib/server/connectors/types.ts +41 -11
  106. package/src/lib/server/daemon-state.ts +59 -1
  107. package/src/lib/server/data-dir.ts +13 -0
  108. package/src/lib/server/delegation-jobs.test.ts +140 -0
  109. package/src/lib/server/delegation-jobs.ts +248 -0
  110. package/src/lib/server/document-utils.test.ts +47 -0
  111. package/src/lib/server/document-utils.ts +397 -0
  112. package/src/lib/server/heartbeat-service.ts +13 -39
  113. package/src/lib/server/heartbeat-source.test.ts +22 -0
  114. package/src/lib/server/heartbeat-source.ts +7 -0
  115. package/src/lib/server/identity-continuity.test.ts +77 -0
  116. package/src/lib/server/identity-continuity.ts +127 -0
  117. package/src/lib/server/mailbox-utils.ts +347 -0
  118. package/src/lib/server/main-agent-loop.ts +27 -967
  119. package/src/lib/server/memory-db.ts +4 -6
  120. package/src/lib/server/memory-tiers.ts +40 -0
  121. package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
  122. package/src/lib/server/openclaw-agent-resolver.ts +128 -0
  123. package/src/lib/server/openclaw-exec-config.ts +5 -6
  124. package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
  125. package/src/lib/server/openclaw-skills-normalize.ts +136 -0
  126. package/src/lib/server/openclaw-sync.ts +3 -2
  127. package/src/lib/server/orchestrator-lg.ts +17 -6
  128. package/src/lib/server/orchestrator.ts +2 -2
  129. package/src/lib/server/playwright-proxy.mjs +27 -3
  130. package/src/lib/server/plugins.test.ts +207 -0
  131. package/src/lib/server/plugins.ts +822 -69
  132. package/src/lib/server/provider-health.ts +33 -3
  133. package/src/lib/server/queue.ts +3 -20
  134. package/src/lib/server/scheduler.ts +2 -0
  135. package/src/lib/server/session-archive-memory.test.ts +85 -0
  136. package/src/lib/server/session-archive-memory.ts +230 -0
  137. package/src/lib/server/session-mailbox.ts +8 -18
  138. package/src/lib/server/session-reset-policy.test.ts +99 -0
  139. package/src/lib/server/session-reset-policy.ts +311 -0
  140. package/src/lib/server/session-run-manager.ts +33 -80
  141. package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
  142. package/src/lib/server/session-tools/calendar.ts +2 -12
  143. package/src/lib/server/session-tools/connector.ts +109 -8
  144. package/src/lib/server/session-tools/context.ts +14 -2
  145. package/src/lib/server/session-tools/crawl.ts +447 -0
  146. package/src/lib/server/session-tools/crud.ts +70 -32
  147. package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
  148. package/src/lib/server/session-tools/delegate.ts +406 -20
  149. package/src/lib/server/session-tools/discovery.ts +22 -4
  150. package/src/lib/server/session-tools/document.ts +283 -0
  151. package/src/lib/server/session-tools/email.ts +1 -3
  152. package/src/lib/server/session-tools/extract.ts +137 -0
  153. package/src/lib/server/session-tools/file-normalize.test.ts +93 -0
  154. package/src/lib/server/session-tools/file-send.test.ts +84 -1
  155. package/src/lib/server/session-tools/file.ts +237 -24
  156. package/src/lib/server/session-tools/human-loop.ts +227 -0
  157. package/src/lib/server/session-tools/image-gen.ts +1 -3
  158. package/src/lib/server/session-tools/index.ts +56 -1
  159. package/src/lib/server/session-tools/mailbox.ts +276 -0
  160. package/src/lib/server/session-tools/memory.ts +35 -3
  161. package/src/lib/server/session-tools/monitor.ts +150 -7
  162. package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
  163. package/src/lib/server/session-tools/platform-normalize.test.ts +142 -0
  164. package/src/lib/server/session-tools/platform.ts +142 -4
  165. package/src/lib/server/session-tools/plugin-creator.ts +86 -23
  166. package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
  167. package/src/lib/server/session-tools/replicate.ts +1 -3
  168. package/src/lib/server/session-tools/schedule.ts +20 -10
  169. package/src/lib/server/session-tools/session-info.ts +36 -3
  170. package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
  171. package/src/lib/server/session-tools/subagent.ts +193 -27
  172. package/src/lib/server/session-tools/table.ts +587 -0
  173. package/src/lib/server/session-tools/wallet.ts +13 -10
  174. package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
  175. package/src/lib/server/session-tools/web.ts +896 -100
  176. package/src/lib/server/storage.ts +226 -7
  177. package/src/lib/server/stream-agent-chat.ts +46 -21
  178. package/src/lib/server/structured-extract.test.ts +72 -0
  179. package/src/lib/server/structured-extract.ts +373 -0
  180. package/src/lib/server/task-mention.test.ts +16 -2
  181. package/src/lib/server/task-mention.ts +61 -10
  182. package/src/lib/server/tool-aliases.ts +44 -7
  183. package/src/lib/server/tool-capability-policy.ts +6 -0
  184. package/src/lib/server/tool-retry.ts +2 -0
  185. package/src/lib/server/watch-jobs.test.ts +173 -0
  186. package/src/lib/server/watch-jobs.ts +532 -0
  187. package/src/lib/server/ws-hub.ts +5 -3
  188. package/src/lib/validation/schemas.test.ts +26 -0
  189. package/src/lib/validation/schemas.ts +7 -0
  190. package/src/lib/ws-client.ts +14 -12
  191. package/src/proxy.ts +5 -5
  192. package/src/stores/use-app-store.ts +0 -6
  193. package/src/stores/use-chat-store.ts +31 -2
  194. package/src/types/index.ts +287 -44
  195. package/src/components/chat/new-chat-sheet.tsx +0 -253
  196. package/src/lib/server/main-session.ts +0 -17
  197. package/src/lib/server/session-run-manager.test.ts +0 -26
@@ -54,6 +54,24 @@ function parseDurationToSec(interval: string | number | null | undefined, interv
54
54
  return '' // default
55
55
  }
56
56
 
57
+ function formatIdentityList(value: string[] | null | undefined): string {
58
+ return Array.isArray(value) ? value.join('\n') : ''
59
+ }
60
+
61
+ function parseIdentityList(value: string): string[] {
62
+ const seen = new Set<string>()
63
+ return value
64
+ .split('\n')
65
+ .map((line) => line.replace(/\s+/g, ' ').trim())
66
+ .filter((line) => {
67
+ if (!line) return false
68
+ const key = line.toLowerCase()
69
+ if (seen.has(key)) return false
70
+ seen.add(key)
71
+ return true
72
+ })
73
+ }
74
+
57
75
  export function AgentSheet() {
58
76
  const open = useAppStore((s) => s.agentSheetOpen)
59
77
  const setOpen = useAppStore((s) => s.setAgentSheetOpen)
@@ -92,7 +110,7 @@ export function AgentSheet() {
92
110
  const [model, setModel] = useState('')
93
111
  const [credentialId, setCredentialId] = useState<string | null>(null)
94
112
  const [apiEndpoint, setApiEndpoint] = useState<string | null>(null)
95
- const [isOrchestrator, setIsOrchestrator] = useState(false)
113
+ const [platformAssignScope, setPlatformAssignScope] = useState<'self' | 'all'>('self')
96
114
  const [subAgentIds, setAgentAgentIds] = useState<string[]>([])
97
115
  const [tools, setTools] = useState<string[]>([])
98
116
  const [skills, setSkills] = useState<string[]>([])
@@ -117,6 +135,17 @@ export function AgentSheet() {
117
135
  const [heartbeatIntervalSec, setHeartbeatIntervalSec] = useState('') // '' = default (30m)
118
136
  const [heartbeatModel, setHeartbeatModel] = useState('')
119
137
  const [heartbeatPrompt, setHeartbeatPrompt] = useState('')
138
+ const [sessionResetMode, setSessionResetMode] = useState<'' | 'idle' | 'daily'>('')
139
+ const [sessionIdleTimeoutSec, setSessionIdleTimeoutSec] = useState('')
140
+ const [sessionMaxAgeSec, setSessionMaxAgeSec] = useState('')
141
+ const [sessionDailyResetAt, setSessionDailyResetAt] = useState('')
142
+ const [sessionResetTimezone, setSessionResetTimezone] = useState('')
143
+ const [identityPersonaLabel, setIdentityPersonaLabel] = useState('')
144
+ const [identitySelfSummary, setIdentitySelfSummary] = useState('')
145
+ const [identityRelationshipSummary, setIdentityRelationshipSummary] = useState('')
146
+ const [identityToneStyle, setIdentityToneStyle] = useState('')
147
+ const [identityBoundariesText, setIdentityBoundariesText] = useState('')
148
+ const [identityContinuityNotesText, setIdentityContinuityNotesText] = useState('')
120
149
  const [budgetEnabled, setBudgetEnabled] = useState(false)
121
150
  const [hourlyBudget, setHourlyBudget] = useState('')
122
151
  const [dailyBudget, setDailyBudget] = useState('')
@@ -181,7 +210,7 @@ export function AgentSheet() {
181
210
  setModel(editing.model)
182
211
  setCredentialId(editing.credentialId || null)
183
212
  setApiEndpoint(editing.apiEndpoint || null)
184
- setIsOrchestrator(editing.isOrchestrator || false)
213
+ setPlatformAssignScope(editing.platformAssignScope || 'self')
185
214
  setAgentAgentIds(editing.subAgentIds || [])
186
215
  setTools(editing.plugins || [])
187
216
  setSkills(editing.skills || [])
@@ -189,7 +218,6 @@ export function AgentSheet() {
189
218
  setMcpServerIds(editing.mcpServerIds || [])
190
219
  setMcpDisabledTools(editing.mcpDisabledTools || [])
191
220
  setFallbackCredentialIds(editing.fallbackCredentialIds || [])
192
- // platformAssignScope derived from isOrchestrator — no separate state
193
221
  setCapabilities(Array.isArray(editing.capabilities) ? editing.capabilities : [])
194
222
  setCapInput('')
195
223
  setOllamaMode(editing.credentialId && editing.provider === 'ollama' ? 'cloud' : 'local')
@@ -204,6 +232,17 @@ export function AgentSheet() {
204
232
  setHeartbeatIntervalSec(parseDurationToSec(editing.heartbeatInterval, editing.heartbeatIntervalSec))
205
233
  setHeartbeatModel(editing.heartbeatModel || '')
206
234
  setHeartbeatPrompt(editing.heartbeatPrompt || '')
235
+ setSessionResetMode(editing.sessionResetMode || '')
236
+ setSessionIdleTimeoutSec(editing.sessionIdleTimeoutSec != null ? String(editing.sessionIdleTimeoutSec) : '')
237
+ setSessionMaxAgeSec(editing.sessionMaxAgeSec != null ? String(editing.sessionMaxAgeSec) : '')
238
+ setSessionDailyResetAt(editing.sessionDailyResetAt || '')
239
+ setSessionResetTimezone(editing.sessionResetTimezone || '')
240
+ setIdentityPersonaLabel(editing.identityState?.personaLabel || '')
241
+ setIdentitySelfSummary(editing.identityState?.selfSummary || '')
242
+ setIdentityRelationshipSummary(editing.identityState?.relationshipSummary || '')
243
+ setIdentityToneStyle(editing.identityState?.toneStyle || '')
244
+ setIdentityBoundariesText(formatIdentityList(editing.identityState?.boundaries))
245
+ setIdentityContinuityNotesText(formatIdentityList(editing.identityState?.continuityNotes))
207
246
  setBudgetEnabled(
208
247
  (typeof editing.hourlyBudget === 'number' && editing.hourlyBudget > 0)
209
248
  || (typeof editing.dailyBudget === 'number' && editing.dailyBudget > 0)
@@ -233,7 +272,7 @@ export function AgentSheet() {
233
272
  setModel('')
234
273
  setCredentialId(null)
235
274
  setApiEndpoint(null)
236
- setIsOrchestrator(false)
275
+ setPlatformAssignScope('self')
237
276
  setAgentAgentIds([])
238
277
  setTools([])
239
278
  setSkills([])
@@ -253,6 +292,17 @@ export function AgentSheet() {
253
292
  setHeartbeatIntervalSec('')
254
293
  setHeartbeatModel('')
255
294
  setHeartbeatPrompt('')
295
+ setSessionResetMode('')
296
+ setSessionIdleTimeoutSec('')
297
+ setSessionMaxAgeSec('')
298
+ setSessionDailyResetAt('')
299
+ setSessionResetTimezone('')
300
+ setIdentityPersonaLabel('')
301
+ setIdentitySelfSummary('')
302
+ setIdentityRelationshipSummary('')
303
+ setIdentityToneStyle('')
304
+ setIdentityBoundariesText('')
305
+ setIdentityContinuityNotesText('')
256
306
  setBudgetEnabled(false)
257
307
  setHourlyBudget('')
258
308
  setDailyBudget('')
@@ -329,6 +379,22 @@ export function AgentSheet() {
329
379
  const parsedHourlyBudget = budgetEnabled && hourlyBudget ? Number(hourlyBudget) : null
330
380
  const parsedDailyBudget = budgetEnabled && dailyBudget ? Number(dailyBudget) : null
331
381
  const parsedMonthlyBudget = budgetEnabled && monthlyBudget ? Number(monthlyBudget) : null
382
+ const parsedSessionIdleTimeoutSec = sessionIdleTimeoutSec ? Number(sessionIdleTimeoutSec) : null
383
+ const parsedSessionMaxAgeSec = sessionMaxAgeSec ? Number(sessionMaxAgeSec) : null
384
+ const identityBoundaries = parseIdentityList(identityBoundariesText)
385
+ const identityContinuityNotes = parseIdentityList(identityContinuityNotesText)
386
+ const identityState = (() => {
387
+ const value = {
388
+ personaLabel: identityPersonaLabel.trim() || undefined,
389
+ selfSummary: identitySelfSummary.trim() || undefined,
390
+ relationshipSummary: identityRelationshipSummary.trim() || undefined,
391
+ toneStyle: identityToneStyle.trim() || undefined,
392
+ boundaries: identityBoundaries.length ? identityBoundaries : undefined,
393
+ continuityNotes: identityContinuityNotes.length ? identityContinuityNotes : undefined,
394
+ }
395
+ return Object.values(value).some((entry) => Array.isArray(entry) ? entry.length > 0 : Boolean(entry)) ? value : null
396
+ })()
397
+ const canDelegateToAgents = platformAssignScope === 'all'
332
398
  const data = {
333
399
  name: name.trim() || 'Unnamed Agent',
334
400
  description,
@@ -338,15 +404,14 @@ export function AgentSheet() {
338
404
  model,
339
405
  credentialId,
340
406
  apiEndpoint: normalizedEndpoint,
341
- isOrchestrator,
342
- subAgentIds: isOrchestrator ? subAgentIds : [],
407
+ subAgentIds: canDelegateToAgents ? subAgentIds : [],
343
408
  tools,
344
409
  skills,
345
410
  skillIds,
346
411
  mcpServerIds,
347
412
  mcpDisabledTools: mcpDisabledTools.length ? mcpDisabledTools : undefined,
348
413
  fallbackCredentialIds,
349
- platformAssignScope: (isOrchestrator ? 'all' : 'self') as 'all' | 'self',
414
+ platformAssignScope,
350
415
  capabilities,
351
416
  projectId: projectId || undefined,
352
417
  avatarSeed: avatarSeed.trim() || undefined,
@@ -359,6 +424,12 @@ export function AgentSheet() {
359
424
  heartbeatIntervalSec: heartbeatIntervalSec ? Number(heartbeatIntervalSec) : null,
360
425
  heartbeatModel: heartbeatModel.trim() || null,
361
426
  heartbeatPrompt: heartbeatPrompt.trim() || null,
427
+ identityState,
428
+ sessionResetMode: sessionResetMode || null,
429
+ sessionIdleTimeoutSec: Number.isFinite(parsedSessionIdleTimeoutSec) && parsedSessionIdleTimeoutSec! >= 0 ? parsedSessionIdleTimeoutSec : null,
430
+ sessionMaxAgeSec: Number.isFinite(parsedSessionMaxAgeSec) && parsedSessionMaxAgeSec! >= 0 ? parsedSessionMaxAgeSec : null,
431
+ sessionDailyResetAt: sessionDailyResetAt.trim() || null,
432
+ sessionResetTimezone: sessionResetTimezone.trim() || null,
362
433
  hourlyBudget: parsedHourlyBudget && parsedHourlyBudget > 0 ? parsedHourlyBudget : null,
363
434
  dailyBudget: parsedDailyBudget && parsedDailyBudget > 0 ? parsedDailyBudget : null,
364
435
  monthlyBudget: parsedMonthlyBudget && parsedMonthlyBudget > 0 ? parsedMonthlyBudget : null,
@@ -473,7 +544,8 @@ export function AgentSheet() {
473
544
  setSaving(false)
474
545
  }
475
546
 
476
- const agentOptions = Object.values(agents).filter((p) => !p.isOrchestrator && p.id !== editingId)
547
+ const canDelegateToAgents = platformAssignScope === 'all'
548
+ const agentOptions = Object.values(agents).filter((p) => p.id !== editingId)
477
549
 
478
550
  const toggleAgent = (id: string) => {
479
551
  setAgentAgentIds((prev) =>
@@ -491,7 +563,7 @@ export function AgentSheet() {
491
563
  <h2 className="font-display text-[28px] font-700 tracking-[-0.03em] mb-2">
492
564
  {editing ? 'Edit Agent' : 'New Agent'}
493
565
  </h2>
494
- <p className="text-[14px] text-text-3">Define an AI agent or orchestrator</p>
566
+ <p className="text-[14px] text-text-3">Define an AI agent and optional multi-agent delegation behavior</p>
495
567
  </div>
496
568
  <div className="flex items-center gap-3 mt-1.5">
497
569
  <label className="text-[11px] font-600 text-text-3 uppercase tracking-[0.08em]">OpenClaw</label>
@@ -981,6 +1053,127 @@ export function AgentSheet() {
981
1053
  </div>
982
1054
  )}
983
1055
 
1056
+ <div className="mb-8">
1057
+ <label className="flex items-center gap-2 font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-2">
1058
+ Identity Continuity <HintTip text="Seeds the agent's continuity state so session memory can preserve a stable persona and relationship context." />
1059
+ </label>
1060
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-3 mb-3">
1061
+ <input
1062
+ type="text"
1063
+ value={identityPersonaLabel}
1064
+ onChange={(e) => setIdentityPersonaLabel(e.target.value)}
1065
+ placeholder="Persona label"
1066
+ className={inputClass}
1067
+ style={{ fontFamily: 'inherit' }}
1068
+ />
1069
+ <input
1070
+ type="text"
1071
+ value={identityToneStyle}
1072
+ onChange={(e) => setIdentityToneStyle(e.target.value)}
1073
+ placeholder="Tone style"
1074
+ className={inputClass}
1075
+ style={{ fontFamily: 'inherit' }}
1076
+ />
1077
+ </div>
1078
+ <div className="grid grid-cols-1 gap-3">
1079
+ <textarea
1080
+ value={identitySelfSummary}
1081
+ onChange={(e) => setIdentitySelfSummary(e.target.value)}
1082
+ placeholder="How this agent should summarize itself across sessions."
1083
+ rows={3}
1084
+ className={`${inputClass} resize-y min-h-[84px]`}
1085
+ style={{ fontFamily: 'inherit' }}
1086
+ />
1087
+ <textarea
1088
+ value={identityRelationshipSummary}
1089
+ onChange={(e) => setIdentityRelationshipSummary(e.target.value)}
1090
+ placeholder="Relationship framing or standing context the agent should keep in mind."
1091
+ rows={3}
1092
+ className={`${inputClass} resize-y min-h-[84px]`}
1093
+ style={{ fontFamily: 'inherit' }}
1094
+ />
1095
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
1096
+ <textarea
1097
+ value={identityBoundariesText}
1098
+ onChange={(e) => setIdentityBoundariesText(e.target.value)}
1099
+ placeholder="Boundaries, one per line."
1100
+ rows={4}
1101
+ className={`${inputClass} resize-y min-h-[108px]`}
1102
+ style={{ fontFamily: 'inherit' }}
1103
+ />
1104
+ <textarea
1105
+ value={identityContinuityNotesText}
1106
+ onChange={(e) => setIdentityContinuityNotesText(e.target.value)}
1107
+ placeholder="Continuity notes, one per line."
1108
+ rows={4}
1109
+ className={`${inputClass} resize-y min-h-[108px]`}
1110
+ style={{ fontFamily: 'inherit' }}
1111
+ />
1112
+ </div>
1113
+ </div>
1114
+ <p className="text-[12px] text-text-3/60 mt-2 leading-[1.5]">
1115
+ Use one line per item. Boundaries are stable guardrails; continuity notes are recurring relationship or project context worth carrying across sessions.
1116
+ </p>
1117
+ </div>
1118
+
1119
+ <div className="mb-8">
1120
+ <label className="flex items-center gap-2 font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-2">
1121
+ Session Reset Policy <HintTip text="Controls when this agent's sessions are considered stale and should be refreshed." />
1122
+ </label>
1123
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-3 mb-3">
1124
+ <div>
1125
+ <select
1126
+ value={sessionResetMode}
1127
+ onChange={(e) => setSessionResetMode(e.target.value as typeof sessionResetMode)}
1128
+ className={inputClass}
1129
+ style={{ fontFamily: 'inherit' }}
1130
+ >
1131
+ <option value="">Inherit global default</option>
1132
+ <option value="idle">Idle</option>
1133
+ <option value="daily">Daily</option>
1134
+ </select>
1135
+ </div>
1136
+ <div>
1137
+ <input
1138
+ type="number"
1139
+ min={0}
1140
+ value={sessionIdleTimeoutSec}
1141
+ onChange={(e) => setSessionIdleTimeoutSec(e.target.value)}
1142
+ placeholder="Idle timeout in seconds"
1143
+ className={inputClass}
1144
+ style={{ fontFamily: 'inherit' }}
1145
+ />
1146
+ </div>
1147
+ </div>
1148
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
1149
+ <input
1150
+ type="number"
1151
+ min={0}
1152
+ value={sessionMaxAgeSec}
1153
+ onChange={(e) => setSessionMaxAgeSec(e.target.value)}
1154
+ placeholder="Max age in seconds"
1155
+ className={inputClass}
1156
+ style={{ fontFamily: 'inherit' }}
1157
+ />
1158
+ <input
1159
+ type="text"
1160
+ value={sessionDailyResetAt}
1161
+ onChange={(e) => setSessionDailyResetAt(e.target.value)}
1162
+ placeholder="Daily reset time (HH:MM)"
1163
+ className={inputClass}
1164
+ style={{ fontFamily: 'inherit' }}
1165
+ />
1166
+ <input
1167
+ type="text"
1168
+ value={sessionResetTimezone}
1169
+ onChange={(e) => setSessionResetTimezone(e.target.value)}
1170
+ placeholder="Timezone (optional)"
1171
+ className={inputClass}
1172
+ style={{ fontFamily: 'inherit' }}
1173
+ />
1174
+ </div>
1175
+ </div>
1176
+
984
1177
  {/* OpenClaw Gateway Fields */}
985
1178
  {openclawEnabled && (
986
1179
  <div className="mb-8 space-y-5">
@@ -1178,7 +1371,7 @@ export function AgentSheet() {
1178
1371
  {!openclawEnabled && <div className="mb-8">
1179
1372
  <SectionLabel>Provider</SectionLabel>
1180
1373
  <div className="grid grid-cols-3 gap-3">
1181
- {providers.filter((p) => !isOrchestrator || p.id !== 'claude-cli').map((p) => {
1374
+ {providers.map((p) => {
1182
1375
  const isConnected = !p.requiresApiKey || Object.values(credentials).some((c) => c.provider === p.id)
1183
1376
  return (
1184
1377
  <button
@@ -1584,15 +1777,13 @@ export function AgentSheet() {
1584
1777
  <label className="flex items-center gap-3 cursor-pointer">
1585
1778
  <div
1586
1779
  onClick={() => {
1587
- const next = !isOrchestrator
1588
- setIsOrchestrator(next)
1589
- if (next && provider === 'claude-cli') setProvider('anthropic')
1780
+ setPlatformAssignScope((current) => current === 'all' ? 'self' : 'all')
1590
1781
  }}
1591
1782
  className={`w-11 h-6 rounded-full transition-all duration-200 relative cursor-pointer
1592
- ${isOrchestrator ? 'bg-accent-bright' : 'bg-white/[0.08]'}`}
1783
+ ${canDelegateToAgents ? 'bg-accent-bright' : 'bg-white/[0.08]'}`}
1593
1784
  >
1594
1785
  <div className={`absolute top-0.5 w-5 h-5 rounded-full bg-white transition-all duration-200
1595
- ${isOrchestrator ? 'left-[22px]' : 'left-0.5'}`} />
1786
+ ${canDelegateToAgents ? 'left-[22px]' : 'left-0.5'}`} />
1596
1787
  </div>
1597
1788
  <span className="font-display text-[14px] font-600 text-text-2">Can Delegate to Other Agents</span>
1598
1789
  <span className="text-[12px] text-text-3">Route work to specialized agents and coordinate multi-agent tasks</span>
@@ -1600,7 +1791,7 @@ export function AgentSheet() {
1600
1791
  </div>
1601
1792
  )}
1602
1793
 
1603
- {provider !== 'openclaw' && isOrchestrator && agentOptions.length > 0 && (
1794
+ {provider !== 'openclaw' && canDelegateToAgents && agentOptions.length > 0 && (
1604
1795
  <div className="mb-8">
1605
1796
  <SectionLabel>Available Agents</SectionLabel>
1606
1797
  <AgentPickerList