@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,119 @@
1
+ import { genId } from '@/lib/id'
2
+ import { loadWallets, loadWallet, saveWallet, deleteWallet } from './wallet-repository'
3
+ import { generateEthereumWallet, normalizeEthereumAddress } from './wallet-crypto'
4
+ import { logActivity } from '@/lib/server/activity/activity-log'
5
+ import { loadAgent } from '@/lib/server/agents/agent-repository'
6
+ import type { AgentWallet, SafeWallet } from '@/types/swarmdock'
7
+
8
+ export class WalletServiceError extends Error {
9
+ status: number
10
+
11
+ constructor(status: number, message: string) {
12
+ super(message)
13
+ this.name = 'WalletServiceError'
14
+ this.status = status
15
+ }
16
+ }
17
+
18
+ function stripPrivateKey(wallet: AgentWallet): SafeWallet {
19
+ const { encryptedPrivateKey: _, ...safe } = wallet
20
+ return safe
21
+ }
22
+
23
+ function requireAgent(agentId: string): string {
24
+ const normalizedAgentId = agentId.trim()
25
+ if (!normalizedAgentId) {
26
+ throw new WalletServiceError(400, 'agentId is required')
27
+ }
28
+ if (!loadAgent(normalizedAgentId)) {
29
+ throw new WalletServiceError(404, `Agent not found: ${normalizedAgentId}`)
30
+ }
31
+ return normalizedAgentId
32
+ }
33
+
34
+ async function requireWalletAddress(walletAddress: string): Promise<string> {
35
+ const normalizedAddress = walletAddress.trim()
36
+ if (!normalizedAddress) {
37
+ throw new WalletServiceError(400, 'walletAddress is required')
38
+ }
39
+ const checksumAddress = await normalizeEthereumAddress(normalizedAddress)
40
+ if (!checksumAddress) {
41
+ throw new WalletServiceError(400, 'walletAddress must be a valid Base/Ethereum address')
42
+ }
43
+ return checksumAddress
44
+ }
45
+
46
+ export function listWalletsSafe(): Record<string, SafeWallet> {
47
+ const wallets = loadWallets()
48
+ const safe: Record<string, SafeWallet> = {}
49
+ for (const [id, w] of Object.entries(wallets)) {
50
+ safe[id] = stripPrivateKey(w)
51
+ }
52
+ return safe
53
+ }
54
+
55
+ export function getWalletSafe(id: string): SafeWallet | null {
56
+ const wallet = loadWallet(id)
57
+ return wallet ? stripPrivateKey(wallet) : null
58
+ }
59
+
60
+ /** Generate a new Base L2 Ethereum wallet with encrypted private key storage. */
61
+ export async function generateWallet(params: { agentId: string; label?: string }): Promise<SafeWallet> {
62
+ const agentId = requireAgent(params.agentId)
63
+ const { address, encryptedPrivateKey } = await generateEthereumWallet()
64
+ const id = genId()
65
+ const wallet: AgentWallet = {
66
+ id,
67
+ agentId,
68
+ walletAddress: address,
69
+ chain: 'base',
70
+ label: params.label || 'Base L2 Wallet',
71
+ encryptedPrivateKey,
72
+ requireApproval: true,
73
+ createdAt: Date.now(),
74
+ }
75
+ saveWallet(id, wallet)
76
+ logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet generated: ${address}` })
77
+ return stripPrivateKey(wallet)
78
+ }
79
+
80
+ /** Create a wallet from an existing address (no key generation). */
81
+ export async function createWallet(params: { agentId: string; walletAddress: string; label?: string }): Promise<SafeWallet> {
82
+ const agentId = requireAgent(params.agentId)
83
+ const walletAddress = await requireWalletAddress(params.walletAddress)
84
+ const id = genId()
85
+ const wallet: AgentWallet = {
86
+ id,
87
+ agentId,
88
+ walletAddress,
89
+ chain: 'base',
90
+ label: params.label,
91
+ createdAt: Date.now(),
92
+ }
93
+ saveWallet(id, wallet)
94
+ logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet created: ${walletAddress}` })
95
+ return stripPrivateKey(wallet)
96
+ }
97
+
98
+ /** Update wallet settings (label, limits, approval). */
99
+ export function updateWallet(
100
+ id: string,
101
+ patch: Partial<Pick<AgentWallet, 'label' | 'spendingLimitUsdc' | 'dailyLimitUsdc' | 'requireApproval'>>,
102
+ ): SafeWallet | null {
103
+ const wallet = loadWallet(id)
104
+ if (!wallet) return null
105
+ if (patch.label !== undefined) wallet.label = patch.label
106
+ if (patch.spendingLimitUsdc !== undefined) wallet.spendingLimitUsdc = patch.spendingLimitUsdc
107
+ if (patch.dailyLimitUsdc !== undefined) wallet.dailyLimitUsdc = patch.dailyLimitUsdc
108
+ if (patch.requireApproval !== undefined) wallet.requireApproval = patch.requireApproval
109
+ saveWallet(id, wallet)
110
+ return stripPrivateKey(wallet)
111
+ }
112
+
113
+ export function removeWallet(id: string): boolean {
114
+ const wallet = loadWallet(id)
115
+ if (!wallet) return false
116
+ deleteWallet(id)
117
+ logActivity({ entityType: 'wallet', entityId: id, action: 'deleted', actor: 'user', summary: `Wallet deleted: ${wallet.walletAddress}` })
118
+ return true
119
+ }
@@ -22,7 +22,6 @@ import type {
22
22
  import {
23
23
  EXTRACTION_TIMEOUT_MS,
24
24
  WorkingStatePatchSchema,
25
- missionStatusToWorkingStateStatus,
26
25
  normalizeEvidenceIds,
27
26
  now,
28
27
  } from '@/lib/server/working-state/normalization'
@@ -268,9 +267,9 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
268
267
  'You maintain a structured working-state object for an autonomous agent.',
269
268
  'Return JSON only.',
270
269
  '',
271
- 'Update the state using only evidence from the latest turn, tool results, and mission snapshot.',
270
+ 'Update the state using only evidence from the latest turn and tool results.',
272
271
  'Rules:',
273
- '- Facts must be confirmed by explicit user text, mission state, or tool evidence. Do not turn guesses into facts.',
272
+ '- Facts must be confirmed by explicit user text or tool evidence. Do not turn guesses into facts.',
274
273
  '- Put uncertain leads into hypotheses, not facts.',
275
274
  '- Use blockers for approvals, credentials, human input, external waits, and explicit execution failures.',
276
275
  '- nextAction must be one concrete immediate action, not a broad plan.',
@@ -288,7 +287,7 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
288
287
  status: 'idle|progress|blocked|waiting|completed',
289
288
  nextAction: 'optional',
290
289
  planSteps: [{ id: 'optional', text: 'step', status: 'active|resolved|superseded' }],
291
- factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|mission|system', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
290
+ factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|system', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
292
291
  artifactsUpsert: [{ id: 'optional', label: 'artifact', kind: 'file|url|approval|message|other', path: 'optional', url: 'optional', sourceTool: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
293
292
  decisionsAppend: [{ summary: 'decision', rationale: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
294
293
  blockersUpsert: [{ summary: 'blocker', kind: 'approval|credential|human_input|external_dependency|error|other', nextAction: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
@@ -298,21 +297,6 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
298
297
  }),
299
298
  '',
300
299
  `source: ${JSON.stringify(cleanText(input.source, 80) || 'chat')}`,
301
- `mission: ${JSON.stringify(input.mission ? {
302
- id: input.mission.id,
303
- objective: cleanMultiline(input.mission.objective, 600),
304
- status: input.mission.status,
305
- phase: input.mission.phase,
306
- currentStep: cleanText(input.mission.currentStep, 240) || null,
307
- plannerSummary: cleanText(input.mission.plannerSummary, 280) || null,
308
- verifierSummary: cleanText(input.mission.verifierSummary, 280) || null,
309
- blockerSummary: cleanText(input.mission.blockerSummary, 240) || null,
310
- waitState: input.mission.waitState ? {
311
- kind: input.mission.waitState.kind,
312
- reason: cleanText(input.mission.waitState.reason, 240),
313
- approvalId: cleanText(input.mission.waitState.approvalId, 120) || null,
314
- } : null,
315
- } : null)}`,
316
300
  `current_state:\n${renderStateForExtraction(input.currentState)}`,
317
301
  `user_message: ${JSON.stringify(cleanMultiline(input.message, 1200) || null)}`,
318
302
  `assistant_text: ${JSON.stringify(cleanMultiline(input.assistantText, 1200) || null)}`,
@@ -398,7 +382,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
398
382
  value: input.runId,
399
383
  runId: input.runId,
400
384
  sessionId: input.sessionId,
401
- missionId: input.mission?.id || null,
402
385
  createdAt: nowTs,
403
386
  })
404
387
  }
@@ -420,7 +403,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
420
403
  toolCallId: cleanText(event.toolCallId, 120) || null,
421
404
  runId: input.runId || null,
422
405
  sessionId: input.sessionId,
423
- missionId: input.mission?.id || null,
424
406
  createdAt: nowTs + index,
425
407
  })
426
408
 
@@ -428,7 +410,7 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
428
410
  blockersUpsert.push({
429
411
  summary: output || `Tool ${toolName} failed.`,
430
412
  kind: 'error',
431
- nextAction: cleanText(input.mission?.currentStep, 240) || null,
413
+ nextAction: null,
432
414
  status: 'active',
433
415
  evidenceIds: [evidenceId],
434
416
  })
@@ -521,7 +503,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
521
503
  value: cleanText(input.error, 240) || null,
522
504
  runId: input.runId || null,
523
505
  sessionId: input.sessionId,
524
- missionId: input.mission?.id || null,
525
506
  createdAt: nowTs + 100,
526
507
  })
527
508
  blockersUpsert.push({
@@ -531,26 +512,11 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
531
512
  })
532
513
  }
533
514
 
534
- if (input.mission) {
535
- evidenceAppend.push({
536
- id: genId(12),
537
- type: 'mission',
538
- summary: `Mission state updated: ${input.mission.status}/${input.mission.phase}.`,
539
- value: cleanText(input.mission.currentStep || input.mission.objective, 240) || null,
540
- runId: input.runId || null,
541
- sessionId: input.sessionId,
542
- missionId: input.mission.id,
543
- createdAt: nowTs + 200,
544
- })
545
- }
546
-
547
515
  return {
548
516
  status: input.error
549
517
  ? 'blocked'
550
- : input.mission
551
- ? missionStatusToWorkingStateStatus(input.mission)
552
- : undefined,
553
- nextAction: cleanText(input.mission?.currentStep, 240) || undefined,
518
+ : undefined,
519
+ nextAction: undefined,
554
520
  factsUpsert: factsUpsert.length > 0 ? factsUpsert : undefined,
555
521
  artifactsUpsert: artifactsUpsert.length > 0 ? artifactsUpsert : undefined,
556
522
  blockersUpsert: blockersUpsert.length > 0 ? blockersUpsert : undefined,
@@ -608,7 +574,7 @@ export function shouldExtractStructuredPatch(input: SynchronizeWorkingStateForTu
608
574
  const hasAssistantText = cleanMultiline(input.assistantText, 400).length > 0
609
575
  const hasError = cleanText(input.error, 120).length > 0
610
576
  if (cleanText(input.source, 80) === 'heartbeat') {
611
- return hasToolEvents || hasError || Boolean(input.mission)
577
+ return hasToolEvents || hasError
612
578
  }
613
- return hasToolEvents || hasAssistantText || hasMessage || hasError || Boolean(input.mission)
579
+ return hasToolEvents || hasAssistantText || hasMessage || hasError
614
580
  }
@@ -4,7 +4,6 @@ import { genId } from '@/lib/id'
4
4
  import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
5
5
  import type {
6
6
  EvidenceRef,
7
- Mission,
8
7
  SessionWorkingState,
9
8
  WorkingArtifact,
10
9
  WorkingArtifactPatch,
@@ -56,7 +55,7 @@ export const WorkingPlanStepPatchSchema = z.object({
56
55
  export const WorkingFactPatchSchema = z.object({
57
56
  id: z.string().optional().nullable(),
58
57
  statement: z.string().optional().nullable(),
59
- source: z.enum(['user', 'tool', 'assistant', 'mission', 'system']).optional().nullable(),
58
+ source: z.enum(['user', 'tool', 'assistant', 'system']).optional().nullable(),
60
59
  status: WorkingItemStatusSchema.optional().nullable(),
61
60
  evidenceIds: z.array(z.string()).optional().nullable(),
62
61
  })
@@ -150,7 +149,6 @@ import type { MessageToolEvent } from '@/types'
150
149
 
151
150
  export interface WorkingStateDeterministicUpdateInput {
152
151
  sessionId: string
153
- mission?: Mission | null
154
152
  message?: string | null
155
153
  assistantText?: string | null
156
154
  error?: string | null
@@ -233,7 +231,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
233
231
  if (!summary) return null
234
232
  const type = record.type === 'tool'
235
233
  || record.type === 'message'
236
- || record.type === 'mission'
237
234
  || record.type === 'task'
238
235
  || record.type === 'artifact'
239
236
  || record.type === 'error'
@@ -249,7 +246,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
249
246
  toolCallId: cleanText(record.toolCallId, 120) || null,
250
247
  runId: cleanText(record.runId, 120) || null,
251
248
  sessionId: cleanText(record.sessionId, 120) || null,
252
- missionId: cleanText(record.missionId, 120) || null,
253
249
  taskId: cleanText(record.taskId, 120) || null,
254
250
  createdAt: typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
255
251
  ? Math.trunc(record.createdAt)
@@ -290,7 +286,6 @@ export function normalizeFact(input: unknown): WorkingFact | null {
290
286
  source: record.source === 'user'
291
287
  || record.source === 'tool'
292
288
  || record.source === 'assistant'
293
- || record.source === 'mission'
294
289
  || record.source === 'system'
295
290
  ? record.source
296
291
  : 'assistant',
@@ -434,17 +429,16 @@ export function normalizeMatchKey(value: string): string {
434
429
  // defaultWorkingState & normalizeWorkingState
435
430
  // ---------------------------------------------------------------------------
436
431
 
437
- export function defaultWorkingState(sessionId: string, mission?: Mission | null): SessionWorkingState {
432
+ export function defaultWorkingState(sessionId: string): SessionWorkingState {
438
433
  const nowTs = now()
439
434
  return {
440
435
  sessionId,
441
- missionId: mission?.id || null,
442
- objective: cleanMultiline(mission?.objective, 900) || null,
443
- summary: cleanMultiline(mission?.verifierSummary || mission?.plannerSummary, 600) || null,
436
+ objective: null,
437
+ summary: null,
444
438
  constraints: [],
445
- successCriteria: normalizeList(mission?.successCriteria, 12, 240),
446
- status: mission ? missionStatusToWorkingStateStatus(mission) : 'idle',
447
- nextAction: cleanText(mission?.currentStep, 240) || null,
439
+ successCriteria: [],
440
+ status: 'idle',
441
+ nextAction: null,
448
442
  planSteps: [],
449
443
  confirmedFacts: [],
450
444
  artifacts: [],
@@ -462,19 +456,17 @@ export function defaultWorkingState(sessionId: string, mission?: Mission | null)
462
456
  export function normalizeWorkingState(
463
457
  input: unknown,
464
458
  sessionId: string,
465
- mission?: Mission | null,
466
459
  ): SessionWorkingState {
467
460
  if (!input || typeof input !== 'object' || Array.isArray(input)) {
468
- return defaultWorkingState(sessionId, mission)
461
+ return defaultWorkingState(sessionId)
469
462
  }
470
463
  const record = input as Record<string, unknown>
471
- const base = defaultWorkingState(sessionId, mission)
464
+ const base = defaultWorkingState(sessionId)
472
465
  const createdAt = typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
473
466
  ? Math.trunc(record.createdAt)
474
467
  : base.createdAt
475
468
  const normalized: SessionWorkingState = {
476
469
  sessionId: cleanText(record.sessionId, 120) || sessionId,
477
- missionId: cleanText(record.missionId, 120) || mission?.id || null,
478
470
  objective: cleanMultiline(record.objective, 900) || base.objective,
479
471
  summary: cleanMultiline(record.summary, 600) || base.summary,
480
472
  constraints: normalizeList(record.constraints, 12, 240),
@@ -497,7 +489,7 @@ export function normalizeWorkingState(
497
489
  ? Math.trunc(record.lastCompactedAt)
498
490
  : null,
499
491
  }
500
- return compactWorkingStateObject(syncWorkingStateWithMission(normalized, mission))
492
+ return compactWorkingStateObject(normalized)
501
493
  }
502
494
 
503
495
  // ---------------------------------------------------------------------------
@@ -522,89 +514,6 @@ export function compactWorkingStateObject(state: SessionWorkingState): SessionWo
522
514
  }
523
515
 
524
516
  // ---------------------------------------------------------------------------
525
- // missionStatusToWorkingStateStatus & syncWorkingStateWithMission
526
- // ---------------------------------------------------------------------------
527
-
528
- export function missionStatusToWorkingStateStatus(mission: Mission): WorkingStateStatus {
529
- if (mission.status === 'completed') return 'completed'
530
- if (mission.status === 'waiting') return 'waiting'
531
- if (mission.status === 'failed' || mission.status === 'cancelled') return 'blocked'
532
- return 'progress'
533
- }
534
-
535
- export function syncWorkingStateWithMission(
536
- state: SessionWorkingState,
537
- mission?: Mission | null,
538
- ): SessionWorkingState {
539
- if (!mission) return state
540
- const next = { ...state }
541
- next.missionId = mission.id
542
- next.objective = cleanMultiline(mission.objective, 900) || next.objective
543
- next.successCriteria = normalizeList(mission.successCriteria, 12, 240)
544
- next.summary = next.summary || cleanMultiline(mission.verifierSummary || mission.plannerSummary, 600) || null
545
- const missionStatus = missionStatusToWorkingStateStatus(mission)
546
- if (missionStatus === 'completed' || missionStatus === 'waiting' || missionStatus === 'blocked') {
547
- next.status = missionStatus
548
- } else if (next.status === 'idle') {
549
- next.status = missionStatus
550
- }
551
- next.nextAction = next.nextAction || cleanText(mission.currentStep, 240) || null
552
-
553
- if (mission.currentStep) {
554
- next.planSteps = upsertItems(next.planSteps, [{
555
- id: null,
556
- text: mission.currentStep,
557
- status: mission.status === 'completed' ? 'resolved' : 'active',
558
- } satisfies WorkingPlanStepPatch], {
559
- max: MAX_PLAN_STEPS,
560
- getPatchId: (patch) => cleanText(patch.id, 120) || null,
561
- getPatchKey: (patch) => cleanText(patch.text, 240),
562
- getItemKey: (item) => item.text,
563
- create: (patch, nowTs) => ({
564
- id: genId(12),
565
- text: cleanText(patch.text, 240),
566
- status: normalizeItemStatus(patch.status),
567
- createdAt: nowTs,
568
- updatedAt: nowTs,
569
- }),
570
- merge: (current, patch, nowTs) => ({
571
- ...current,
572
- text: cleanText(patch.text, 240) || current.text,
573
- status: normalizeItemStatus(patch.status, current.status),
574
- updatedAt: nowTs,
575
- }),
576
- compact: compactPlanSteps,
577
- })
578
- }
579
-
580
- if (mission.waitState?.reason || mission.blockerSummary) {
581
- const blockerSummary = cleanText(mission.waitState?.reason || mission.blockerSummary, 280)
582
- if (blockerSummary) {
583
- next.blockers = upsertItems(next.blockers, [{
584
- summary: blockerSummary,
585
- kind: mission.waitState?.kind === 'approval'
586
- ? 'approval'
587
- : mission.waitState?.kind === 'human_reply'
588
- ? 'human_input'
589
- : mission.waitState?.kind === 'external_dependency' || mission.waitState?.kind === 'provider'
590
- ? 'external_dependency'
591
- : mission.status === 'failed'
592
- ? 'error'
593
- : 'other',
594
- nextAction: mission.currentStep || null,
595
- status: mission.status === 'completed' ? 'resolved' : 'active',
596
- }], blockerUpsertConfig())
597
- }
598
- }
599
-
600
- if (mission.status === 'completed') {
601
- next.blockers = next.blockers.map((blocker) => blocker.status === 'active'
602
- ? { ...blocker, status: 'resolved', updatedAt: now() }
603
- : blocker)
604
- }
605
-
606
- return next
607
- }
608
517
 
609
518
  // ---------------------------------------------------------------------------
610
519
  // upsertItems & upsertConfig factories
@@ -647,7 +556,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
647
556
  source: patch.source === 'user'
648
557
  || patch.source === 'tool'
649
558
  || patch.source === 'assistant'
650
- || patch.source === 'mission'
651
559
  || patch.source === 'system'
652
560
  ? patch.source
653
561
  : 'assistant',
@@ -662,7 +570,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
662
570
  source: patch.source === 'user'
663
571
  || patch.source === 'tool'
664
572
  || patch.source === 'assistant'
665
- || patch.source === 'mission'
666
573
  || patch.source === 'system'
667
574
  ? patch.source
668
575
  : current.source,
@@ -1,7 +1,6 @@
1
1
  import { genId } from '@/lib/id'
2
2
  import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
3
3
  import type {
4
- Mission,
5
4
  SessionWorkingState,
6
5
  WorkingBlocker,
7
6
  WorkingPlanStepPatch,
@@ -20,7 +19,6 @@ import {
20
19
  normalizeWorkingState,
21
20
  defaultWorkingState,
22
21
  compactWorkingStateObject,
23
- syncWorkingStateWithMission,
24
22
  normalizeItemStatus,
25
23
  normalizeStateStatus,
26
24
  upsertItems,
@@ -96,8 +94,6 @@ export {
96
94
  compactPlanSteps,
97
95
  defaultWorkingState,
98
96
  compactWorkingStateObject,
99
- missionStatusToWorkingStateStatus,
100
- syncWorkingStateWithMission,
101
97
  // Upsert
102
98
  upsertItems,
103
99
  factUpsertConfig,
@@ -142,14 +138,14 @@ export { buildWorkingStatePromptBlockFromState } from '@/lib/server/working-stat
142
138
  // CRUD / coordination layer
143
139
  // ---------------------------------------------------------------------------
144
140
 
145
- export function loadSessionWorkingState(sessionId: string, options?: { mission?: Mission | null }): SessionWorkingState | null {
141
+ export function loadSessionWorkingState(sessionId: string): SessionWorkingState | null {
146
142
  const stored = loadPersistedWorkingState(sessionId)
147
- if (!stored && !options?.mission) return null
148
- return normalizeWorkingState(stored, sessionId, options?.mission || null)
143
+ if (!stored) return null
144
+ return normalizeWorkingState(stored, sessionId)
149
145
  }
150
146
 
151
- export function getOrCreateSessionWorkingState(sessionId: string, options?: { mission?: Mission | null }): SessionWorkingState {
152
- return loadSessionWorkingState(sessionId, options) || defaultWorkingState(sessionId, options?.mission || null)
147
+ export function getOrCreateSessionWorkingState(sessionId: string): SessionWorkingState {
148
+ return loadSessionWorkingState(sessionId) || defaultWorkingState(sessionId)
153
149
  }
154
150
 
155
151
  export function saveSessionWorkingState(state: SessionWorkingState): SessionWorkingState {
@@ -165,12 +161,10 @@ export function deleteSessionWorkingState(sessionId: string): void {
165
161
  export function applyWorkingStatePatch(
166
162
  sessionId: string,
167
163
  patch: WorkingStatePatch,
168
- options?: { mission?: Mission | null },
169
164
  ): SessionWorkingState {
170
- const current = getOrCreateSessionWorkingState(sessionId, options)
165
+ const current = getOrCreateSessionWorkingState(sessionId)
171
166
  const next: SessionWorkingState = {
172
167
  ...current,
173
- missionId: options?.mission?.id || current.missionId || null,
174
168
  objective: patch.objective !== undefined ? (cleanMultiline(patch.objective, 900) || null) : current.objective,
175
169
  summary: patch.summary !== undefined ? (cleanMultiline(patch.summary, 600) || null) : current.summary,
176
170
  constraints: patch.constraints !== undefined ? normalizeList(patch.constraints, 12, 240) : current.constraints,
@@ -215,16 +209,15 @@ export function applyWorkingStatePatch(
215
209
  next.openQuestions = markSuperseded(next.openQuestions, patch.supersedeIds)
216
210
  next.hypotheses = markSuperseded(next.hypotheses, patch.supersedeIds)
217
211
 
218
- const synced = compactWorkingStateObject(syncWorkingStateWithMission(next, options?.mission || null))
219
- upsertPersistedWorkingState(sessionId, synced as unknown as Record<string, unknown>)
220
- return synced
212
+ const compacted = compactWorkingStateObject(next)
213
+ upsertPersistedWorkingState(sessionId, compacted as unknown as Record<string, unknown>)
214
+ return compacted
221
215
  }
222
216
 
223
217
  export function recordWorkingStateEvidence(input: WorkingStateDeterministicUpdateInput): SessionWorkingState {
224
218
  return applyWorkingStatePatch(
225
219
  input.sessionId,
226
220
  deterministicEvidencePatch(input),
227
- { mission: input.mission || null },
228
221
  )
229
222
  }
230
223
 
@@ -241,12 +234,11 @@ export async function synchronizeWorkingStateForTurn(
241
234
  currentState: deterministic,
242
235
  }, options)
243
236
  if (!patch) return deterministic
244
- return applyWorkingStatePatch(input.sessionId, patch, { mission: input.mission || null })
237
+ return applyWorkingStatePatch(input.sessionId, patch)
245
238
  }
246
239
 
247
240
  export function syncWorkingStateFromMainLoopState(input: {
248
241
  sessionId: string
249
- mission?: Mission | null
250
242
  goal?: string | null
251
243
  summary?: string | null
252
244
  status?: WorkingStateStatus | null
@@ -281,13 +273,12 @@ export function syncWorkingStateFromMainLoopState(input: {
281
273
  status: (input.status === 'completed' ? 'resolved' : 'active') as WorkingStateItemStatus,
282
274
  })).filter((fact) => fact.statement)
283
275
  : undefined,
284
- }, { mission: input.mission || null })
276
+ })
285
277
  }
286
278
 
287
279
  export function buildWorkingStatePromptBlock(
288
280
  sessionId: string,
289
- options?: { mission?: Mission | null },
290
281
  ): string {
291
- const state = loadSessionWorkingState(sessionId, options)
282
+ const state = loadSessionWorkingState(sessionId)
292
283
  return buildWorkingStatePromptBlockFromState(state)
293
284
  }
@@ -204,6 +204,7 @@ export const SETUP_PROVIDERS: SetupProviderOption[] = [
204
204
  export const STARTER_AGENT_TOOLS = [
205
205
  'memory',
206
206
  'files',
207
+ 'execute',
207
208
  'web_search',
208
209
  'web_fetch',
209
210
  'browser',
@@ -363,6 +364,7 @@ export interface StarterKit {
363
364
  const PERSONAL_AGENT_TOOLS = [
364
365
  'memory',
365
366
  'files',
367
+ 'execute',
366
368
  'web_search',
367
369
  'web_fetch',
368
370
  'browser',
@@ -374,6 +376,7 @@ const PERSONAL_AGENT_TOOLS = [
374
376
  const RESEARCH_AGENT_TOOLS = [
375
377
  'memory',
376
378
  'files',
379
+ 'execute',
377
380
  'web_search',
378
381
  'web_fetch',
379
382
  'browser',
@@ -384,6 +387,7 @@ const RESEARCH_AGENT_TOOLS = [
384
387
  const BUILDER_AGENT_TOOLS = [
385
388
  'memory',
386
389
  'files',
390
+ 'execute',
387
391
  'web_search',
388
392
  'web_fetch',
389
393
  'browser',
@@ -397,6 +401,7 @@ const OPERATOR_AGENT_TOOLS = STARTER_AGENT_TOOLS
397
401
  const OPENCLAW_AGENT_TOOLS = [
398
402
  'memory',
399
403
  'files',
404
+ 'execute',
400
405
  'web_search',
401
406
  'web_fetch',
402
407
  'browser',
@@ -31,7 +31,7 @@ describe('stripInternalJson', () => {
31
31
  })
32
32
 
33
33
  it('removes JSON with nested objects when internal keys are present', () => {
34
- const input = '{ "walletIntent": "send", "details": { "amount": 100 } }'
34
+ const input = '{ "isDeliverableTask": true, "details": { "amount": 100 } }'
35
35
  assert.equal(stripInternalJson(input).trim(), '')
36
36
  })
37
37
 
@@ -15,7 +15,7 @@
15
15
  // ---------------------------------------------------------------------------
16
16
 
17
17
  const INTERNAL_JSON_KEYS = [
18
- 'isDeliverableTask', 'quality_score', 'isBroadGoal', 'walletIntent',
18
+ 'isDeliverableTask', 'quality_score', 'isBroadGoal',
19
19
  'hasHumanSignals', 'explicitToolRequests', 'isResearchSynthesis', 'confidence',
20
20
  ]
21
21
 
@@ -16,13 +16,13 @@ export interface ToolDefinition {
16
16
  */
17
17
  export const AVAILABLE_TOOLS: ToolDefinition[] = [
18
18
  { id: 'shell', label: 'Shell', description: 'Execute commands in the working directory and manage background processes' },
19
+ { id: 'execute', label: 'Execute', description: 'Run sandboxed bash scripts with just-bash, with optional host execution when explicitly enabled' },
19
20
  { id: 'files', label: 'Files', description: 'Complete file management: read, write, list, move, copy, delete, and send' },
20
21
  { id: 'edit_file', label: 'Edit File', description: 'Surgical search-and-replace within files' },
21
22
  { id: 'web', label: 'Web', description: 'Search the web, fetch content, and make HTTP API calls' },
22
23
  { id: 'delegate', label: 'Delegate', description: 'Delegate complex tasks to specialized backends (Claude Code, Codex, OpenCode)' },
23
24
  { id: 'browser', label: 'Browser', description: 'Playwright — browse, scrape, interact with web pages' },
24
25
  { id: 'memory', label: 'Memory', description: 'Store and retrieve long-term memories across conversations' },
25
- { id: 'wallet', label: 'Wallet', description: 'Manage agent crypto wallet — check balance, send SOL, view transactions', extensionId: 'wallet' },
26
26
  { id: 'monitor', label: 'Monitor', description: 'Durable watch jobs: monitor files, endpoints, tasks, and resume agents on triggers' },
27
27
  { id: 'extension_creator', label: 'Extension Creator', description: 'Design focused extensions for durable capabilities and recurring automations' },
28
28
  { id: 'image_gen', label: 'Image Generation', description: 'Generate images from text prompts using OpenAI, Stability AI, Replicate, fal.ai, and more', extensionId: 'image_gen' },
@@ -57,4 +57,20 @@ describe('AgentCreateSchema', () => {
57
57
  assert.equal(parsed.orchestratorMaxCyclesPerDay, 12)
58
58
  assert.equal(parsed.sessionResetMode, 'isolated')
59
59
  })
60
+
61
+ it('accepts executeConfig for sandboxed execute defaults', () => {
62
+ const parsed = AgentCreateSchema.parse({
63
+ name: 'Builder',
64
+ provider: 'openai',
65
+ executeConfig: {
66
+ backend: 'sandbox',
67
+ network: { enabled: true },
68
+ timeout: 45,
69
+ },
70
+ })
71
+
72
+ assert.equal(parsed.executeConfig?.backend, 'sandbox')
73
+ assert.equal(parsed.executeConfig?.network?.enabled, true)
74
+ assert.equal(parsed.executeConfig?.timeout, 45)
75
+ })
60
76
  })