@swarmclawai/swarmclaw 1.2.8 → 1.3.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 (214) hide show
  1. package/README.md +39 -6
  2. package/package.json +2 -2
  3. package/src/app/agents/[id]/page.tsx +1 -18
  4. package/src/app/api/activity/route.ts +9 -23
  5. package/src/app/api/agents/route.ts +17 -1
  6. package/src/app/api/agents/thread-route.test.ts +0 -1
  7. package/src/app/api/approvals/route.test.ts +6 -22
  8. package/src/app/api/approvals/route.ts +13 -5
  9. package/src/app/api/connectors/route.ts +2 -2
  10. package/src/app/api/credentials/[id]/route.ts +2 -0
  11. package/src/app/api/credentials/route.ts +4 -1
  12. package/src/app/api/goals/[id]/route.ts +28 -0
  13. package/src/app/api/goals/route.ts +33 -0
  14. package/src/app/api/portability/export/route.ts +8 -0
  15. package/src/app/api/portability/import/route.test.ts +80 -0
  16. package/src/app/api/portability/import/route.ts +28 -0
  17. package/src/app/api/protocols/templates/[id]/route.ts +2 -1
  18. package/src/app/api/protocols/templates/route.ts +2 -1
  19. package/src/app/api/settings/route.ts +13 -2
  20. package/src/app/api/wallets/[id]/route.ts +15 -157
  21. package/src/app/api/wallets/generate/route.ts +22 -0
  22. package/src/app/api/wallets/route.test.ts +147 -0
  23. package/src/app/api/wallets/route.ts +13 -95
  24. package/src/app/autonomy/page.tsx +2 -57
  25. package/src/app/home/page.tsx +3 -0
  26. package/src/app/protocols/page.tsx +2 -21
  27. package/src/app/settings/page.tsx +0 -9
  28. package/src/app/wallets/page.tsx +105 -5
  29. package/src/cli/index.js +32 -33
  30. package/src/cli/spec.js +26 -27
  31. package/src/components/agents/agent-sheet.tsx +2 -40
  32. package/src/components/agents/inspector-panel.tsx +0 -83
  33. package/src/components/chat/chat-card.tsx +0 -31
  34. package/src/components/chat/message-bubble.tsx +1 -108
  35. package/src/components/connectors/connector-sheet.tsx +25 -1
  36. package/src/components/layout/sidebar-rail.tsx +6 -10
  37. package/src/components/projects/project-detail.tsx +3 -35
  38. package/src/components/projects/tabs/overview-tab.tsx +3 -59
  39. package/src/components/projects/tabs/work-tab.tsx +7 -77
  40. package/src/components/protocols/structured-session-launcher.tsx +1 -22
  41. package/src/components/shared/connector-platform-icon.tsx +1 -0
  42. package/src/components/tasks/task-card.tsx +4 -34
  43. package/src/components/tasks/task-sheet.tsx +6 -36
  44. package/src/components/wallets/wallet-list.tsx +150 -0
  45. package/src/lib/app/navigation.test.ts +0 -13
  46. package/src/lib/app/navigation.ts +2 -7
  47. package/src/lib/app/view-constants.ts +14 -19
  48. package/src/lib/server/activity/activity-log.ts +16 -1
  49. package/src/lib/server/agents/agent-service.ts +24 -11
  50. package/src/lib/server/agents/agent-thread-session.ts +0 -1
  51. package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
  52. package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
  53. package/src/lib/server/agents/delegation-jobs.ts +0 -25
  54. package/src/lib/server/agents/main-agent-loop.ts +1 -49
  55. package/src/lib/server/agents/subagent-runtime.ts +0 -1
  56. package/src/lib/server/approval-match.ts +14 -85
  57. package/src/lib/server/approvals/approval-hooks.ts +81 -0
  58. package/src/lib/server/approvals.test.ts +6 -6
  59. package/src/lib/server/approvals.ts +11 -6
  60. package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
  61. package/src/lib/server/builtin-extensions.ts +0 -2
  62. package/src/lib/server/capability-router.test.ts +0 -2
  63. package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
  64. package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
  65. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
  66. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
  67. package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
  68. package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
  69. package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
  70. package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
  71. package/src/lib/server/chat-execution/message-classifier.ts +1 -16
  72. package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
  73. package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
  74. package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
  75. package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
  76. package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
  77. package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
  78. package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
  79. package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
  80. package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
  81. package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
  82. package/src/lib/server/chats/chat-session-service.ts +3 -5
  83. package/src/lib/server/connectors/connector-inbound.ts +0 -1
  84. package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
  85. package/src/lib/server/connectors/connector-service.ts +39 -9
  86. package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
  87. package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
  88. package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
  89. package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
  90. package/src/lib/server/connectors/swarmdock-tasks.ts +127 -0
  91. package/src/lib/server/connectors/swarmdock.ts +285 -0
  92. package/src/lib/server/execution-brief.test.ts +2 -25
  93. package/src/lib/server/execution-brief.ts +30 -35
  94. package/src/lib/server/execution-engine/task-attempt.ts +0 -1
  95. package/src/lib/server/goals/goal-repository.ts +19 -0
  96. package/src/lib/server/goals/goal-service.ts +143 -0
  97. package/src/lib/server/persistence/storage-context.ts +0 -5
  98. package/src/lib/server/portability/export.ts +109 -0
  99. package/src/lib/server/portability/import.ts +159 -0
  100. package/src/lib/server/protocols/protocol-normalization.ts +0 -4
  101. package/src/lib/server/protocols/protocol-queries.ts +0 -6
  102. package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
  103. package/src/lib/server/protocols/protocol-service.ts +0 -1
  104. package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
  105. package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
  106. package/src/lib/server/protocols/protocol-swarm.ts +0 -2
  107. package/src/lib/server/protocols/protocol-types.ts +0 -2
  108. package/src/lib/server/provider-health.ts +0 -9
  109. package/src/lib/server/runtime/daemon-state/core.ts +0 -9
  110. package/src/lib/server/runtime/daemon-state.test.ts +0 -35
  111. package/src/lib/server/runtime/heartbeat-service.ts +3 -23
  112. package/src/lib/server/runtime/queue/core.ts +11 -33
  113. package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
  114. package/src/lib/server/runtime/scheduler.ts +0 -13
  115. package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
  116. package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
  117. package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
  118. package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
  119. package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
  120. package/src/lib/server/session-tools/crud.ts +0 -14
  121. package/src/lib/server/session-tools/delegate.ts +0 -4
  122. package/src/lib/server/session-tools/index.ts +0 -4
  123. package/src/lib/server/session-tools/team-context.ts +0 -3
  124. package/src/lib/server/storage-normalization.ts +13 -0
  125. package/src/lib/server/storage.ts +75 -45
  126. package/src/lib/server/tasks/task-checkout.ts +59 -0
  127. package/src/lib/server/tasks/task-lifecycle.ts +2 -0
  128. package/src/lib/server/tasks/task-route-service.ts +4 -26
  129. package/src/lib/server/tasks/task-service.ts +0 -7
  130. package/src/lib/server/tool-aliases.ts +0 -1
  131. package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
  132. package/src/lib/server/tool-capability-policy.ts +0 -2
  133. package/src/lib/server/tool-planning.ts +0 -12
  134. package/src/lib/server/universal-tool-access.ts +0 -1
  135. package/src/lib/server/usage/cost-rollup.ts +124 -0
  136. package/src/lib/server/usage/usage-repository.ts +6 -0
  137. package/src/lib/server/wallets/wallet-crypto.ts +33 -0
  138. package/src/lib/server/wallets/wallet-repository.ts +24 -0
  139. package/src/lib/server/wallets/wallet-service.ts +119 -0
  140. package/src/lib/server/working-state/extraction.ts +8 -42
  141. package/src/lib/server/working-state/normalization.ts +10 -103
  142. package/src/lib/server/working-state/service.ts +12 -21
  143. package/src/lib/strip-internal-metadata.test.ts +1 -1
  144. package/src/lib/strip-internal-metadata.ts +1 -1
  145. package/src/lib/tool-definitions.ts +0 -1
  146. package/src/lib/validation/schemas.ts +36 -32
  147. package/src/lib/validation/server-schemas.ts +35 -0
  148. package/src/stores/slices/data-slice.ts +5 -1
  149. package/src/stores/slices/ui-slice.ts +0 -4
  150. package/src/types/agent.ts +10 -84
  151. package/src/types/app-settings.ts +6 -2
  152. package/src/types/approval.ts +3 -2
  153. package/src/types/connector.ts +1 -0
  154. package/src/types/goal.ts +30 -0
  155. package/src/types/index.ts +2 -1
  156. package/src/types/message.ts +0 -1
  157. package/src/types/misc.ts +2 -4
  158. package/src/types/protocol.ts +0 -2
  159. package/src/types/run.ts +0 -3
  160. package/src/types/session.ts +1 -51
  161. package/src/types/swarmdock.ts +29 -0
  162. package/src/types/task.ts +9 -3
  163. package/src/types/working-state.ts +2 -9
  164. package/src/views/settings/section-runtime-loop.tsx +0 -14
  165. package/src/app/api/canvas/[sessionId]/route.ts +0 -35
  166. package/src/app/api/missions/[id]/actions/route.ts +0 -31
  167. package/src/app/api/missions/[id]/events/route.ts +0 -14
  168. package/src/app/api/missions/[id]/route.ts +0 -10
  169. package/src/app/api/missions/route.test.ts +0 -244
  170. package/src/app/api/missions/route.ts +0 -57
  171. package/src/app/api/wallets/[id]/approve/route.ts +0 -79
  172. package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
  173. package/src/app/api/wallets/[id]/send/route.ts +0 -113
  174. package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
  175. package/src/app/missions/[id]/page.tsx +0 -3
  176. package/src/app/missions/page.tsx +0 -685
  177. package/src/components/canvas/canvas-panel.tsx +0 -267
  178. package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
  179. package/src/components/wallets/wallet-panel.tsx +0 -1010
  180. package/src/components/wallets/wallet-section.tsx +0 -260
  181. package/src/features/missions/queries.ts +0 -23
  182. package/src/lib/canvas-content.test.ts +0 -360
  183. package/src/lib/canvas-content.ts +0 -198
  184. package/src/lib/server/canvas-content.test.ts +0 -32
  185. package/src/lib/server/canvas-content.ts +0 -6
  186. package/src/lib/server/ethereum.ts +0 -591
  187. package/src/lib/server/evm-swap.ts +0 -476
  188. package/src/lib/server/missions/mission-intent.test.ts +0 -63
  189. package/src/lib/server/missions/mission-intent.ts +0 -569
  190. package/src/lib/server/missions/mission-repository.ts +0 -74
  191. package/src/lib/server/missions/mission-service/actions.ts +0 -6
  192. package/src/lib/server/missions/mission-service/bindings.ts +0 -9
  193. package/src/lib/server/missions/mission-service/context.ts +0 -4
  194. package/src/lib/server/missions/mission-service/core.ts +0 -2271
  195. package/src/lib/server/missions/mission-service/queries.ts +0 -12
  196. package/src/lib/server/missions/mission-service/recovery.ts +0 -5
  197. package/src/lib/server/missions/mission-service/ticks.ts +0 -9
  198. package/src/lib/server/missions/mission-service.test.ts +0 -888
  199. package/src/lib/server/missions/mission-service.ts +0 -6
  200. package/src/lib/server/session-tools/canvas.ts +0 -105
  201. package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
  202. package/src/lib/server/session-tools/wallet.ts +0 -1287
  203. package/src/lib/server/solana.ts +0 -327
  204. package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
  205. package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
  206. package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
  207. package/src/lib/server/wallet/wallet-service.test.ts +0 -81
  208. package/src/lib/server/wallet/wallet-service.ts +0 -225
  209. package/src/lib/wallet/wallet-transactions.test.ts +0 -75
  210. package/src/lib/wallet/wallet-transactions.ts +0 -43
  211. package/src/lib/wallet/wallet.test.ts +0 -333
  212. package/src/lib/wallet/wallet.ts +0 -183
  213. package/src/types/mission.ts +0 -185
  214. package/src/views/settings/section-wallets.tsx +0 -35
@@ -1,267 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState, useCallback } from 'react'
4
- import ReactMarkdown from 'react-markdown'
5
- import { useWs } from '@/hooks/use-ws'
6
- import { api } from '@/lib/app/api-client'
7
- import { normalizeCanvasContent } from '@/lib/canvas-content'
8
- import type { CanvasContent, CanvasDocument } from '@/types'
9
-
10
- interface CanvasPanelProps {
11
- sessionId: string
12
- agentName?: string
13
- onClose: () => void
14
- }
15
-
16
- const THEME_STYLES: Record<NonNullable<CanvasDocument['theme']>, { accent: string; chip: string }> = {
17
- slate: { accent: 'text-sky-300', chip: 'bg-sky-500/10 text-sky-300 border-sky-500/20' },
18
- sky: { accent: 'text-sky-300', chip: 'bg-sky-500/10 text-sky-300 border-sky-500/20' },
19
- emerald: { accent: 'text-emerald-300', chip: 'bg-emerald-500/10 text-emerald-300 border-emerald-500/20' },
20
- amber: { accent: 'text-amber-300', chip: 'bg-amber-500/10 text-amber-300 border-amber-500/20' },
21
- rose: { accent: 'text-rose-300', chip: 'bg-rose-500/10 text-rose-300 border-rose-500/20' },
22
- }
23
-
24
- function toneClass(tone?: string): string {
25
- switch (tone) {
26
- case 'positive': return 'text-emerald-300'
27
- case 'negative': return 'text-rose-300'
28
- case 'warning': return 'text-amber-300'
29
- default: return 'text-text'
30
- }
31
- }
32
-
33
- function intentClass(intent?: string): string {
34
- switch (intent) {
35
- case 'primary': return 'bg-sky-500 text-white border-sky-400/30'
36
- case 'success': return 'bg-emerald-500 text-white border-emerald-400/30'
37
- case 'danger': return 'bg-rose-500 text-white border-rose-400/30'
38
- default: return 'bg-white/[0.03] text-text-2 border-white/[0.08]'
39
- }
40
- }
41
-
42
- function StructuredCanvasView({ document }: { document: CanvasDocument }) {
43
- const theme = THEME_STYLES[document.theme || 'slate']
44
- return (
45
- <div className="h-full overflow-y-auto bg-bg px-5 py-5">
46
- <div className="max-w-4xl mx-auto space-y-4">
47
- {(document.title || document.subtitle) && (
48
- <div className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
49
- {document.title && <h2 className={`font-display text-[22px] font-700 tracking-[-0.03em] ${theme.accent}`}>{document.title}</h2>}
50
- {document.subtitle && <p className="mt-1 text-[13px] text-text-3/70">{document.subtitle}</p>}
51
- </div>
52
- )}
53
-
54
- {document.blocks.map((block, index) => {
55
- if (block.type === 'markdown') {
56
- return (
57
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
58
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
59
- <div className="max-w-none text-[14px] leading-6 text-text-2/90 [&_h1]:font-display [&_h1]:text-[24px] [&_h1]:text-text [&_h2]:font-display [&_h2]:text-[20px] [&_h2]:text-text [&_h3]:font-display [&_h3]:text-[18px] [&_h3]:text-text [&_p]:my-3 [&_ul]:my-3 [&_ul]:pl-5 [&_li]:my-1 [&_code]:rounded [&_code]:bg-black/[0.2] [&_code]:px-1.5 [&_code]:py-0.5">
60
- <ReactMarkdown>{block.markdown}</ReactMarkdown>
61
- </div>
62
- </section>
63
- )
64
- }
65
-
66
- if (block.type === 'metrics') {
67
- return (
68
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
69
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
70
- <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-3">
71
- {block.items.map((item) => (
72
- <div key={item.label} className="rounded-[14px] border border-white/[0.08] bg-black/[0.14] px-4 py-3">
73
- <div className="text-[11px] uppercase tracking-[0.08em] text-text-3/60">{item.label}</div>
74
- <div className={`mt-1 text-[24px] font-display font-700 tracking-[-0.03em] ${toneClass(item.tone)}`}>{item.value}</div>
75
- {item.detail && <div className="mt-1 text-[12px] text-text-3/65">{item.detail}</div>}
76
- </div>
77
- ))}
78
- </div>
79
- </section>
80
- )
81
- }
82
-
83
- if (block.type === 'cards') {
84
- return (
85
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
86
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
87
- <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
88
- {block.items.map((item) => (
89
- <div key={item.title} className="rounded-[14px] border border-white/[0.08] bg-black/[0.14] px-4 py-3">
90
- <div className={`text-[15px] font-700 ${toneClass(item.tone)}`}>{item.title}</div>
91
- {item.body && <p className="mt-2 text-[13px] leading-6 text-text-2/85 whitespace-pre-wrap">{item.body}</p>}
92
- {item.meta && <div className="mt-3 text-[11px] text-text-3/60">{item.meta}</div>}
93
- </div>
94
- ))}
95
- </div>
96
- </section>
97
- )
98
- }
99
-
100
- if (block.type === 'table') {
101
- return (
102
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4 overflow-hidden">
103
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
104
- <div className="overflow-x-auto rounded-[12px] border border-white/[0.08]">
105
- <table className="min-w-full text-left text-[13px]">
106
- <thead className="bg-black/[0.18]">
107
- <tr>
108
- {block.table.columns.map((column) => (
109
- <th key={column} className="px-3 py-2.5 font-700 text-text-2">{column}</th>
110
- ))}
111
- </tr>
112
- </thead>
113
- <tbody>
114
- {block.table.rows.map((row, rowIndex) => (
115
- <tr key={rowIndex} className="border-t border-white/[0.06]">
116
- {row.map((cell, cellIndex) => (
117
- <td key={cellIndex} className="px-3 py-2.5 text-text-3/80">{cell == null ? '—' : String(cell)}</td>
118
- ))}
119
- </tr>
120
- ))}
121
- </tbody>
122
- </table>
123
- </div>
124
- {block.table.caption && <div className="mt-2 text-[11px] text-text-3/60">{block.table.caption}</div>}
125
- </section>
126
- )
127
- }
128
-
129
- if (block.type === 'code') {
130
- return (
131
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
132
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
133
- <pre className="overflow-x-auto rounded-[14px] border border-white/[0.08] bg-black/[0.25] p-4 text-[12px] leading-6 text-text-2">
134
- <code>{block.code}</code>
135
- </pre>
136
- {block.language && <div className={`mt-2 inline-flex rounded-full border px-2 py-1 text-[10px] font-700 uppercase tracking-[0.08em] ${theme.chip}`}>{block.language}</div>}
137
- </section>
138
- )
139
- }
140
-
141
- if (block.type === 'actions') {
142
- return (
143
- <section key={`${block.type}-${index}`} className="rounded-[18px] border border-white/[0.08] bg-white/[0.03] px-5 py-4">
144
- {block.title && <div className={`mb-3 text-[11px] font-700 uppercase tracking-[0.08em] ${theme.accent}`}>{block.title}</div>}
145
- <div className="flex flex-wrap gap-2">
146
- {block.items.map((item) => (
147
- item.href ? (
148
- <a
149
- key={item.label}
150
- href={item.href}
151
- target="_blank"
152
- rel="noreferrer"
153
- className={`inline-flex items-center rounded-[12px] border px-3 py-2 text-[12px] font-700 transition-all hover:brightness-110 ${intentClass(item.intent)}`}
154
- >
155
- {item.label}
156
- </a>
157
- ) : (
158
- <div key={item.label} className={`inline-flex items-center rounded-[12px] border px-3 py-2 text-[12px] font-700 ${intentClass(item.intent)}`}>
159
- {item.label}
160
- </div>
161
- )
162
- ))}
163
- </div>
164
- {block.items.some((item) => item.note) && (
165
- <div className="mt-3 space-y-1">
166
- {block.items.filter((item) => item.note).map((item) => (
167
- <div key={`${item.label}-note`} className="text-[11px] text-text-3/60">{item.label}: {item.note}</div>
168
- ))}
169
- </div>
170
- )}
171
- </section>
172
- )
173
- }
174
-
175
- return null
176
- })}
177
- </div>
178
- </div>
179
- )
180
- }
181
-
182
- export function CanvasPanel({ sessionId, agentName, onClose }: CanvasPanelProps) {
183
- const [content, setContent] = useState<CanvasContent>(null)
184
- const [loaded, setLoaded] = useState(false)
185
-
186
- const loadCanvas = useCallback(async () => {
187
- try {
188
- const res = await api<{ content: CanvasContent }>('GET', `/canvas/${sessionId}`)
189
- setContent(normalizeCanvasContent(res.content))
190
- } catch {
191
- setContent(null)
192
- } finally {
193
- setLoaded(true)
194
- }
195
- }, [sessionId])
196
-
197
- useEffect(() => { loadCanvas() }, [loadCanvas])
198
- useWs(`canvas:${sessionId}`, loadCanvas, 10_000)
199
-
200
- const header = (
201
- <div className="flex items-center gap-3 px-4 py-3 border-b border-white/[0.06] shrink-0">
202
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-accent-bright shrink-0">
203
- <rect x="2" y="3" width="20" height="14" rx="2" /><path d="M8 21h8" /><path d="M12 17v4" />
204
- </svg>
205
- <span className="text-[13px] font-600 text-text flex-1 truncate">
206
- Canvas{agentName ? ` — ${agentName}` : ''}
207
- </span>
208
- <button
209
- onClick={loadCanvas}
210
- className="p-1.5 rounded-[6px] hover:bg-white/[0.06] transition-colors cursor-pointer border-none bg-transparent text-text-3 hover:text-text-2"
211
- title="Refresh"
212
- >
213
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
214
- <polyline points="23 4 23 10 17 10" /><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
215
- </svg>
216
- </button>
217
- <button
218
- onClick={onClose}
219
- className="p-1.5 rounded-[6px] hover:bg-white/[0.06] transition-colors cursor-pointer border-none bg-transparent text-text-3 hover:text-text-2"
220
- title="Close canvas"
221
- >
222
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
223
- <path d="M18 6L6 18M6 6l12 12" />
224
- </svg>
225
- </button>
226
- </div>
227
- )
228
-
229
- if (!loaded) {
230
- return (
231
- <div className="flex flex-col h-full border-l border-white/[0.06] bg-bg min-w-[400px]">
232
- {header}
233
- <div className="flex-1 flex items-center justify-center">
234
- <div className="text-center">
235
- <div className="w-8 h-8 rounded-full border-2 border-text-3/20 border-t-accent-bright animate-spin mx-auto mb-3" />
236
- <span className="text-[13px] text-text-3">Loading canvas...</span>
237
- </div>
238
- </div>
239
- </div>
240
- )
241
- }
242
-
243
- return (
244
- <div className="flex flex-col h-full border-l border-white/[0.06] bg-bg min-w-[400px]">
245
- {header}
246
- <div className="flex-1 overflow-hidden">
247
- {!content ? (
248
- <div className="h-full flex items-center justify-center text-center px-6">
249
- <div>
250
- <div className="text-[14px] font-600 text-text-2">No canvas content yet</div>
251
- <p className="mt-1 text-[12px] text-text-3/60">Agents can present HTML or structured documents here.</p>
252
- </div>
253
- </div>
254
- ) : typeof content === 'string' ? (
255
- <iframe
256
- sandbox="allow-scripts allow-same-origin"
257
- srcDoc={content}
258
- className="w-full h-full border-none bg-white"
259
- title="Agent Canvas"
260
- />
261
- ) : (
262
- <StructuredCanvasView document={content} />
263
- )}
264
- </div>
265
- </div>
266
- )
267
- }
@@ -1,107 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useCallback } from 'react'
4
- import { api } from '@/lib/app/api-client'
5
- import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
6
- import type { WalletTransaction } from '@/types'
7
- import { formatWalletAmount, getWalletAssetSymbol, getWalletAtomicAmount } from '@/lib/wallet/wallet'
8
- import { errorMessage } from '@/lib/shared-utils'
9
-
10
- interface WalletApprovalDialogProps {
11
- transaction: WalletTransaction
12
- walletAddress: string
13
- onClose: () => void
14
- onResolved: () => void
15
- }
16
-
17
- export function WalletApprovalDialog({ transaction, walletAddress, onClose, onResolved }: WalletApprovalDialogProps) {
18
- const [submitting, setSubmitting] = useState(false)
19
- const [error, setError] = useState<string | null>(null)
20
-
21
- const handleDecision = useCallback(async (decision: 'approve' | 'deny') => {
22
- setSubmitting(true)
23
- setError(null)
24
- try {
25
- await api('POST', `/wallets/${transaction.walletId}/approve`, {
26
- transactionId: transaction.id,
27
- decision,
28
- })
29
- onResolved()
30
- onClose()
31
- } catch (err: unknown) {
32
- setError(errorMessage(err))
33
- } finally {
34
- setSubmitting(false)
35
- }
36
- }, [transaction, onResolved, onClose])
37
-
38
- const amountFormatted = formatWalletAmount(transaction.chain, getWalletAtomicAmount(transaction), { minFractionDigits: 4, maxFractionDigits: 6 })
39
- const symbol = getWalletAssetSymbol(transaction.chain)
40
-
41
- return (
42
- <Dialog open onOpenChange={(nextOpen) => { if (!nextOpen) onClose() }}>
43
- <DialogContent className="sm:max-w-[460px] rounded-[20px] border-white/[0.08] bg-surface/95 p-0 shadow-[0_24px_80px_rgba(0,0,0,0.6)]">
44
- <div className="p-6 space-y-5">
45
- <DialogHeader className="text-left">
46
- <div className="flex items-center gap-2">
47
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-amber-400">
48
- <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
49
- <line x1="12" y1="9" x2="12" y2="13" /><line x1="12" y1="17" x2="12.01" y2="17" />
50
- </svg>
51
- <DialogTitle className="font-display text-[16px] font-700 tracking-[-0.02em] text-text-1">
52
- Transaction Approval
53
- </DialogTitle>
54
- </div>
55
- <DialogDescription className="text-[12px] leading-relaxed text-text-3">
56
- Crypto transactions are irreversible. Verify the recipient address carefully before approving.
57
- </DialogDescription>
58
- </DialogHeader>
59
-
60
- <div className="rounded-[14px] border border-white/[0.06] bg-black/20 p-4 space-y-3">
61
- <div className="flex items-center justify-between">
62
- <span className="text-[11px] uppercase tracking-wide text-text-3/70">Amount</span>
63
- <span className="text-[16px] font-600 text-text-1">{amountFormatted} {symbol}</span>
64
- </div>
65
- <div>
66
- <span className="mb-1 block text-[11px] uppercase tracking-wide text-text-3/70">From</span>
67
- <code className="text-[10px] text-text-3 font-mono break-all">{walletAddress}</code>
68
- </div>
69
- <div>
70
- <span className="mb-1 block text-[11px] uppercase tracking-wide text-text-3/70">To</span>
71
- <code className="text-[10px] text-text-3 font-mono break-all">{transaction.toAddress}</code>
72
- </div>
73
- {transaction.memo && (
74
- <div>
75
- <span className="mb-1 block text-[11px] uppercase tracking-wide text-text-3/70">Reason</span>
76
- <p className="text-[12px] text-text-2">{transaction.memo}</p>
77
- </div>
78
- )}
79
- </div>
80
-
81
- {error && <p className="text-[11px] text-red-400">{error}</p>}
82
-
83
- <DialogFooter>
84
- <button
85
- type="button"
86
- onClick={() => handleDecision('deny')}
87
- disabled={submitting}
88
- className="flex-1 rounded-[12px] border border-white/[0.08] bg-surface px-4 py-2.5 text-[12px] font-600 text-text-3 transition-colors hover:border-red-400/30 hover:text-red-400 disabled:opacity-50"
89
- style={{ fontFamily: 'inherit' }}
90
- >
91
- Deny
92
- </button>
93
- <button
94
- type="button"
95
- onClick={() => handleDecision('approve')}
96
- disabled={submitting}
97
- className="flex-1 rounded-[12px] bg-accent px-4 py-2.5 text-[12px] font-600 text-white transition-all hover:brightness-110 disabled:opacity-50"
98
- style={{ fontFamily: 'inherit' }}
99
- >
100
- {submitting ? 'Processing...' : 'Approve & Send'}
101
- </button>
102
- </DialogFooter>
103
- </div>
104
- </DialogContent>
105
- </Dialog>
106
- )
107
- }