@swarmclawai/swarmclaw 0.6.7 → 0.7.0

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 (203) hide show
  1. package/README.md +82 -39
  2. package/next.config.ts +31 -6
  3. package/package.json +3 -2
  4. package/src/app/api/agents/[id]/thread/route.ts +1 -0
  5. package/src/app/api/agents/route.ts +19 -5
  6. package/src/app/api/approvals/route.ts +22 -0
  7. package/src/app/api/chatrooms/[id]/chat/route.ts +4 -0
  8. package/src/app/api/clawhub/install/route.ts +2 -2
  9. package/src/app/api/eval/run/route.ts +37 -0
  10. package/src/app/api/eval/scenarios/route.ts +24 -0
  11. package/src/app/api/eval/suite/route.ts +29 -0
  12. package/src/app/api/mcp-servers/[id]/conformance/route.ts +26 -0
  13. package/src/app/api/mcp-servers/[id]/invoke/route.ts +81 -0
  14. package/src/app/api/memory/graph/route.ts +46 -0
  15. package/src/app/api/memory/route.ts +36 -5
  16. package/src/app/api/notifications/route.ts +3 -0
  17. package/src/app/api/plugins/install/route.ts +57 -5
  18. package/src/app/api/plugins/marketplace/route.ts +73 -22
  19. package/src/app/api/plugins/route.ts +61 -1
  20. package/src/app/api/plugins/ui/route.ts +34 -0
  21. package/src/app/api/sessions/[id]/checkpoints/route.ts +31 -0
  22. package/src/app/api/sessions/[id]/restore/route.ts +36 -0
  23. package/src/app/api/settings/route.ts +62 -0
  24. package/src/app/api/setup/doctor/route.ts +22 -5
  25. package/src/app/api/souls/[id]/route.ts +65 -0
  26. package/src/app/api/souls/route.ts +70 -0
  27. package/src/app/api/tasks/[id]/approve/route.ts +4 -3
  28. package/src/app/api/tasks/[id]/route.ts +16 -3
  29. package/src/app/api/tasks/route.ts +10 -2
  30. package/src/app/api/usage/route.ts +9 -2
  31. package/src/app/globals.css +27 -0
  32. package/src/app/page.tsx +10 -5
  33. package/src/cli/index.js +37 -0
  34. package/src/components/activity/activity-feed.tsx +9 -2
  35. package/src/components/agents/agent-avatar.tsx +5 -1
  36. package/src/components/agents/agent-card.tsx +55 -9
  37. package/src/components/agents/agent-sheet.tsx +112 -34
  38. package/src/components/agents/inspector-panel.tsx +1 -1
  39. package/src/components/agents/soul-library-picker.tsx +84 -13
  40. package/src/components/auth/access-key-gate.tsx +63 -54
  41. package/src/components/auth/user-picker.tsx +37 -32
  42. package/src/components/chat/activity-moment.tsx +2 -0
  43. package/src/components/chat/chat-area.tsx +11 -0
  44. package/src/components/chat/chat-header.tsx +69 -25
  45. package/src/components/chat/chat-tool-toggles.tsx +2 -2
  46. package/src/components/chat/checkpoint-timeline.tsx +112 -0
  47. package/src/components/chat/code-block.tsx +3 -1
  48. package/src/components/chat/exec-approval-card.tsx +8 -1
  49. package/src/components/chat/message-bubble.tsx +164 -4
  50. package/src/components/chat/message-list.tsx +46 -4
  51. package/src/components/chat/session-approval-card.tsx +80 -0
  52. package/src/components/chat/session-debug-panel.tsx +106 -84
  53. package/src/components/chat/streaming-bubble.tsx +6 -5
  54. package/src/components/chat/task-approval-card.tsx +78 -0
  55. package/src/components/chat/thinking-indicator.tsx +48 -12
  56. package/src/components/chat/tool-call-bubble.tsx +3 -0
  57. package/src/components/chat/tool-request-banner.tsx +39 -20
  58. package/src/components/chatrooms/chatroom-list.tsx +11 -4
  59. package/src/components/chatrooms/chatroom-sheet.tsx +7 -2
  60. package/src/components/connectors/connector-list.tsx +33 -11
  61. package/src/components/connectors/connector-sheet.tsx +37 -7
  62. package/src/components/home/home-view.tsx +54 -24
  63. package/src/components/input/chat-input.tsx +22 -1
  64. package/src/components/knowledge/knowledge-list.tsx +17 -18
  65. package/src/components/knowledge/knowledge-sheet.tsx +9 -5
  66. package/src/components/layout/app-layout.tsx +87 -19
  67. package/src/components/mcp-servers/mcp-server-list.tsx +352 -50
  68. package/src/components/mcp-servers/mcp-server-sheet.tsx +25 -9
  69. package/src/components/memory/memory-browser.tsx +73 -45
  70. package/src/components/memory/memory-graph-view.tsx +203 -0
  71. package/src/components/memory/memory-list.tsx +20 -13
  72. package/src/components/plugins/plugin-list.tsx +214 -60
  73. package/src/components/plugins/plugin-sheet.tsx +119 -24
  74. package/src/components/projects/project-list.tsx +17 -9
  75. package/src/components/providers/provider-list.tsx +21 -6
  76. package/src/components/providers/provider-sheet.tsx +42 -25
  77. package/src/components/runs/run-list.tsx +17 -13
  78. package/src/components/schedules/schedule-card.tsx +10 -3
  79. package/src/components/schedules/schedule-list.tsx +2 -2
  80. package/src/components/schedules/schedule-sheet.tsx +28 -9
  81. package/src/components/secrets/secret-sheet.tsx +7 -2
  82. package/src/components/secrets/secrets-list.tsx +18 -5
  83. package/src/components/sessions/new-session-sheet.tsx +183 -376
  84. package/src/components/sessions/session-card.tsx +10 -2
  85. package/src/components/settings/gateway-connection-panel.tsx +9 -8
  86. package/src/components/shared/command-palette.tsx +13 -5
  87. package/src/components/shared/empty-state.tsx +20 -8
  88. package/src/components/shared/hint-tip.tsx +31 -0
  89. package/src/components/shared/notification-center.tsx +134 -86
  90. package/src/components/shared/profile-sheet.tsx +4 -0
  91. package/src/components/shared/settings/plugin-manager.tsx +360 -135
  92. package/src/components/shared/settings/section-capability-policy.tsx +3 -3
  93. package/src/components/shared/settings/section-runtime-loop.tsx +149 -4
  94. package/src/components/skills/clawhub-browser.tsx +1 -0
  95. package/src/components/skills/skill-list.tsx +31 -12
  96. package/src/components/skills/skill-sheet.tsx +20 -7
  97. package/src/components/tasks/approvals-panel.tsx +224 -0
  98. package/src/components/tasks/task-board.tsx +20 -12
  99. package/src/components/tasks/task-card.tsx +21 -7
  100. package/src/components/tasks/task-column.tsx +4 -3
  101. package/src/components/tasks/task-list.tsx +1 -1
  102. package/src/components/tasks/task-sheet.tsx +130 -1
  103. package/src/components/ui/dialog.tsx +1 -0
  104. package/src/components/ui/sheet.tsx +1 -0
  105. package/src/components/usage/metrics-dashboard.tsx +72 -48
  106. package/src/components/wallets/wallet-panel.tsx +65 -41
  107. package/src/components/wallets/wallet-section.tsx +9 -3
  108. package/src/components/webhooks/webhook-list.tsx +21 -12
  109. package/src/components/webhooks/webhook-sheet.tsx +13 -3
  110. package/src/lib/approval-display.test.ts +45 -0
  111. package/src/lib/approval-display.ts +62 -0
  112. package/src/lib/clipboard.ts +38 -0
  113. package/src/lib/memory.ts +8 -0
  114. package/src/lib/providers/claude-cli.ts +5 -3
  115. package/src/lib/providers/index.ts +67 -21
  116. package/src/lib/runtime-loop.ts +3 -2
  117. package/src/lib/server/approvals.ts +150 -0
  118. package/src/lib/server/chat-execution.ts +319 -74
  119. package/src/lib/server/chatroom-helpers.ts +63 -5
  120. package/src/lib/server/chatroom-orchestration.ts +74 -0
  121. package/src/lib/server/clawhub-client.ts +82 -6
  122. package/src/lib/server/connectors/manager.ts +27 -1
  123. package/src/lib/server/context-manager.ts +132 -50
  124. package/src/lib/server/cost.test.ts +73 -0
  125. package/src/lib/server/cost.ts +165 -34
  126. package/src/lib/server/daemon-state.ts +112 -1
  127. package/src/lib/server/data-dir.ts +18 -1
  128. package/src/lib/server/eval/runner.ts +126 -0
  129. package/src/lib/server/eval/scenarios.ts +218 -0
  130. package/src/lib/server/eval/scorer.ts +96 -0
  131. package/src/lib/server/eval/store.ts +37 -0
  132. package/src/lib/server/eval/types.ts +48 -0
  133. package/src/lib/server/execution-log.ts +12 -8
  134. package/src/lib/server/guardian.ts +34 -0
  135. package/src/lib/server/heartbeat-service.ts +53 -1
  136. package/src/lib/server/integrity-monitor.ts +208 -0
  137. package/src/lib/server/langgraph-checkpoint.ts +10 -0
  138. package/src/lib/server/link-understanding.ts +55 -0
  139. package/src/lib/server/llm-response-cache.test.ts +102 -0
  140. package/src/lib/server/llm-response-cache.ts +227 -0
  141. package/src/lib/server/main-agent-loop.ts +115 -16
  142. package/src/lib/server/main-session.ts +6 -3
  143. package/src/lib/server/mcp-conformance.test.ts +18 -0
  144. package/src/lib/server/mcp-conformance.ts +233 -0
  145. package/src/lib/server/memory-db.ts +193 -19
  146. package/src/lib/server/memory-retrieval.test.ts +56 -0
  147. package/src/lib/server/mmr.ts +73 -0
  148. package/src/lib/server/orchestrator-lg.ts +7 -1
  149. package/src/lib/server/orchestrator.ts +4 -3
  150. package/src/lib/server/plugins.ts +662 -132
  151. package/src/lib/server/process-manager.ts +18 -0
  152. package/src/lib/server/query-expansion.ts +57 -0
  153. package/src/lib/server/queue.ts +280 -11
  154. package/src/lib/server/runtime-settings.ts +9 -0
  155. package/src/lib/server/session-run-manager.test.ts +23 -0
  156. package/src/lib/server/session-run-manager.ts +32 -2
  157. package/src/lib/server/session-tools/canvas.ts +85 -50
  158. package/src/lib/server/session-tools/chatroom.ts +130 -127
  159. package/src/lib/server/session-tools/connector.ts +233 -454
  160. package/src/lib/server/session-tools/context-mgmt.ts +87 -105
  161. package/src/lib/server/session-tools/crud.ts +84 -7
  162. package/src/lib/server/session-tools/delegate.ts +351 -752
  163. package/src/lib/server/session-tools/discovery.ts +198 -0
  164. package/src/lib/server/session-tools/edit_file.ts +82 -0
  165. package/src/lib/server/session-tools/file-send.test.ts +39 -0
  166. package/src/lib/server/session-tools/file.ts +257 -425
  167. package/src/lib/server/session-tools/git.ts +87 -47
  168. package/src/lib/server/session-tools/http.ts +95 -33
  169. package/src/lib/server/session-tools/index.ts +217 -138
  170. package/src/lib/server/session-tools/memory.ts +154 -239
  171. package/src/lib/server/session-tools/monitor.ts +126 -0
  172. package/src/lib/server/session-tools/normalize-tool-args.test.ts +61 -0
  173. package/src/lib/server/session-tools/normalize-tool-args.ts +48 -0
  174. package/src/lib/server/session-tools/openclaw-nodes.ts +82 -99
  175. package/src/lib/server/session-tools/openclaw-workspace.ts +103 -93
  176. package/src/lib/server/session-tools/platform.ts +86 -0
  177. package/src/lib/server/session-tools/plugin-creator.ts +239 -0
  178. package/src/lib/server/session-tools/sample-ui.ts +97 -0
  179. package/src/lib/server/session-tools/sandbox.ts +175 -148
  180. package/src/lib/server/session-tools/schedule.ts +78 -0
  181. package/src/lib/server/session-tools/session-info.ts +104 -410
  182. package/src/lib/server/session-tools/shell-normalize.test.ts +43 -0
  183. package/src/lib/server/session-tools/shell.ts +171 -143
  184. package/src/lib/server/session-tools/subagent.ts +77 -77
  185. package/src/lib/server/session-tools/wallet.ts +182 -106
  186. package/src/lib/server/session-tools/web.ts +181 -327
  187. package/src/lib/server/storage.ts +36 -0
  188. package/src/lib/server/stream-agent-chat.ts +348 -242
  189. package/src/lib/server/task-quality-gate.test.ts +44 -0
  190. package/src/lib/server/task-quality-gate.ts +67 -0
  191. package/src/lib/server/task-validation.test.ts +78 -0
  192. package/src/lib/server/task-validation.ts +67 -2
  193. package/src/lib/server/tool-aliases.ts +68 -0
  194. package/src/lib/server/tool-capability-policy.ts +24 -5
  195. package/src/lib/server/tool-retry.ts +62 -0
  196. package/src/lib/server/transcript-repair.ts +72 -0
  197. package/src/lib/setup-defaults.ts +1 -0
  198. package/src/lib/tasks.ts +7 -1
  199. package/src/lib/tool-definitions.ts +24 -23
  200. package/src/lib/validation/schemas.ts +13 -0
  201. package/src/lib/view-routes.ts +2 -23
  202. package/src/stores/use-app-store.ts +23 -1
  203. package/src/types/index.ts +155 -10
@@ -2,123 +2,199 @@ import { z } from 'zod'
2
2
  import { tool, type StructuredToolInterface } from '@langchain/core/tools'
3
3
  import type { ToolBuildContext } from './context'
4
4
  import { loadWallets, loadWalletTransactions } from '../storage'
5
- import type { AgentWallet, WalletTransaction } from '@/types'
5
+ import type { AgentWallet, WalletTransaction, Plugin, PluginHooks } from '@/types'
6
+ import { getPluginManager } from '../plugins'
7
+ import { normalizeToolInputArgs } from './normalize-tool-args'
6
8
 
7
- export function buildWalletTools(bctx: ToolBuildContext): StructuredToolInterface[] {
8
- if (!bctx.hasTool('wallet')) return []
9
+ /**
10
+ * Core Wallet Execution Logic
11
+ */
12
+ async function executeWalletAction(args: any, context: { agentId?: string | null }) {
13
+ const normalized = normalizeToolInputArgs((args ?? {}) as Record<string, unknown>)
14
+ const action = normalized.action as string | undefined
15
+ const toAddress = (normalized.toAddress ?? normalized.to) as string | undefined
16
+ const amountSol = normalized.amountSol as number | undefined
17
+ const memo = normalized.memo as string | undefined
18
+ const limit = normalized.limit as number | undefined
19
+ const agentId = context.agentId
9
20
 
10
- const agentId = bctx.ctx?.agentId
21
+ if (!agentId) return JSON.stringify({ error: 'No agent ID in context' })
22
+
23
+ const wallets = loadWallets() as Record<string, AgentWallet>
24
+ const wallet = Object.values(wallets).find((w) => w.agentId === agentId) ?? null
11
25
 
12
- function getAgentWallet(): AgentWallet | null {
13
- if (!agentId) return null
14
- const wallets = loadWallets() as Record<string, AgentWallet>
15
- return Object.values(wallets).find((w) => w.agentId === agentId) ?? null
26
+ if (!wallet) {
27
+ if (action === 'address' || action === 'balance' || action === 'transactions') {
28
+ return JSON.stringify({
29
+ status: 'wallet_not_linked',
30
+ message: 'No wallet linked to this agent yet.',
31
+ setup: {
32
+ endpoint: '/wallets',
33
+ method: 'POST',
34
+ body: { agentId, chain: 'solana' },
35
+ },
36
+ })
37
+ }
38
+ return JSON.stringify({ error: 'No wallet linked to this agent. Ask the user to create one in the Wallets section.' })
16
39
  }
17
40
 
18
- return [
19
- tool(
20
- async ({ action, toAddress, amountSol, memo, limit }) => {
21
- const wallet = getAgentWallet()
22
- if (!wallet) {
23
- return JSON.stringify({ error: 'No wallet linked to this agent. Ask the user to create one in the Wallets section.' })
24
- }
25
-
26
- switch (action) {
27
- case 'balance': {
28
- try {
29
- const { getBalance, lamportsToSol } = await import('../solana')
30
- const balanceLamports = await getBalance(wallet.publicKey)
31
- return JSON.stringify({
32
- address: wallet.publicKey,
33
- chain: wallet.chain,
34
- balanceLamports,
35
- balanceSol: lamportsToSol(balanceLamports),
36
- })
37
- } catch (err: unknown) {
38
- return JSON.stringify({ error: `Failed to fetch balance: ${err instanceof Error ? err.message : String(err)}` })
39
- }
40
- }
41
-
42
- case 'address': {
43
- return JSON.stringify({
44
- address: wallet.publicKey,
45
- chain: wallet.chain,
46
- })
47
- }
41
+ switch (action) {
42
+ case 'balance': {
43
+ try {
44
+ const { getBalance, lamportsToSol } = await import('../solana')
45
+ const balanceLamports = await getBalance(wallet.publicKey)
46
+ const sol = lamportsToSol(balanceLamports)
47
+
48
+ // Return a Rich UI Card for balance
49
+ return JSON.stringify({
50
+ kind: 'plugin-ui',
51
+ text: `### Wallet Balance\n\n**Address:** \`${wallet.publicKey}\`\n**Balance:** \`${sol} SOL\``,
52
+ actions: [
53
+ { id: 'view-solscan', label: 'View on Solscan', href: `https://solscan.io/account/${wallet.publicKey}` }
54
+ ]
55
+ })
56
+ } catch (err: unknown) {
57
+ return JSON.stringify({ error: `Failed to fetch balance: ${err instanceof Error ? err.message : String(err)}` })
58
+ }
59
+ }
60
+ case 'address': return JSON.stringify({ address: wallet.publicKey, chain: wallet.chain })
61
+ case 'send': {
62
+ if (!toAddress) return JSON.stringify({ error: 'toAddress is required for send' })
63
+ if (!amountSol || amountSol <= 0) return JSON.stringify({ error: 'amountSol must be positive' })
64
+
65
+ if (normalized.approved !== true) {
66
+ const { requestApproval } = await import('../approvals')
67
+ requestApproval({
68
+ category: 'wallet_transfer',
69
+ title: `Send ${amountSol} SOL`,
70
+ description: `Transfer to ${toAddress}. Memo: ${memo || 'none'}`,
71
+ data: { toAddress, amountSol, memo },
72
+ agentId: context.agentId,
73
+ })
74
+ return JSON.stringify({
75
+ type: 'plugin_wallet_transfer_request',
76
+ amountSol,
77
+ toAddress,
78
+ memo,
79
+ message: `I'm requesting to send ${amountSol} SOL to ${toAddress}. Please approve this transaction.`
80
+ })
81
+ }
48
82
 
49
- case 'send': {
50
- if (!toAddress) return JSON.stringify({ error: 'toAddress is required for send action' })
51
- if (!amountSol || amountSol <= 0) return JSON.stringify({ error: 'amountSol must be positive' })
52
-
53
- const { isValidSolanaAddress, solToLamports, lamportsToSol } = await import('../solana')
54
- if (!isValidSolanaAddress(toAddress)) {
55
- return JSON.stringify({ error: 'Invalid Solana address' })
56
- }
57
-
58
- const amountLamports = solToLamports(amountSol)
59
-
60
- // Check per-tx limit
61
- const perTxLimit = wallet.spendingLimitLamports ?? 100_000_000
62
- if (amountLamports > perTxLimit) {
63
- return JSON.stringify({
64
- error: `Amount ${amountSol} SOL exceeds per-transaction limit of ${lamportsToSol(perTxLimit)} SOL`,
65
- })
66
- }
67
-
68
- // Send via API to enforce all limits and approval flow
69
- try {
70
- const baseUrl = process.env.NEXTAUTH_URL || `http://localhost:${process.env.PORT || 3456}`
71
- const res = await fetch(`${baseUrl}/api/wallets/${wallet.id}/send`, {
72
- method: 'POST',
73
- headers: {
74
- 'Content-Type': 'application/json',
75
- 'X-Access-Key': process.env.ACCESS_KEY || '',
76
- },
77
- body: JSON.stringify({ toAddress, amountLamports, memo }),
78
- })
79
- const result = await res.json()
80
- return JSON.stringify(result)
81
- } catch (err: unknown) {
82
- return JSON.stringify({ error: `Send failed: ${err instanceof Error ? err.message : String(err)}` })
83
- }
84
- }
83
+ const { isValidSolanaAddress, solToLamports, lamportsToSol } = await import('../solana')
84
+ if (!isValidSolanaAddress(toAddress)) return JSON.stringify({ error: 'Invalid Solana address' })
85
+ const amountLamports = solToLamports(amountSol)
86
+ const perTxLimit = wallet.spendingLimitLamports ?? 100_000_000
87
+ if (amountLamports > perTxLimit) return JSON.stringify({ error: `Amount ${amountSol} SOL exceeds limit of ${lamportsToSol(perTxLimit)} SOL` })
88
+ try {
89
+ const baseUrl = process.env.NEXTAUTH_URL || `http://localhost:${process.env.PORT || 3456}`
90
+ const res = await fetch(`${baseUrl}/api/wallets/${wallet.id}/send`, {
91
+ method: 'POST',
92
+ headers: { 'Content-Type': 'application/json', 'X-Access-Key': process.env.ACCESS_KEY || '' },
93
+ body: JSON.stringify({ toAddress, amountLamports, memo }),
94
+ })
95
+ const data = await res.json()
96
+
97
+ if (data.signature) {
98
+ return JSON.stringify({
99
+ kind: 'plugin-ui',
100
+ text: `### Transaction Sent!\n\n**Amount:** \`${amountSol} SOL\`\n**To:** \`${toAddress}\`\n**Sig:** \`${data.signature.slice(0, 8)}...\``,
101
+ actions: [
102
+ { id: 'view-tx', label: 'View Transaction', href: `https://solscan.io/tx/${data.signature}` }
103
+ ]
104
+ })
105
+ }
106
+ return JSON.stringify(data)
107
+ } catch (err: unknown) {
108
+ return JSON.stringify({ error: `Send failed: ${err instanceof Error ? err.message : String(err)}` })
109
+ }
110
+ }
111
+ case 'transactions': {
112
+ const allTxs = loadWalletTransactions() as Record<string, WalletTransaction>
113
+ const walletTxs = Object.values(allTxs)
114
+ .filter((tx) => tx.walletId === wallet.id)
115
+ .sort((a, b) => b.timestamp - a.timestamp)
116
+ .slice(0, limit ?? 5)
117
+
118
+ const txLines = walletTxs.map(tx => `- **${tx.type.toUpperCase()}**: ${tx.amountLamports / 1e9} SOL (${tx.status})`).join('\n')
119
+
120
+ return JSON.stringify({
121
+ kind: 'plugin-ui',
122
+ text: `### Recent Transactions\n\n${txLines || 'No recent transactions found.'}`,
123
+ actions: [
124
+ { id: 'view-history', label: 'Full History', href: `https://solscan.io/account/${wallet.publicKey}#transfers` }
125
+ ]
126
+ })
127
+ }
128
+ default: return JSON.stringify({ error: `Unknown action: ${action}` })
129
+ }
130
+ }
85
131
 
86
- case 'transactions': {
87
- const allTxs = loadWalletTransactions() as Record<string, WalletTransaction>
88
- const walletTxs = Object.values(allTxs)
89
- .filter((tx) => tx.walletId === wallet.id)
90
- .sort((a, b) => b.timestamp - a.timestamp)
91
- .slice(0, limit ?? 10)
92
- .map((tx) => ({
93
- id: tx.id,
94
- type: tx.type,
95
- status: tx.status,
96
- amountLamports: tx.amountLamports,
97
- toAddress: tx.toAddress,
98
- fromAddress: tx.fromAddress,
99
- signature: tx.signature || undefined,
100
- memo: tx.memo,
101
- timestamp: tx.timestamp,
102
- }))
132
+ /**
133
+ * Register as a Built-in Plugin with UI extensions
134
+ */
135
+ const WalletPlugin: Plugin = {
136
+ name: 'Core Wallet',
137
+ description: 'Manage agent crypto wallet: check balance, send SOL, view transactions.',
138
+ hooks: {} as PluginHooks,
139
+ ui: {
140
+ sidebarItems: [
141
+ {
142
+ id: 'wallet-dashboard',
143
+ label: 'Wallet',
144
+ href: '/wallets',
145
+ position: 'top'
146
+ }
147
+ ],
148
+ headerWidgets: [
149
+ {
150
+ id: 'wallet-status',
151
+ label: '💎 Wallet Active'
152
+ }
153
+ ]
154
+ },
155
+ tools: [
156
+ {
157
+ name: 'wallet_tool',
158
+ description: 'Manage your own crypto wallet.',
159
+ parameters: {
160
+ type: 'object',
161
+ properties: {
162
+ action: { type: 'string', enum: ['balance', 'address', 'send', 'transactions'] },
163
+ toAddress: { type: 'string' },
164
+ amountSol: { type: 'number' },
165
+ memo: { type: 'string' },
166
+ limit: { type: 'number' },
167
+ approved: { type: 'boolean', description: 'Set to true only after user has manually approved the transfer request.' }
168
+ },
169
+ required: ['action']
170
+ },
171
+ execute: async (args, context) => executeWalletAction(args, { agentId: context.session.agentId })
172
+ }
173
+ ]
174
+ }
103
175
 
104
- return JSON.stringify({ transactions: walletTxs, count: walletTxs.length })
105
- }
176
+ getPluginManager().registerBuiltin('wallet', WalletPlugin)
106
177
 
107
- default:
108
- return JSON.stringify({ error: `Unknown action: ${action}. Use balance, address, send, or transactions.` })
109
- }
110
- },
178
+ /**
179
+ * Legacy Bridge
180
+ */
181
+ export function buildWalletTools(bctx: ToolBuildContext): StructuredToolInterface[] {
182
+ if (!bctx.hasTool('wallet')) return []
183
+ return [
184
+ tool(
185
+ async (args) => executeWalletAction(args, { agentId: bctx.ctx?.agentId }),
111
186
  {
112
187
  name: 'wallet_tool',
113
- description: 'Manage your own crypto wallet. Actions: balance (check your SOL balance), address (get your wallet address), send (send SOL from your wallet — subject to your spending limits and user approval), transactions (view your recent transaction history).',
188
+ description: WalletPlugin.tools![0].description,
114
189
  schema: z.object({
115
- action: z.enum(['balance', 'address', 'send', 'transactions']).describe('Wallet action to perform'),
116
- toAddress: z.string().optional().describe('Recipient Solana address (required for send)'),
117
- amountSol: z.number().optional().describe('Amount in SOL to send (required for send)'),
118
- memo: z.string().optional().describe('Reason or memo for the transaction'),
119
- limit: z.number().optional().describe('Number of transactions to return (default 10, for transactions action)'),
120
- }),
121
- },
122
- ),
190
+ action: z.enum(['balance', 'address', 'send', 'transactions']),
191
+ toAddress: z.string().optional(),
192
+ amountSol: z.number().optional(),
193
+ memo: z.string().optional(),
194
+ limit: z.number().optional(),
195
+ approved: z.boolean().optional()
196
+ })
197
+ }
198
+ )
123
199
  ]
124
200
  }