@swarmclawai/swarmclaw 1.2.6 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/README.md +54 -23
  2. package/next.config.ts +1 -0
  3. package/package.json +4 -3
  4. package/scripts/easy-setup.mjs +1 -1
  5. package/scripts/postinstall.mjs +1 -1
  6. package/skills/swarmclaw.md +115 -0
  7. package/skills/tools/browser.md +131 -0
  8. package/skills/tools/execute.md +98 -0
  9. package/skills/tools/files.md +98 -0
  10. package/skills/tools/memory.md +104 -0
  11. package/skills/tools/platform.md +144 -0
  12. package/skills/tools/skills.md +83 -0
  13. package/src/app/agents/[id]/page.tsx +1 -18
  14. package/src/app/api/agents/thread-route.test.ts +0 -1
  15. package/src/app/api/approvals/route.test.ts +6 -22
  16. package/src/app/api/chats/[id]/messages/route.ts +23 -19
  17. package/src/app/api/chats/messages-route.test.ts +105 -51
  18. package/src/app/api/connectors/route.ts +2 -2
  19. package/src/app/api/mcp-servers/[id]/test/route.ts +3 -2
  20. package/src/app/api/openclaw/deploy/route.ts +2 -0
  21. package/src/app/api/portability/export/route.ts +8 -0
  22. package/src/app/api/portability/import/route.test.ts +80 -0
  23. package/src/app/api/portability/import/route.ts +28 -0
  24. package/src/app/api/settings/route.ts +0 -2
  25. package/src/app/api/setup/doctor/route.ts +4 -4
  26. package/src/app/api/wallets/[id]/route.ts +15 -157
  27. package/src/app/api/wallets/generate/route.ts +22 -0
  28. package/src/app/api/wallets/route.test.ts +147 -0
  29. package/src/app/api/wallets/route.ts +13 -95
  30. package/src/app/autonomy/page.tsx +2 -57
  31. package/src/app/protocols/page.tsx +2 -21
  32. package/src/app/settings/page.tsx +0 -9
  33. package/src/app/wallets/page.tsx +105 -5
  34. package/src/cli/index.js +21 -33
  35. package/src/cli/spec.js +19 -30
  36. package/src/components/agents/agent-chat-list.tsx +23 -1
  37. package/src/components/agents/agent-sheet.tsx +2 -40
  38. package/src/components/agents/inspector-panel.tsx +165 -131
  39. package/src/components/chat/chat-area.tsx +38 -9
  40. package/src/components/chat/chat-card.tsx +0 -31
  41. package/src/components/chat/message-bubble.tsx +1 -108
  42. package/src/components/chat/message-list.tsx +33 -19
  43. package/src/components/connectors/connector-sheet.tsx +25 -1
  44. package/src/components/gateways/gateway-sheet.tsx +5 -2
  45. package/src/components/layout/sidebar-rail.tsx +6 -10
  46. package/src/components/projects/project-detail.tsx +3 -35
  47. package/src/components/projects/tabs/overview-tab.tsx +3 -59
  48. package/src/components/projects/tabs/work-tab.tsx +7 -77
  49. package/src/components/protocols/structured-session-launcher.tsx +1 -22
  50. package/src/components/shared/connector-platform-icon.tsx +1 -0
  51. package/src/components/tasks/task-card.tsx +4 -34
  52. package/src/components/tasks/task-sheet.tsx +6 -36
  53. package/src/components/wallets/wallet-list.tsx +150 -0
  54. package/src/lib/agent-execute-defaults.test.ts +24 -0
  55. package/src/lib/agent-execute-defaults.ts +62 -0
  56. package/src/lib/app/navigation.test.ts +0 -13
  57. package/src/lib/app/navigation.ts +2 -7
  58. package/src/lib/app/view-constants.ts +14 -19
  59. package/src/lib/chat/queued-message-queue.test.ts +134 -1
  60. package/src/lib/chat/queued-message-queue.ts +77 -2
  61. package/src/lib/server/agents/agent-service.ts +5 -0
  62. package/src/lib/server/agents/agent-thread-session.ts +0 -1
  63. package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
  64. package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
  65. package/src/lib/server/agents/delegation-jobs.ts +0 -25
  66. package/src/lib/server/agents/main-agent-loop.ts +1 -49
  67. package/src/lib/server/agents/subagent-runtime.ts +0 -1
  68. package/src/lib/server/approval-match.ts +0 -85
  69. package/src/lib/server/approvals.test.ts +6 -6
  70. package/src/lib/server/approvals.ts +0 -6
  71. package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
  72. package/src/lib/server/builtin-extensions.ts +1 -2
  73. package/src/lib/server/capability-router.test.ts +0 -2
  74. package/src/lib/server/chat-execution/chat-execution-advanced.test.ts +1 -1
  75. package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +15 -14
  76. package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
  77. package/src/lib/server/chat-execution/chat-execution-utils.ts +2 -4
  78. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
  79. package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
  80. package/src/lib/server/chat-execution/chat-turn-preparation.ts +81 -64
  81. package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -0
  82. package/src/lib/server/chat-execution/continuation-evaluator.ts +8 -0
  83. package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
  84. package/src/lib/server/chat-execution/memory-mutation-tools.ts +1 -1
  85. package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
  86. package/src/lib/server/chat-execution/message-classifier.ts +11 -16
  87. package/src/lib/server/chat-execution/prompt-builder.test.ts +27 -0
  88. package/src/lib/server/chat-execution/prompt-builder.ts +14 -31
  89. package/src/lib/server/chat-execution/prompt-mode.test.ts +24 -0
  90. package/src/lib/server/chat-execution/prompt-mode.ts +5 -1
  91. package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
  92. package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
  93. package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
  94. package/src/lib/server/chat-execution/stream-agent-chat.test.ts +13 -126
  95. package/src/lib/server/chat-execution/stream-agent-chat.ts +46 -21
  96. package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
  97. package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
  98. package/src/lib/server/chatrooms/chatroom-routing.test.ts +4 -0
  99. package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
  100. package/src/lib/server/chats/chat-session-service.ts +3 -5
  101. package/src/lib/server/connectors/connector-inbound.ts +0 -1
  102. package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
  103. package/src/lib/server/connectors/connector-service.ts +39 -9
  104. package/src/lib/server/connectors/discord.ts +2 -2
  105. package/src/lib/server/connectors/matrix.ts +3 -2
  106. package/src/lib/server/connectors/signal.ts +5 -4
  107. package/src/lib/server/connectors/slack.ts +10 -9
  108. package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
  109. package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
  110. package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
  111. package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
  112. package/src/lib/server/connectors/swarmdock-tasks.ts +119 -0
  113. package/src/lib/server/connectors/swarmdock.ts +255 -0
  114. package/src/lib/server/connectors/teams.ts +3 -2
  115. package/src/lib/server/connectors/telegram.ts +4 -4
  116. package/src/lib/server/connectors/whatsapp.ts +2 -2
  117. package/src/lib/server/daemon/controller.ts +7 -0
  118. package/src/lib/server/execution-brief.test.ts +2 -25
  119. package/src/lib/server/execution-brief.ts +12 -35
  120. package/src/lib/server/execution-engine/task-attempt.ts +0 -1
  121. package/src/lib/server/gateways/gateway-profile-service.ts +19 -1
  122. package/src/lib/server/messages/message-repository.test.ts +70 -0
  123. package/src/lib/server/messages/message-repository.ts +11 -6
  124. package/src/lib/server/openclaw/deploy.ts +32 -2
  125. package/src/lib/server/persistence/storage-context.ts +0 -5
  126. package/src/lib/server/plugins-advanced.test.ts +1 -2
  127. package/src/lib/server/portability/export.ts +109 -0
  128. package/src/lib/server/portability/import.ts +159 -0
  129. package/src/lib/server/protocols/protocol-normalization.ts +0 -4
  130. package/src/lib/server/protocols/protocol-queries.ts +0 -6
  131. package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
  132. package/src/lib/server/protocols/protocol-service.ts +0 -1
  133. package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
  134. package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
  135. package/src/lib/server/protocols/protocol-swarm.ts +0 -2
  136. package/src/lib/server/protocols/protocol-types.ts +0 -2
  137. package/src/lib/server/provider-health.ts +1 -10
  138. package/src/lib/server/runtime/daemon-state/core.ts +0 -9
  139. package/src/lib/server/runtime/daemon-state.test.ts +0 -35
  140. package/src/lib/server/runtime/heartbeat-service.ts +3 -23
  141. package/src/lib/server/runtime/process-manager.ts +13 -9
  142. package/src/lib/server/runtime/queue/core.ts +11 -33
  143. package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
  144. package/src/lib/server/runtime/scheduler.ts +0 -13
  145. package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
  146. package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
  147. package/src/lib/server/runtime/session-run-manager/queries.ts +15 -1
  148. package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
  149. package/src/lib/server/runtime/session-run-manager.test.ts +58 -28
  150. package/src/lib/server/sandbox/session-runtime.test.ts +18 -1
  151. package/src/lib/server/sandbox/session-runtime.ts +40 -28
  152. package/src/lib/server/session-tools/autonomy-tools.test.ts +7 -9
  153. package/src/lib/server/session-tools/context.ts +1 -1
  154. package/src/lib/server/session-tools/credential-env.ts +109 -0
  155. package/src/lib/server/session-tools/crud.ts +3 -17
  156. package/src/lib/server/session-tools/delegate.ts +0 -4
  157. package/src/lib/server/session-tools/edit_file.ts +3 -2
  158. package/src/lib/server/session-tools/execute.test.ts +58 -0
  159. package/src/lib/server/session-tools/execute.ts +334 -0
  160. package/src/lib/server/session-tools/files-tool.ts +635 -0
  161. package/src/lib/server/session-tools/index.ts +14 -8
  162. package/src/lib/server/session-tools/memory-tool.ts +242 -0
  163. package/src/lib/server/session-tools/memory.ts +1 -1
  164. package/src/lib/server/session-tools/openclaw-nodes.ts +3 -2
  165. package/src/lib/server/session-tools/openclaw-workspace.ts +3 -2
  166. package/src/lib/server/session-tools/platform-tool.ts +617 -0
  167. package/src/lib/server/session-tools/session-info.ts +3 -2
  168. package/src/lib/server/session-tools/session-tools-wiring.test.ts +3 -4
  169. package/src/lib/server/session-tools/shell.ts +7 -122
  170. package/src/lib/server/session-tools/skills-tool.ts +396 -0
  171. package/src/lib/server/session-tools/team-context.ts +0 -3
  172. package/src/lib/server/session-tools/web.ts +2 -2
  173. package/src/lib/server/storage-normalization.ts +10 -0
  174. package/src/lib/server/storage.ts +18 -45
  175. package/src/lib/server/tasks/task-checkout.ts +59 -0
  176. package/src/lib/server/tasks/task-lifecycle.ts +2 -0
  177. package/src/lib/server/tasks/task-route-service.ts +4 -26
  178. package/src/lib/server/tasks/task-service.ts +0 -7
  179. package/src/lib/server/tool-aliases.ts +2 -2
  180. package/src/lib/server/tool-capability-policy-advanced.test.ts +13 -6
  181. package/src/lib/server/tool-capability-policy.test.ts +2 -1
  182. package/src/lib/server/tool-capability-policy.ts +60 -35
  183. package/src/lib/server/tool-planning.ts +11 -12
  184. package/src/lib/server/universal-tool-access.ts +0 -1
  185. package/src/lib/server/wallets/wallet-crypto.ts +33 -0
  186. package/src/lib/server/wallets/wallet-repository.ts +24 -0
  187. package/src/lib/server/wallets/wallet-service.ts +119 -0
  188. package/src/lib/server/working-state/extraction.ts +8 -42
  189. package/src/lib/server/working-state/normalization.ts +10 -103
  190. package/src/lib/server/working-state/service.ts +12 -21
  191. package/src/lib/setup-defaults.ts +5 -0
  192. package/src/lib/strip-internal-metadata.test.ts +1 -1
  193. package/src/lib/strip-internal-metadata.ts +1 -1
  194. package/src/lib/tool-definitions.ts +1 -1
  195. package/src/lib/validation/schemas.test.ts +16 -0
  196. package/src/lib/validation/schemas.ts +49 -2
  197. package/src/stores/slices/data-slice.ts +5 -1
  198. package/src/stores/slices/ui-slice.ts +0 -4
  199. package/src/stores/use-chat-store.test.ts +231 -0
  200. package/src/stores/use-chat-store.ts +62 -13
  201. package/src/types/agent.ts +264 -0
  202. package/src/types/app-settings.ts +173 -0
  203. package/src/types/approval.ts +25 -0
  204. package/src/types/connector.ts +188 -0
  205. package/src/types/extension.ts +386 -0
  206. package/src/types/index.ts +16 -3555
  207. package/src/types/message.ts +56 -0
  208. package/src/types/misc.ts +737 -0
  209. package/src/types/protocol.ts +420 -0
  210. package/src/types/provider.ts +52 -0
  211. package/src/types/run.ts +180 -0
  212. package/src/types/schedule.ts +59 -0
  213. package/src/types/session.ts +215 -0
  214. package/src/types/skill.ts +157 -0
  215. package/src/types/swarmdock.ts +29 -0
  216. package/src/types/task.ts +144 -0
  217. package/src/types/working-state.ts +204 -0
  218. package/src/views/settings/section-heartbeat.tsx +2 -2
  219. package/src/views/settings/section-runtime-loop.tsx +0 -14
  220. package/src/app/api/canvas/[sessionId]/route.ts +0 -35
  221. package/src/app/api/missions/[id]/actions/route.ts +0 -31
  222. package/src/app/api/missions/[id]/events/route.ts +0 -14
  223. package/src/app/api/missions/[id]/route.ts +0 -10
  224. package/src/app/api/missions/route.test.ts +0 -244
  225. package/src/app/api/missions/route.ts +0 -57
  226. package/src/app/api/wallets/[id]/approve/route.ts +0 -79
  227. package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
  228. package/src/app/api/wallets/[id]/send/route.ts +0 -113
  229. package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
  230. package/src/app/missions/[id]/page.tsx +0 -3
  231. package/src/app/missions/page.tsx +0 -685
  232. package/src/components/canvas/canvas-panel.tsx +0 -267
  233. package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
  234. package/src/components/wallets/wallet-panel.tsx +0 -1010
  235. package/src/components/wallets/wallet-section.tsx +0 -260
  236. package/src/features/missions/queries.ts +0 -23
  237. package/src/lib/canvas-content.test.ts +0 -360
  238. package/src/lib/canvas-content.ts +0 -198
  239. package/src/lib/server/canvas-content.test.ts +0 -32
  240. package/src/lib/server/canvas-content.ts +0 -6
  241. package/src/lib/server/ethereum.ts +0 -591
  242. package/src/lib/server/evm-swap.ts +0 -476
  243. package/src/lib/server/missions/mission-intent.test.ts +0 -63
  244. package/src/lib/server/missions/mission-intent.ts +0 -569
  245. package/src/lib/server/missions/mission-repository.ts +0 -74
  246. package/src/lib/server/missions/mission-service/actions.ts +0 -6
  247. package/src/lib/server/missions/mission-service/bindings.ts +0 -9
  248. package/src/lib/server/missions/mission-service/context.ts +0 -4
  249. package/src/lib/server/missions/mission-service/core.ts +0 -2271
  250. package/src/lib/server/missions/mission-service/queries.ts +0 -12
  251. package/src/lib/server/missions/mission-service/recovery.ts +0 -5
  252. package/src/lib/server/missions/mission-service/ticks.ts +0 -9
  253. package/src/lib/server/missions/mission-service.test.ts +0 -888
  254. package/src/lib/server/missions/mission-service.ts +0 -6
  255. package/src/lib/server/session-tools/canvas.ts +0 -105
  256. package/src/lib/server/session-tools/sandbox.ts +0 -281
  257. package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
  258. package/src/lib/server/session-tools/wallet.ts +0 -1287
  259. package/src/lib/server/solana.ts +0 -327
  260. package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
  261. package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
  262. package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
  263. package/src/lib/server/wallet/wallet-service.test.ts +0 -81
  264. package/src/lib/server/wallet/wallet-service.ts +0 -225
  265. package/src/lib/wallet/wallet-transactions.test.ts +0 -75
  266. package/src/lib/wallet/wallet-transactions.ts +0 -43
  267. package/src/lib/wallet/wallet.test.ts +0 -333
  268. package/src/lib/wallet/wallet.ts +0 -183
  269. package/src/views/settings/section-wallets.tsx +0 -35
@@ -0,0 +1,104 @@
1
+ # Memory Tool
2
+
3
+ Persistent knowledge storage across conversations. Store facts, preferences, context, and decisions so they survive beyond the current session.
4
+
5
+ ## Memory Tiers
6
+
7
+ | Tier | Scope | Lifetime | Use For |
8
+ |------|-------|----------|---------|
9
+ | **Working** | Current session | Session duration | Scratch notes, intermediate results, task state |
10
+ | **Durable** | Cross-session | Permanent until deleted | User preferences, project facts, learned patterns |
11
+ | **Archive** | Cross-session | Permanent, lower priority | Completed task summaries, historical context |
12
+
13
+ ## Actions
14
+
15
+ | Action | Description | Key Parameters |
16
+ |--------|-------------|----------------|
17
+ | `store` | Save a new memory | `title`, `value`, `category` |
18
+ | `search` | Find memories by query | `query`, `scope` (optional) |
19
+ | `get` | Retrieve a specific memory | `id` or `key` |
20
+ | `update` | Modify an existing memory | `id`, `value` (and/or `title`, `category`) |
21
+
22
+ ## Store
23
+
24
+ ```json
25
+ {
26
+ "action": "store",
27
+ "title": "User prefers dark mode",
28
+ "value": "The user explicitly asked for dark mode in all UI components. Use dark backgrounds (#1a1a2e) with light text (#e0e0e0).",
29
+ "category": "preference"
30
+ }
31
+ ```
32
+
33
+ ### Categories
34
+
35
+ | Category | When to Use |
36
+ |----------|------------|
37
+ | `preference` | User likes, dislikes, style choices |
38
+ | `fact` | Verified information about user, project, or domain |
39
+ | `decision` | Architecture decisions, design choices with rationale |
40
+ | `context` | Background info that helps future conversations |
41
+ | `note` | General observations, reminders |
42
+ | `identity` | Agent's learned personality traits, communication style |
43
+
44
+ ## Search
45
+
46
+ ```json
47
+ { "action": "search", "query": "database schema preferences" }
48
+ ```
49
+
50
+ Returns ranked results with relevance scores. Supports semantic-style matching (expanded query terms).
51
+
52
+ ### Scope Filtering
53
+
54
+ ```json
55
+ { "action": "search", "query": "API keys", "scope": "agent" }
56
+ ```
57
+
58
+ | Scope | What It Searches |
59
+ |-------|-----------------|
60
+ | `auto` | Smart default: session + agent + global (recommended) |
61
+ | `session` | Current session only |
62
+ | `agent` | Current agent's memories |
63
+ | `project` | Current project's memories |
64
+ | `global` | Shared across all agents |
65
+ | `all` | Everything |
66
+
67
+ ## Update
68
+
69
+ ```json
70
+ { "action": "update", "id": "mem_abc123", "value": "Updated: user now prefers system theme over dark mode" }
71
+ ```
72
+
73
+ Use `update` when information changes. Avoids creating duplicate memories.
74
+
75
+ ## When to Remember
76
+
77
+ **Do remember:**
78
+ - User-stated preferences ("I prefer TypeScript", "always use tabs")
79
+ - Corrections ("actually, the API endpoint is /v2/...")
80
+ - Project-specific facts (tech stack, coding conventions, team structure)
81
+ - Important decisions and their rationale
82
+
83
+ **Do not remember:**
84
+ - Ephemeral task details (file paths being edited right now)
85
+ - Information already in the codebase (README, config files)
86
+ - Trivial conversational context
87
+ - Sensitive data (passwords, tokens, private keys)
88
+
89
+ ## When to Forget
90
+
91
+ Use `update` to revise outdated memories rather than storing contradictory ones. If a memory is no longer relevant, update its value to reflect the current state.
92
+
93
+ ## Memory in Practice
94
+
95
+ 1. **Start of session**: Relevant memories are automatically injected into context based on the current agent, project, and conversation topic.
96
+ 2. **During conversation**: Store new insights as they emerge. Search when you need to recall something.
97
+ 3. **End of significant interaction**: Store a summary of decisions made, preferences learned, or context that would help next time.
98
+
99
+ ## Tips
100
+
101
+ - Write memories in the third person for clarity: "The user prefers..." not "You prefer..."
102
+ - Include enough context in the `value` that the memory is useful standalone
103
+ - Use descriptive `title` fields -- they're used for search ranking
104
+ - Prefer `category: "decision"` for architectural choices so they can be filtered later
@@ -0,0 +1,144 @@
1
+ # Platform Tool
2
+
3
+ Interact with the SwarmClaw platform: manage tasks, communicate with humans and other agents, access projects, and participate in chatrooms.
4
+
5
+ ## Action Groups
6
+
7
+ ### Tasks
8
+
9
+ | Action | Description | Key Parameters |
10
+ |--------|-------------|----------------|
11
+ | `tasks.create` | Create a new task | `title`, `description`, `priority` |
12
+ | `tasks.update` | Update task fields | `id`, fields to update |
13
+ | `tasks.list` | List tasks with filters | `status`, `assignee`, `priority` |
14
+ | `tasks.get` | Get task details | `id` |
15
+ | `tasks.complete` | Mark task as done | `id`, `result` (optional summary) |
16
+
17
+ #### Create a task
18
+
19
+ ```json
20
+ {
21
+ "action": "tasks.create",
22
+ "title": "Review PR #55",
23
+ "description": "Check for type safety issues and test coverage",
24
+ "priority": "high"
25
+ }
26
+ ```
27
+
28
+ #### List open tasks
29
+
30
+ ```json
31
+ { "action": "tasks.list", "status": "open" }
32
+ ```
33
+
34
+ ### Communication
35
+
36
+ | Action | Description | Key Parameters |
37
+ |--------|-------------|----------------|
38
+ | `communicate.ask_human` | Block and wait for human input | `question`, `context` |
39
+ | `communicate.send_message` | Send to a connector channel | `connector`, `channel`, `message` |
40
+ | `communicate.delegate` | Route work to another agent | `agentId`, `message` |
41
+ | `communicate.spawn` | Create a subagent for parallel work | `agentId`, `message`, `mode` |
42
+
43
+ #### Ask human (blocks execution)
44
+
45
+ ```json
46
+ {
47
+ "action": "communicate.ask_human",
48
+ "question": "Should I proceed with the database migration?",
49
+ "context": "This will add 3 new columns to the users table and backfill existing rows."
50
+ }
51
+ ```
52
+
53
+ **Important:** `ask_human` blocks the agent loop until the human responds. Use it when you genuinely need input before continuing. Do not use it for status updates (use `send_message` instead).
54
+
55
+ #### Send a message to Discord/Slack/Telegram
56
+
57
+ ```json
58
+ {
59
+ "action": "communicate.send_message",
60
+ "connector": "discord",
61
+ "channel": "#general",
62
+ "message": "Deployment complete. All tests passing."
63
+ }
64
+ ```
65
+
66
+ #### Delegate to another agent
67
+
68
+ ```json
69
+ {
70
+ "action": "communicate.delegate",
71
+ "agentId": "agent_research",
72
+ "message": "Find the top 5 competitors in the AI coding assistant space and summarize their pricing."
73
+ }
74
+ ```
75
+
76
+ #### Spawn a subagent
77
+
78
+ ```json
79
+ {
80
+ "action": "communicate.spawn",
81
+ "agentId": "agent_coder",
82
+ "message": "Implement the dark mode toggle component",
83
+ "mode": "run"
84
+ }
85
+ ```
86
+
87
+ Modes:
88
+ - `run` -- fire and forget, subagent runs independently
89
+ - `session` -- creates a persistent session you can check on later
90
+
91
+ ### Projects
92
+
93
+ | Action | Description | Key Parameters |
94
+ |--------|-------------|----------------|
95
+ | `projects.list` | List all projects | (none) |
96
+ | `projects.get` | Get project details | `id` |
97
+
98
+ ```json
99
+ { "action": "projects.list" }
100
+ ```
101
+
102
+ ### Chatrooms
103
+
104
+ | Action | Description | Key Parameters |
105
+ |--------|-------------|----------------|
106
+ | `chatrooms.send` | Send a message to a chatroom | `chatroomId`, `message` |
107
+ | `chatrooms.list` | List available chatrooms | (none) |
108
+ | `chatrooms.history` | Get recent messages | `chatroomId`, `limit` |
109
+
110
+ ```json
111
+ {
112
+ "action": "chatrooms.send",
113
+ "chatroomId": "room_design",
114
+ "message": "The mockups are ready for review."
115
+ }
116
+ ```
117
+
118
+ ### Agents
119
+
120
+ | Action | Description | Key Parameters |
121
+ |--------|-------------|----------------|
122
+ | `agents.list` | List all agents | (none) |
123
+ | `agents.get` | Get agent details | `id` |
124
+
125
+ ```json
126
+ { "action": "agents.list" }
127
+ ```
128
+
129
+ ## Communication Decision Guide
130
+
131
+ | Situation | Action |
132
+ |-----------|--------|
133
+ | Need human approval before proceeding | `communicate.ask_human` |
134
+ | Sharing a status update with the team | `communicate.send_message` |
135
+ | Task is outside your expertise | `communicate.delegate` |
136
+ | Task can run in parallel with your work | `communicate.spawn` |
137
+ | Collaborating with agents in a shared space | `chatrooms.send` |
138
+
139
+ ## Tips
140
+
141
+ - Use `ask_human` sparingly. Only block when you truly cannot proceed without input.
142
+ - When delegating, provide enough context that the target agent can work independently.
143
+ - Check `tasks.list` before creating duplicates.
144
+ - Use `agents.list` to discover available agents and their capabilities before delegating.
@@ -0,0 +1,83 @@
1
+ # Skills Tool
2
+
3
+ Discover and load skill files that teach you how to use tools, APIs, and workflows.
4
+
5
+ ## Actions
6
+
7
+ | Action | Description | Key Parameters |
8
+ |--------|-------------|----------------|
9
+ | `list` | Browse all available skills | (none) |
10
+ | `read` | Load a skill by name | `name` |
11
+ | `search` | Find skills by keyword | `query` |
12
+
13
+ ## List Available Skills
14
+
15
+ ```json
16
+ { "action": "list" }
17
+ ```
18
+
19
+ Returns all discoverable skill files with names and short descriptions.
20
+
21
+ ## Read a Skill
22
+
23
+ ```json
24
+ { "action": "read", "name": "tools/files" }
25
+ ```
26
+
27
+ Loads the full content of a skill file. Skill names use path-style notation:
28
+
29
+ - `tools/files` -- the files tool documentation
30
+ - `tools/memory` -- the memory tool documentation
31
+ - `swarmclaw` -- the platform overview skill
32
+ - `github` -- GitHub CLI operations
33
+
34
+ Name matching is flexible: partial matches work if unambiguous.
35
+
36
+ ## Search Skills
37
+
38
+ ```json
39
+ { "action": "search", "query": "browser screenshot" }
40
+ ```
41
+
42
+ Searches skill file names, descriptions, and content for keyword matches. Returns ranked results.
43
+
44
+ ## Skill File Locations
45
+
46
+ | Directory | Source | Description |
47
+ |-----------|--------|-------------|
48
+ | `skills/` | Built-in | Shipped with SwarmClaw, checked into the repo |
49
+ | `data/skills/` | User-created | Added at runtime, not version-controlled |
50
+
51
+ ## Skill File Format
52
+
53
+ Skills are markdown files (`.md`). They can be:
54
+
55
+ - **Flat files**: `skills/swarmclaw.md`
56
+ - **Directory-based**: `skills/github/SKILL.md`
57
+ - **Nested**: `skills/tools/files.md`
58
+
59
+ Optional YAML frontmatter can declare metadata:
60
+
61
+ ```yaml
62
+ ---
63
+ name: my-skill
64
+ description: What this skill teaches
65
+ metadata:
66
+ openclaw:
67
+ requires:
68
+ bins: ["gh"]
69
+ ---
70
+ ```
71
+
72
+ ## When to Use Skills
73
+
74
+ - **Before using an unfamiliar tool**: Load its skill to understand parameters, patterns, and best practices.
75
+ - **When stuck on a task**: Search for skills related to what you're trying to accomplish.
76
+ - **At the start of a session**: List skills to understand what documentation is available.
77
+
78
+ ## Tips
79
+
80
+ - Skills are read-only reference material. They don't execute anything.
81
+ - Load the relevant tool skill before attempting complex operations with that tool.
82
+ - If a skill doesn't exist for what you need, you can still use the tool directly -- skills are guides, not gates.
83
+ - User-created skills in `data/skills/` take the same format as built-in ones.
@@ -1,19 +1,13 @@
1
1
  'use client'
2
2
 
3
- import { useEffect, useState } from 'react'
3
+ import { useEffect } from 'react'
4
4
  import { useParams } from 'next/navigation'
5
5
  import { useAppStore } from '@/stores/use-app-store'
6
- import { selectActiveSessionId } from '@/stores/slices/session-slice'
7
6
  import { ChatArea } from '@/components/chat/chat-area'
8
- import { CanvasPanel } from '@/components/canvas/canvas-panel'
9
7
 
10
8
  export default function AgentChatPage() {
11
9
  const { id } = useParams<{ id: string }>()
12
10
  const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
13
- const activeSessionId = useAppStore(selectActiveSessionId)
14
- const sessions = useAppStore((s) => s.sessions)
15
- const agents = useAppStore((s) => s.agents)
16
- const [canvasDismissedFor, setCanvasDismissedFor] = useState<string | null>(null)
17
11
 
18
12
  // Sync URL param to store
19
13
  useEffect(() => {
@@ -22,22 +16,11 @@ export default function AgentChatPage() {
22
16
  }
23
17
  }, [id, setCurrentAgent])
24
18
 
25
- const currentSession = activeSessionId ? sessions[activeSessionId] : null
26
- const hasCanvas = !!(currentSession?.canvasContent && canvasDismissedFor !== activeSessionId)
27
- const canvasAgentName = currentSession?.agentId && agents[currentSession.agentId] ? agents[currentSession.agentId].name : undefined
28
-
29
19
  return (
30
20
  <div className="flex-1 flex h-full min-h-0 min-w-0">
31
21
  <div className="flex-1 min-h-0 min-w-0 overflow-hidden">
32
22
  <ChatArea key={id} />
33
23
  </div>
34
- {hasCanvas && activeSessionId && (
35
- <CanvasPanel
36
- sessionId={activeSessionId}
37
- agentName={canvasAgentName}
38
- onClose={() => activeSessionId && setCanvasDismissedFor(activeSessionId)}
39
- />
40
- )}
41
24
  </div>
42
25
  )
43
26
  }
@@ -116,7 +116,6 @@ test('POST /api/agents/[id]/thread reuses an existing thread for a disabled agen
116
116
  file: null,
117
117
  queuedCount: 0,
118
118
  currentRunId: null,
119
- canvasContent: null,
120
119
  }
121
120
  saveSessions(sessions)
122
121
 
@@ -46,11 +46,6 @@ test('GET and POST /api/approvals handle human-loop approvals only', () => {
46
46
  title: 'Approve deploy',
47
47
  data: { question: 'Deploy now?' },
48
48
  })
49
- approvals.requestApproval({
50
- category: 'wallet_action',
51
- title: 'Legacy wallet approval',
52
- data: { action: 'sign_message' },
53
- })
54
49
 
55
50
  const pendingBefore = await route.GET()
56
51
  const pendingBeforeJson = await pendingBefore.json()
@@ -84,43 +79,32 @@ test('GET and POST /api/approvals handle human-loop approvals only', () => {
84
79
  assert.equal(output.storedStatus, 'approved')
85
80
  })
86
81
 
87
- test('POST /api/approvals rejects invalid and non-human-loop approvals', () => {
82
+ test('POST /api/approvals rejects invalid payloads', () => {
88
83
  const output = runWithTempDataDir(`
89
84
  const approvalsMod = await import('./src/lib/server/approvals')
90
85
  const routeMod = await import('./src/app/api/approvals/route')
91
86
  const approvals = approvalsMod.default || approvalsMod
92
87
  const route = routeMod.default || routeMod
93
88
 
94
- const walletApproval = approvals.requestApproval({
95
- category: 'wallet_action',
96
- title: 'Legacy wallet approval',
97
- data: { action: 'sign_message' },
89
+ const humanApproval = approvals.requestApproval({
90
+ category: 'human_loop',
91
+ title: 'Test approval',
92
+ data: { question: 'Proceed?' },
98
93
  })
99
94
 
100
95
  const invalidResponse = await route.POST(new Request('http://local/api/approvals', {
101
96
  method: 'POST',
102
97
  headers: { 'content-type': 'application/json' },
103
- body: JSON.stringify({ id: walletApproval.id }),
98
+ body: JSON.stringify({ id: humanApproval.id }),
104
99
  }))
105
100
  const invalidPayload = await invalidResponse.json()
106
101
 
107
- const wrongCategory = await route.POST(new Request('http://local/api/approvals', {
108
- method: 'POST',
109
- headers: { 'content-type': 'application/json' },
110
- body: JSON.stringify({ id: walletApproval.id, approved: true }),
111
- }))
112
- const wrongCategoryPayload = await wrongCategory.json()
113
-
114
102
  console.log(JSON.stringify({
115
103
  invalidStatus: invalidResponse.status,
116
104
  invalidError: invalidPayload?.error || null,
117
- wrongCategoryStatus: wrongCategory.status,
118
- wrongCategoryError: wrongCategoryPayload?.error || null,
119
105
  }))
120
106
  `)
121
107
 
122
108
  assert.equal(output.invalidStatus, 400)
123
109
  assert.match(String(output.invalidError || ''), /id and approved required/i)
124
- assert.equal(output.wrongCategoryStatus, 400)
125
- assert.match(String(output.wrongCategoryError || ''), /human-loop/i)
126
110
  })
@@ -3,7 +3,13 @@ import { notFound } from '@/lib/server/collection-helpers'
3
3
  import { materializeStreamingAssistantArtifacts } from '@/lib/chat/chat-streaming-state'
4
4
  import { appendSessionNote } from '@/lib/server/session-note'
5
5
  import { getSessionRunState } from '@/lib/server/runtime/session-run-manager'
6
- import { getSession, saveSession } from '@/lib/server/sessions/session-repository'
6
+ import { getSession } from '@/lib/server/sessions/session-repository'
7
+ import {
8
+ appendMessage,
9
+ getMessages,
10
+ replaceAllMessages,
11
+ replaceMessageAt,
12
+ } from '@/lib/server/messages/message-repository'
7
13
  import type { Message } from '@/types'
8
14
  import { safeParseBody } from '@/lib/server/safe-parse-body'
9
15
 
@@ -11,22 +17,21 @@ export async function GET(req: Request, { params }: { params: Promise<{ id: stri
11
17
  const { id } = await params
12
18
  const session = getSession(id)
13
19
  if (!session) return notFound()
14
- session.messages = Array.isArray(session.messages) ? session.messages : []
15
20
 
16
21
  // Use persisted fields plus the run ledger. Process-local execution state is
17
22
  // intentionally excluded here so stale registry entries do not block cleanup.
18
23
  const sessionClaimsActive = session.active === true
19
24
  || (typeof session.currentRunId === 'string' && session.currentRunId.trim().length > 0)
20
25
  || !!getSessionRunState(id).runningRunId
21
- if (!sessionClaimsActive && materializeStreamingAssistantArtifacts(session.messages)) {
22
- saveSession(id, session)
26
+ const allMessages = getMessages(id)
27
+ if (!sessionClaimsActive && materializeStreamingAssistantArtifacts(allMessages)) {
28
+ replaceAllMessages(id, allMessages)
23
29
  }
24
30
 
25
31
  const url = new URL(req.url)
26
32
  const limitParam = url.searchParams.get('limit')
27
33
  const beforeParam = url.searchParams.get('before')
28
34
 
29
- const allMessages = Array.isArray(session.messages) ? session.messages : []
30
35
  const total = allMessages.length
31
36
 
32
37
  // If no limit param, return all messages (backward compatible)
@@ -64,13 +69,12 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
64
69
  const session = getSession(id)
65
70
  if (!session) return notFound()
66
71
 
67
- session.messages.push({
72
+ appendMessage(id, {
68
73
  role: 'user',
69
74
  text: '',
70
75
  kind: 'context-clear',
71
76
  time: Date.now(),
72
77
  })
73
- saveSession(id, session)
74
78
  return NextResponse.json({ ok: true })
75
79
  }
76
80
 
@@ -96,37 +100,37 @@ export async function PUT(req: Request, { params }: { params: Promise<{ id: stri
96
100
  const { id } = await params
97
101
  const { data: body, error } = await safeParseBody<{ messageIndex: number; bookmarked: boolean }>(req)
98
102
  if (error) return error
99
- const session = getSession(id)
100
- if (!session) return notFound()
103
+ if (!getSession(id)) return notFound()
101
104
 
102
105
  const { messageIndex, bookmarked } = body
103
- if (typeof messageIndex !== 'number' || messageIndex < 0 || messageIndex >= session.messages.length) {
106
+ const messages = getMessages(id)
107
+ if (typeof messageIndex !== 'number' || messageIndex < 0 || messageIndex >= messages.length) {
104
108
  return NextResponse.json({ error: 'Invalid message index' }, { status: 400 })
105
109
  }
106
110
 
107
- session.messages[messageIndex].bookmarked = bookmarked
108
- saveSession(id, session)
109
- return NextResponse.json(session.messages[messageIndex])
111
+ const updated = { ...messages[messageIndex], bookmarked }
112
+ replaceMessageAt(id, messageIndex, updated)
113
+ return NextResponse.json(updated)
110
114
  }
111
115
 
112
116
  export async function DELETE(req: Request, { params }: { params: Promise<{ id: string }> }) {
113
117
  const { id } = await params
114
118
  const { data: body, error } = await safeParseBody<{ messageIndex: number }>(req)
115
119
  if (error) return error
116
- const session = getSession(id)
117
- if (!session) return notFound()
120
+ if (!getSession(id)) return notFound()
118
121
 
119
122
  const { messageIndex } = body
120
- if (typeof messageIndex !== 'number' || messageIndex < 0 || messageIndex >= session.messages.length) {
123
+ const messages = getMessages(id)
124
+ if (typeof messageIndex !== 'number' || messageIndex < 0 || messageIndex >= messages.length) {
121
125
  return NextResponse.json({ error: 'Invalid message index' }, { status: 400 })
122
126
  }
123
127
 
124
128
  // Only allow deleting context-clear markers (safety guard)
125
- if (session.messages[messageIndex].kind !== 'context-clear') {
129
+ if (messages[messageIndex].kind !== 'context-clear') {
126
130
  return NextResponse.json({ error: 'Only context-clear markers can be removed' }, { status: 400 })
127
131
  }
128
132
 
129
- session.messages.splice(messageIndex, 1)
130
- saveSession(id, session)
133
+ messages.splice(messageIndex, 1)
134
+ replaceAllMessages(id, messages)
131
135
  return NextResponse.json({ ok: true })
132
136
  }