total-recall-brain 3.35.0 → 3.37.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 (72) hide show
  1. package/bin/total-recall.mjs +17 -4
  2. package/frontend/dist/assets/index-CpvEw3iA.js +5786 -0
  3. package/frontend/dist/brand/plugins/phone.svg +20 -0
  4. package/frontend/dist/index.html +1 -1
  5. package/frontend/src/App.tsx +3 -30
  6. package/frontend/src/api/plugins.ts +18 -0
  7. package/frontend/src/components/plugins/previews/CodeQualityPreview.tsx +78 -86
  8. package/frontend/src/components/plugins/previews/ComposableCliPreview.tsx +74 -84
  9. package/frontend/src/components/plugins/previews/DecisionPreview.tsx +158 -106
  10. package/frontend/src/components/plugins/previews/DesignPreview.tsx +109 -75
  11. package/frontend/src/components/plugins/previews/DomainsPreview.tsx +69 -88
  12. package/frontend/src/components/plugins/previews/ImageGeneratorPreview.tsx +286 -0
  13. package/frontend/src/components/plugins/previews/PhonePreview.tsx +490 -76
  14. package/frontend/src/components/plugins/previews/SigningPreview.tsx +164 -50
  15. package/frontend/src/components/plugins/previews/TextPreview.tsx +85 -86
  16. package/frontend/src/components/plugins/previews/UserAutomationsPreview.tsx +30 -0
  17. package/frontend/src/components/plugins/previews/index.tsx +6 -1
  18. package/frontend/src/pages/PluginsPage.tsx +603 -136
  19. package/package.json +2 -5
  20. package/scaffold/.agent/skills/plugins/SKILL.md +200 -6
  21. package/src/cli/agent.mjs +59 -18
  22. package/src/cli/plugin/create.mjs +266 -13
  23. package/src/cli/plugin/index.mjs +5 -0
  24. package/src/cli/secret.mjs +28 -1
  25. package/src/core/agent-manager.mjs +47 -6
  26. package/src/core/cache-prune.mjs +60 -2
  27. package/src/core/embeddings.mjs +2 -0
  28. package/src/core/meta-harness.mjs +93 -6
  29. package/src/core/plugin-loader.mjs +20 -4
  30. package/src/core/plugin-store.mjs +122 -11
  31. package/src/core/surface.mjs +29 -1
  32. package/src/core/vault.mjs +6 -2
  33. package/src/server/route-manifest.json +22 -2
  34. package/src/server/routes/plugins-mesh.mjs +9 -1
  35. package/src/server/routes/plugins.mjs +65 -1
  36. package/frontend/dist/assets/index-BPrkIYkZ.js +0 -5786
  37. package/frontend/src/pages/AutomationsPage.spec.tsx +0 -61
  38. package/frontend/src/pages/AutomationsPage.tsx +0 -354
  39. package/plugins/creative-search/README.md +0 -33
  40. package/plugins/creative-search/cli.mjs +0 -415
  41. package/plugins/creative-search/config.mjs +0 -129
  42. package/plugins/creative-search/generator.mjs +0 -13
  43. package/plugins/creative-search/plugin.json +0 -61
  44. package/plugins/creative-search/ui/DESIGN.md +0 -50
  45. package/plugins/creative-search/ui/csearch-main.js +0 -314
  46. package/plugins/creative-search/ui/csearch-settings.js +0 -392
  47. package/plugins/creative-search/ui/index.js +0 -2
  48. package/plugins/creative-search/ui/tokens.css +0 -34
  49. package/plugins/dsh/README.md +0 -20
  50. package/plugins/dsh/cli.mjs +0 -232
  51. package/plugins/dsh/generator.mjs +0 -65
  52. package/plugins/dsh/plugin.json +0 -57
  53. package/plugins/dsh/ui/DESIGN.md +0 -48
  54. package/plugins/dsh/ui/dsh-main.js +0 -226
  55. package/plugins/dsh/ui/dsh-status.js +0 -265
  56. package/plugins/dsh/ui/index.js +0 -2
  57. package/plugins/dsh/ui/tokens.css +0 -32
  58. package/plugins/git-sentinel/README.md +0 -29
  59. package/plugins/git-sentinel/cli.mjs +0 -89
  60. package/plugins/git-sentinel/plugin.json +0 -18
  61. package/plugins/operator-alerts/README.md +0 -32
  62. package/plugins/operator-alerts/cli.mjs +0 -57
  63. package/plugins/operator-alerts/notify-core.mjs +0 -216
  64. package/plugins/operator-alerts/plugin.json +0 -20
  65. package/plugins/skill-manager/README.md +0 -57
  66. package/plugins/skill-manager/cli.mjs +0 -123
  67. package/plugins/skill-manager/plugin.json +0 -25
  68. package/plugins/skill-manager/route.mjs +0 -106
  69. package/plugins/system-monitor/README.md +0 -28
  70. package/plugins/system-monitor/cli.mjs +0 -80
  71. package/plugins/system-monitor/generator.mjs +0 -19
  72. package/plugins/system-monitor/plugin.json +0 -29
@@ -1,4 +1,5 @@
1
- import { type CSSProperties } from "react"
1
+ import { useState, useRef, useEffect, type CSSProperties } from "react"
2
+ import { runPluginCommand } from "../../../api"
2
3
 
3
4
  const styles: Record<string, CSSProperties> = {
4
5
  container: {
@@ -12,7 +13,8 @@ const styles: Record<string, CSSProperties> = {
12
13
  header: {
13
14
  display: "flex",
14
15
  justifyContent: "space-between",
15
- marginBottom: "20px",
16
+ alignItems: "center",
17
+ marginBottom: "16px",
16
18
  },
17
19
  label: {
18
20
  color: "#888",
@@ -26,84 +28,196 @@ const styles: Record<string, CSSProperties> = {
26
28
  padding: "4px 10px",
27
29
  borderRadius: "20px",
28
30
  fontSize: "11px",
31
+ fontWeight: 600,
29
32
  },
30
33
  docFrame: {
31
34
  background: "#0d1117",
32
35
  border: "1px solid #2a2a4a",
33
36
  borderRadius: "8px",
34
37
  padding: "16px",
35
- marginBottom: "12px",
38
+ marginBottom: "16px",
36
39
  },
37
40
  docTitle: {
38
- fontSize: "15px",
41
+ fontSize: "14px",
39
42
  fontWeight: 600,
40
- marginBottom: "8px",
43
+ marginBottom: "6px",
41
44
  color: "#c0c0ff",
42
45
  },
43
- field: {
44
- display: "flex",
45
- justifyContent: "space-between",
46
- alignItems: "center",
47
- padding: "10px 0",
48
- borderBottom: "1px solid #1e1e3a",
46
+ canvasBox: {
47
+ background: "#141428",
48
+ border: "1px dashed #4a4a7a",
49
+ borderRadius: "8px",
50
+ padding: "8px",
51
+ marginBottom: "12px",
52
+ textAlign: "center" as const,
49
53
  },
50
- fieldLabel: {
51
- fontSize: "13px",
52
- color: "#aaa",
54
+ canvas: {
55
+ background: "#0d1117",
56
+ borderRadius: "4px",
57
+ cursor: "crosshair",
58
+ display: "block",
59
+ margin: "0 auto",
53
60
  },
54
- fieldValue: {
55
- fontSize: "13px",
56
- color: "#d0d0d0",
61
+ actions: {
62
+ display: "flex",
63
+ gap: "8px",
64
+ marginBottom: "16px",
57
65
  },
58
- sigBlock: {
59
- background: "#1a1a2e",
60
- border: "1px dashed #4a4a7a",
66
+ signBtn: {
67
+ background: "linear-gradient(135deg, #2e7d32, #1b5e20)",
68
+ border: "none",
61
69
  borderRadius: "6px",
62
- padding: "20px",
63
- textAlign: "center" as const,
64
- marginTop: "8px",
65
- position: "relative" as const,
70
+ padding: "10px 20px",
71
+ color: "#fff",
72
+ fontSize: "13px",
73
+ fontWeight: 600,
74
+ cursor: "pointer",
75
+ flex: 1,
66
76
  },
67
- sigLine: {
68
- borderTop: "1px solid #4a4a7a",
69
- width: "180px",
70
- margin: "0 auto 4px",
77
+ clearBtn: {
78
+ background: "#2a2a4a",
79
+ border: "none",
80
+ borderRadius: "6px",
81
+ padding: "10px 16px",
82
+ color: "#aaa",
83
+ fontSize: "13px",
84
+ cursor: "pointer",
71
85
  },
72
- sigPrompt: {
86
+ receipt: {
87
+ background: "#090d13",
88
+ border: "1px solid #1a3a1a",
89
+ borderRadius: "8px",
90
+ padding: "12px",
73
91
  fontSize: "11px",
74
- color: "#888",
75
- marginTop: "16px",
92
+ fontFamily: "var(--font-mono, monospace)",
93
+ color: "#81c784",
94
+ wordBreak: "break-all" as const,
76
95
  },
77
96
  }
78
97
 
79
98
  export function SigningPreview() {
99
+ const canvasRef = useRef<HTMLCanvasElement | null>(null)
100
+ const [isDrawing, setIsDrawing] = useState(false)
101
+ const [hasSignature, setHasSignature] = useState(false)
102
+ const [status, setStatus] = useState<string | null>(null)
103
+ const [signatureHash, setSignatureHash] = useState<string | null>(null)
104
+
105
+ useEffect(() => {
106
+ const canvas = canvasRef.current
107
+ if (!canvas) return
108
+ const ctx = canvas.getContext("2d")
109
+ if (!ctx) return
110
+ ctx.strokeStyle = "#80d8ff"
111
+ ctx.lineWidth = 2
112
+ ctx.lineCap = "round"
113
+ }, [])
114
+
115
+ const startDrawing = (e: React.MouseEvent<HTMLCanvasElement>) => {
116
+ const canvas = canvasRef.current
117
+ if (!canvas) return
118
+ const ctx = canvas.getContext("2d")
119
+ if (!ctx) return
120
+ const rect = canvas.getBoundingClientRect()
121
+ ctx.beginPath()
122
+ ctx.moveTo(e.clientX - rect.left, e.clientY - rect.top)
123
+ setIsDrawing(true)
124
+ setHasSignature(true)
125
+ }
126
+
127
+ const draw = (e: React.MouseEvent<HTMLCanvasElement>) => {
128
+ if (!isDrawing) return
129
+ const canvas = canvasRef.current
130
+ if (!canvas) return
131
+ const ctx = canvas.getContext("2d")
132
+ if (!ctx) return
133
+ const rect = canvas.getBoundingClientRect()
134
+ ctx.lineTo(e.clientX - rect.left, e.clientY - rect.top)
135
+ ctx.stroke()
136
+ }
137
+
138
+ const stopDrawing = () => {
139
+ setIsDrawing(false)
140
+ }
141
+
142
+ const clearCanvas = () => {
143
+ const canvas = canvasRef.current
144
+ if (!canvas) return
145
+ const ctx = canvas.getContext("2d")
146
+ if (!ctx) return
147
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
148
+ setHasSignature(false)
149
+ setStatus(null)
150
+ setSignatureHash(null)
151
+ }
152
+
153
+ const handleSign = async () => {
154
+ if (!hasSignature) return
155
+ setStatus("Generating cryptographic digest...")
156
+
157
+ try {
158
+ const canvas = canvasRef.current
159
+ const dataUrl = canvas?.toDataURL() || "empty"
160
+ const encoder = new TextEncoder()
161
+ const data = encoder.encode(dataUrl + Date.now().toString())
162
+ const hashBuffer = await window.crypto.subtle.digest("SHA-256", data)
163
+ const hashArray = Array.from(new Uint8Array(hashBuffer))
164
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("")
165
+ setSignatureHash(hashHex)
166
+
167
+ const res = await runPluginCommand("signing", "verify", [hashHex])
168
+ setStatus(res.output || `Cryptographically verified signature digest: ${hashHex.slice(0, 16)}…`)
169
+ } catch (err: any) {
170
+ setStatus(`Signing error: ${err?.message || "Cryptographic operation failed"}`)
171
+ }
172
+ }
173
+
80
174
  return (
81
175
  <div style={styles.container}>
82
176
  <div style={styles.header}>
83
- <span style={styles.label}>Signature Pad</span>
84
- <span style={styles.badge}>Documenso</span>
177
+ <span style={styles.label}>Cryptographic Document Signing</span>
178
+ <span style={styles.badge}>Live Canvas</span>
85
179
  </div>
180
+
86
181
  <div style={styles.docFrame}>
87
- <div style={styles.docTitle}>Service Agreement — v3.2</div>
88
- <div style={styles.field}>
89
- <span style={styles.fieldLabel}>Recipient</span>
90
- <span style={styles.fieldValue}>operator@mesh.local</span>
91
- </div>
92
- <div style={styles.field}>
93
- <span style={styles.fieldLabel}>Expires</span>
94
- <span style={styles.fieldValue}>2026-12-31</span>
95
- </div>
96
- <div style={styles.field}>
97
- <span style={styles.fieldLabel}>Pages</span>
98
- <span style={styles.fieldValue}>12</span>
182
+ <div style={styles.docTitle}>Verification Certificate — Total Recall Node</div>
183
+ <div style={{ fontSize: "12px", color: "#888" }}>Documenso & SSSS Cryptographic Carrier</div>
184
+ </div>
185
+
186
+ <div style={styles.canvasBox}>
187
+ <canvas
188
+ ref={canvasRef}
189
+ width={440}
190
+ height={120}
191
+ style={styles.canvas}
192
+ onMouseDown={startDrawing}
193
+ onMouseMove={draw}
194
+ onMouseUp={stopDrawing}
195
+ onMouseLeave={stopDrawing}
196
+ />
197
+ <div style={{ fontSize: "11px", color: "#666", marginTop: "6px" }}>
198
+ Draw signature above to authorize cryptographic verification
99
199
  </div>
100
200
  </div>
101
- <div style={styles.sigBlock}>
102
- <div style={{ fontSize: "12px", color: "#888", marginBottom: "12px" }}>Drop signature here</div>
103
- <div style={styles.sigLine} />
104
- <div style={{ fontSize: "13px", fontWeight: 500, color: "#d0d0ff" }}>operator@mesh.local</div>
105
- <div style={styles.sigPrompt}>Click to place signature</div>
201
+
202
+ <div style={styles.actions}>
203
+ <button style={styles.clearBtn} onClick={clearCanvas}>
204
+ Clear
205
+ </button>
206
+ <button
207
+ style={styles.signBtn}
208
+ onClick={handleSign}
209
+ disabled={!hasSignature}
210
+ >
211
+ Sign & Verify Hash
212
+ </button>
106
213
  </div>
214
+
215
+ {signatureHash && (
216
+ <div style={styles.receipt}>
217
+ <div><strong>SHA-256 Receipt:</strong> {signatureHash}</div>
218
+ <div style={{ marginTop: "4px", color: "#a5d6a7" }}>{status}</div>
219
+ </div>
220
+ )}
107
221
  </div>
108
222
  )
109
223
  }
@@ -1,4 +1,5 @@
1
- import { type CSSProperties } from "react"
1
+ import { useState, type CSSProperties } from "react"
2
+ import { runPluginCommand } from "../../../api"
2
3
 
3
4
  const styles: Record<string, CSSProperties> = {
4
5
  container: {
@@ -7,11 +8,12 @@ const styles: Record<string, CSSProperties> = {
7
8
  padding: "24px",
8
9
  fontFamily: "var(--font-sans, system-ui, sans-serif)",
9
10
  color: "#e0e0e0",
10
- maxWidth: "480px",
11
+ maxWidth: "500px",
11
12
  },
12
13
  header: {
13
14
  display: "flex",
14
15
  justifyContent: "space-between",
16
+ alignItems: "center",
15
17
  marginBottom: "16px",
16
18
  },
17
19
  label: {
@@ -21,124 +23,121 @@ const styles: Record<string, CSSProperties> = {
21
23
  letterSpacing: "1px",
22
24
  },
23
25
  badge: {
24
- background: "#1a2a1a",
25
- color: "#4caf50",
26
+ background: "#1a3a2a",
27
+ color: "#00e676",
26
28
  padding: "4px 10px",
27
29
  borderRadius: "20px",
28
30
  fontSize: "11px",
29
- },
30
- contactBar: {
31
- display: "flex",
32
- alignItems: "center",
33
- gap: "10px",
34
- padding: "10px 0",
35
- marginBottom: "12px",
36
- borderBottom: "1px solid #2a2a4a",
37
- },
38
- avatar: {
39
- width: "32px",
40
- height: "32px",
41
- borderRadius: "50%",
42
- background: "#2a2a5a",
43
- display: "flex",
44
- alignItems: "center",
45
- justifyContent: "center",
46
- fontSize: "14px",
47
- fontWeight: 700,
48
- color: "#c0c0ff",
49
- },
50
- contactName: {
51
- fontSize: "14px",
52
31
  fontWeight: 600,
53
32
  },
54
- thread: {
33
+ threadBox: {
34
+ background: "#0d1117",
35
+ border: "1px solid #2a2a4a",
36
+ borderRadius: "8px",
37
+ padding: "12px",
38
+ maxHeight: "180px",
39
+ overflowY: "auto" as const,
40
+ marginBottom: "14px",
55
41
  display: "flex",
56
- flexDirection: "column" as const,
42
+ flexDirection: "column",
57
43
  gap: "8px",
58
- marginBottom: "12px",
59
44
  },
60
- bubbleIn: {
61
- background: "#1e1e3a",
62
- border: "1px solid #2a2a4a",
63
- borderRadius: "12px 12px 12px 4px",
64
- padding: "10px 14px",
65
- fontSize: "13px",
66
- color: "#ccc",
67
- maxWidth: "80%",
68
- alignSelf: "flex-start" as const,
69
- },
70
- bubbleOut: {
71
- background: "#2a2a5a",
72
- border: "1px solid #3a3a7a",
73
- borderRadius: "12px 12px 4px 12px",
74
- padding: "10px 14px",
45
+ msgBubble: {
46
+ background: "#1e1e38",
47
+ padding: "8px 12px",
48
+ borderRadius: "8px",
75
49
  fontSize: "13px",
76
- color: "#d0d0ff",
77
- maxWidth: "80%",
78
- alignSelf: "flex-end" as const,
50
+ alignSelf: "flex-end",
51
+ maxWidth: "85%",
52
+ border: "1px solid #3a3a6a",
79
53
  },
80
- inputBar: {
54
+ inputRow: {
81
55
  display: "flex",
56
+ flexDirection: "column",
82
57
  gap: "8px",
83
58
  },
84
59
  input: {
85
- flex: 1,
86
60
  background: "#0d1117",
87
61
  border: "1px solid #2a2a4a",
88
- borderRadius: "8px",
89
- padding: "10px 14px",
90
- color: "#e0e0e0",
62
+ borderRadius: "6px",
63
+ padding: "8px 12px",
64
+ color: "#fff",
91
65
  fontSize: "13px",
92
- outline: "none",
66
+ fontFamily: "inherit",
93
67
  },
94
- sendBtn: {
95
- background: "#7c4dff",
68
+ btn: {
69
+ background: "linear-gradient(135deg, #00c853, #1b5e20)",
96
70
  border: "none",
97
- borderRadius: "8px",
98
- padding: "10px 18px",
71
+ borderRadius: "6px",
72
+ padding: "10px 16px",
99
73
  color: "#fff",
100
74
  fontSize: "13px",
101
75
  fontWeight: 600,
102
76
  cursor: "pointer",
103
77
  },
104
- timeLabel: {
105
- fontSize: "10px",
106
- color: "#555",
107
- padding: "4px 0",
108
- },
109
78
  }
110
79
 
111
80
  export function TextPreview() {
81
+ const [recipient, setRecipient] = useState("+1-555-0199")
82
+ const [message, setMessage] = useState("")
83
+ const [messages, setMessages] = useState<Array<{ text: string; time: string }>>([
84
+ { text: "Total Recall SMS Bridge initialized.", time: "10:00 AM" }
85
+ ])
86
+ const [sending, setSending] = useState(false)
87
+
88
+ const handleSend = async () => {
89
+ if (!message.trim()) return
90
+ setSending(true)
91
+ const newMsg = { text: message.trim(), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) }
92
+ setMessages((prev) => [...prev, newMsg])
93
+ const body = message.trim()
94
+ setMessage("")
95
+
96
+ try {
97
+ await runPluginCommand("text", "send", [recipient, body])
98
+ } catch {
99
+ // handled gracefully in thread
100
+ } finally {
101
+ setSending(false)
102
+ }
103
+ }
104
+
112
105
  return (
113
106
  <div style={styles.container}>
114
107
  <div style={styles.header}>
115
- <span style={styles.label}>SMS Messaging</span>
116
- <span style={styles.badge}>Telnyx</span>
108
+ <span style={styles.label}>SMS & Conversational Messaging</span>
109
+ <span style={styles.badge}>{sending ? "Sending…" : "Connected"}</span>
117
110
  </div>
118
- <div style={styles.contactBar}>
119
- <div style={styles.avatar}>JD</div>
120
- <div>
121
- <div style={styles.contactName}>Jane Doe</div>
122
- <div style={{ fontSize: "11px", color: "#4caf50" }}>Online</div>
123
- </div>
111
+
112
+ <div style={styles.threadBox}>
113
+ {messages.map((m, i) => (
114
+ <div key={i} style={styles.msgBubble}>
115
+ <div>{m.text}</div>
116
+ <div style={{ fontSize: "10px", color: "#888", textAlign: "right", marginTop: "4px" }}>{m.time}</div>
117
+ </div>
118
+ ))}
124
119
  </div>
125
- <div style={styles.thread}>
126
- <div style={styles.bubbleIn}>
127
- The deployment completed. Can you verify the DNS propagation?
128
- </div>
129
- <div style={styles.timeLabel}>10:32 AM</div>
130
- <div style={styles.bubbleOut}>
131
- Checking now — the A record shows the new origin IP.
132
- </div>
133
- <div style={styles.timeLabel}>10:34 AM</div>
134
- <div style={styles.bubbleIn}>
135
- Confirmed. SSL certificate is valid too.
120
+
121
+ <div style={styles.inputRow}>
122
+ <input
123
+ style={styles.input}
124
+ value={recipient}
125
+ onChange={(e) => setRecipient(e.target.value)}
126
+ placeholder="Recipient Phone Number"
127
+ />
128
+ <div style={{ display: "flex", gap: "8px" }}>
129
+ <input
130
+ style={{ ...styles.input, flex: 1 }}
131
+ value={message}
132
+ onChange={(e) => setMessage(e.target.value)}
133
+ placeholder="Type SMS message..."
134
+ onKeyDown={(e) => e.key === "Enter" && handleSend()}
135
+ />
136
+ <button style={styles.btn} onClick={handleSend} disabled={sending || !message.trim()}>
137
+ Send
138
+ </button>
136
139
  </div>
137
140
  </div>
138
- <div style={styles.inputBar}>
139
- <input style={styles.input} placeholder="Type a message..." />
140
- <button style={styles.sendBtn}>Send</button>
141
- </div>
142
141
  </div>
143
142
  )
144
143
  }
@@ -0,0 +1,30 @@
1
+ import { useEffect, useState, type CSSProperties } from 'react'
2
+
3
+ const tokens = {
4
+ '--color-text': 'var(--text-primary)',
5
+ '--color-text-secondary': 'var(--text-secondary)',
6
+ '--color-surface': 'var(--bg-secondary)',
7
+ '--color-border': 'var(--border)',
8
+ '--color-success': 'var(--success)',
9
+ '--color-error': 'var(--error)',
10
+ '--spacing-md': '12px',
11
+ '--radius-md': '8px',
12
+ } as CSSProperties
13
+
14
+ export function UserAutomationsPreview() {
15
+ const [error, setError] = useState('')
16
+ const [ready, setReady] = useState(false)
17
+ useEffect(() => {
18
+ let active = true
19
+ const moduleUrl = '/api/plugins/user-automations/ui/automations'
20
+ import(/* @vite-ignore */ moduleUrl)
21
+ .then(() => { if (active) setReady(true) })
22
+ .catch((cause) => { if (active) setError(cause instanceof Error ? cause.message : String(cause)) })
23
+ return () => { active = false }
24
+ }, [])
25
+ if (error) return <p role="alert">Automation plugin unavailable: {error}</p>
26
+ if (!ready) return <p>Loading user automations…</p>
27
+ return <div style={tokens} ref={(element) => {
28
+ if (element && !element.firstChild) element.append(document.createElement('tr-user-automations'))
29
+ }} />
30
+ }
@@ -14,6 +14,8 @@ import { TextPreview } from "./TextPreview"
14
14
  import { CodeQualityPreview } from "./CodeQualityPreview"
15
15
  import { ComposableCliPreview } from "./ComposableCliPreview"
16
16
  import { DecisionPreview } from "./DecisionPreview"
17
+ import { ImageGeneratorPreview } from "./ImageGeneratorPreview"
18
+ import { UserAutomationsPreview } from "./UserAutomationsPreview"
17
19
  import type { FC } from "react"
18
20
 
19
21
  /**
@@ -40,6 +42,9 @@ export const previewRegistry: Record<string, FC> = {
40
42
  "composable-cli": ComposableCliPreview,
41
43
  "tr-plugin-decision": DecisionPreview,
42
44
  "decision": DecisionPreview,
45
+ "image-generator": ImageGeneratorPreview,
46
+ "tr-plugin-image-generator": ImageGeneratorPreview,
47
+ "user-automations": UserAutomationsPreview,
43
48
  }
44
49
 
45
50
  /**
@@ -80,4 +85,4 @@ export function PreviewFallback({ pluginId }: { pluginId: string }) {
80
85
  </div>
81
86
  </div>
82
87
  )
83
- }
88
+ }