total-recall-brain 3.35.0 → 3.36.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 (66) hide show
  1. package/bin/total-recall.mjs +17 -4
  2. package/frontend/dist/assets/{index-BPrkIYkZ.js → index-DZ4ypNEl.js} +135 -135
  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/plugin/create.mjs +156 -11
  22. package/src/cli/plugin/index.mjs +5 -0
  23. package/src/core/embeddings.mjs +2 -0
  24. package/src/core/plugin-loader.mjs +18 -3
  25. package/src/core/plugin-store.mjs +122 -11
  26. package/src/core/surface.mjs +29 -1
  27. package/src/core/vault.mjs +6 -2
  28. package/src/server/route-manifest.json +22 -2
  29. package/src/server/routes/plugins-mesh.mjs +9 -1
  30. package/src/server/routes/plugins.mjs +65 -1
  31. package/frontend/src/pages/AutomationsPage.spec.tsx +0 -61
  32. package/frontend/src/pages/AutomationsPage.tsx +0 -354
  33. package/plugins/creative-search/README.md +0 -33
  34. package/plugins/creative-search/cli.mjs +0 -415
  35. package/plugins/creative-search/config.mjs +0 -129
  36. package/plugins/creative-search/generator.mjs +0 -13
  37. package/plugins/creative-search/plugin.json +0 -61
  38. package/plugins/creative-search/ui/DESIGN.md +0 -50
  39. package/plugins/creative-search/ui/csearch-main.js +0 -314
  40. package/plugins/creative-search/ui/csearch-settings.js +0 -392
  41. package/plugins/creative-search/ui/index.js +0 -2
  42. package/plugins/creative-search/ui/tokens.css +0 -34
  43. package/plugins/dsh/README.md +0 -20
  44. package/plugins/dsh/cli.mjs +0 -232
  45. package/plugins/dsh/generator.mjs +0 -65
  46. package/plugins/dsh/plugin.json +0 -57
  47. package/plugins/dsh/ui/DESIGN.md +0 -48
  48. package/plugins/dsh/ui/dsh-main.js +0 -226
  49. package/plugins/dsh/ui/dsh-status.js +0 -265
  50. package/plugins/dsh/ui/index.js +0 -2
  51. package/plugins/dsh/ui/tokens.css +0 -32
  52. package/plugins/git-sentinel/README.md +0 -29
  53. package/plugins/git-sentinel/cli.mjs +0 -89
  54. package/plugins/git-sentinel/plugin.json +0 -18
  55. package/plugins/operator-alerts/README.md +0 -32
  56. package/plugins/operator-alerts/cli.mjs +0 -57
  57. package/plugins/operator-alerts/notify-core.mjs +0 -216
  58. package/plugins/operator-alerts/plugin.json +0 -20
  59. package/plugins/skill-manager/README.md +0 -57
  60. package/plugins/skill-manager/cli.mjs +0 -123
  61. package/plugins/skill-manager/plugin.json +0 -25
  62. package/plugins/skill-manager/route.mjs +0 -106
  63. package/plugins/system-monitor/README.md +0 -28
  64. package/plugins/system-monitor/cli.mjs +0 -80
  65. package/plugins/system-monitor/generator.mjs +0 -19
  66. package/plugins/system-monitor/plugin.json +0 -29
@@ -1,17 +1,19 @@
1
1
  import { useState, type CSSProperties } from "react"
2
+ import { runPluginCommand } from "../../../api"
2
3
 
3
4
  const styles: Record<string, CSSProperties> = {
4
5
  container: {
5
- background: "linear-gradient(135deg, #0f1923, #1a1a2e)",
6
+ background: "linear-gradient(135deg, #0a1628, #1a1a2e)",
6
7
  borderRadius: "12px",
7
8
  padding: "24px",
8
- fontFamily: "var(--font-sans, system-ui, sans-serif)",
9
+ fontFamily: "var(--font-mono, 'SF Mono', monospace)",
9
10
  color: "#e0e0e0",
10
- maxWidth: "480px",
11
+ maxWidth: "580px",
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,136 +23,186 @@ const styles: Record<string, CSSProperties> = {
21
23
  letterSpacing: "1px",
22
24
  },
23
25
  badge: {
24
- background: "#3a1a1a",
25
- color: "#ff8a80",
26
+ background: "#2a1a3a",
27
+ color: "#ce93d8",
26
28
  padding: "4px 10px",
27
29
  borderRadius: "20px",
28
30
  fontSize: "11px",
31
+ fontWeight: 600,
29
32
  },
30
- confidence: {
33
+ table: {
34
+ width: "100%",
35
+ borderCollapse: "collapse" as const,
31
36
  marginBottom: "16px",
32
37
  },
33
- sliderRow: {
34
- display: "flex",
35
- alignItems: "center",
36
- gap: "12px",
37
- marginBottom: "8px",
38
+ th: {
39
+ color: "#888",
40
+ fontSize: "11px",
41
+ textTransform: "uppercase" as const,
42
+ padding: "8px",
43
+ textAlign: "left" as const,
44
+ borderBottom: "1px solid #2a2a4a",
38
45
  },
39
- slider: {
40
- flex: 1,
41
- WebkitAppearance: "none" as const,
42
- height: "6px",
43
- borderRadius: "3px",
44
- background: "#2a2a4a",
45
- outline: "none",
46
+ td: {
47
+ padding: "8px",
48
+ fontSize: "12px",
49
+ borderBottom: "1px solid #1a1a2e",
46
50
  },
47
- thresholdValue: {
48
- fontSize: "18px",
49
- fontWeight: 700,
50
- color: "#7c4dff",
51
- minWidth: "36px",
52
- textAlign: "center" as const,
51
+ slider: {
52
+ width: "100%",
53
+ accentColor: "#ab47bc",
53
54
  },
54
- stage: {
55
+ winnerBox: {
55
56
  background: "#0d1117",
56
- border: "1px solid #2a2a4a",
57
+ border: "1px solid #4a148c",
57
58
  borderRadius: "8px",
58
- padding: "12px 16px",
59
- marginBottom: "8px",
60
- },
61
- stageHeader: {
59
+ padding: "14px",
62
60
  display: "flex",
63
61
  justifyContent: "space-between",
64
- marginBottom: "6px",
65
- },
66
- stageName: {
67
- fontSize: "13px",
68
- fontWeight: 600,
69
- },
70
- stageStatus: {
71
- fontSize: "12px",
72
- },
73
- stageBar: {
74
- height: "4px",
75
- borderRadius: "2px",
76
- background: "#2a2a4a",
77
- overflow: "hidden" as const,
78
- },
79
- barFill: {
80
- height: "100%",
81
- borderRadius: "2px",
82
- transition: "width 0.3s ease",
62
+ alignItems: "center",
83
63
  },
84
- fallbackNote: {
85
- fontSize: "11px",
86
- color: "#888",
87
- marginTop: "12px",
88
- padding: "8px",
89
- border: "1px dashed #2a2a4a",
90
- borderRadius: "6px",
91
- textAlign: "center" as const,
64
+ score: {
65
+ fontSize: "18px",
66
+ fontWeight: 700,
67
+ color: "#e1bee7",
92
68
  },
93
69
  }
94
70
 
95
- interface DecisionStage {
96
- name: string
97
- score: number
98
- passes: boolean
99
- }
100
-
101
71
  export function DecisionPreview() {
102
- const [threshold, setThreshold] = useState(65)
72
+ const [weights, setWeights] = useState<Record<string, number>>({
73
+ Performance: 8,
74
+ Maintainability: 7,
75
+ Security: 9,
76
+ })
77
+
78
+ const [optAScores, setOptAScores] = useState<Record<string, number>>({
79
+ Performance: 9,
80
+ Maintainability: 7,
81
+ Security: 8,
82
+ })
83
+
84
+ const [optBScores, setOptBScores] = useState<Record<string, number>>({
85
+ Performance: 7,
86
+ Maintainability: 9,
87
+ Security: 9,
88
+ })
103
89
 
104
- const stages: DecisionStage[] = [
105
- { name: "Rule Match", score: 92, passes: 92 >= threshold },
106
- { name: "Semantic Coherence", score: 78, passes: 78 >= threshold },
107
- { name: "Mesh Consensus", score: 45, passes: 45 >= threshold },
108
- ]
90
+ const [evaluating, setEvaluating] = useState(false)
91
+ const [output, setOutput] = useState<string | null>(null)
109
92
 
110
- const allPass = stages.every((s) => s.passes)
93
+ const calcWeightedScore = (scores: Record<string, number>) => {
94
+ let sum = 0
95
+ let totalWeight = 0
96
+ for (const [k, w] of Object.entries(weights)) {
97
+ sum += (scores[k] || 0) * w
98
+ totalWeight += w
99
+ }
100
+ return totalWeight > 0 ? (sum / totalWeight).toFixed(2) : "0.00"
101
+ }
102
+
103
+ const scoreA = parseFloat(calcWeightedScore(optAScores))
104
+ const scoreB = parseFloat(calcWeightedScore(optBScores))
105
+ const winner = scoreA >= scoreB ? "Option A" : "Option B"
106
+
107
+ const handleRunEvaluation = async () => {
108
+ setEvaluating(true)
109
+ try {
110
+ const res = await runPluginCommand("decision", "eval", [
111
+ `OptionA=${scoreA}`,
112
+ `OptionB=${scoreB}`,
113
+ ])
114
+ setOutput(res.output || res.error || `Decision logged: Winner is ${winner}`)
115
+ } catch (err: any) {
116
+ setOutput(`Evaluation error: ${err?.message || "Check decision plugin"}`)
117
+ } finally {
118
+ setEvaluating(false)
119
+ }
120
+ }
111
121
 
112
122
  return (
113
123
  <div style={styles.container}>
114
124
  <div style={styles.header}>
115
- <span style={styles.label}>Decision Gate</span>
116
- <span style={{ ...styles.badge, color: allPass ? "#4caf50" : "#ff8a80", background: allPass ? "#1a3a1a" : "#3a1a1a" }}>
117
- {allPass ? "Passed" : "Blocked"}
118
- </span>
125
+ <span style={styles.label}>Typed Decision Matrix</span>
126
+ <span style={styles.badge}>Jev Evaluation</span>
119
127
  </div>
120
- <div style={styles.confidence}>
121
- <div style={{ fontSize: "11px", color: "#888", marginBottom: "6px" }}>Confidence Threshold</div>
122
- <div style={styles.sliderRow}>
123
- <input
124
- type="range"
125
- min={0}
126
- max={100}
127
- value={threshold}
128
- onChange={(e) => setThreshold(Number(e.target.value))}
129
- style={styles.slider}
130
- />
131
- <span style={styles.thresholdValue}>{threshold}%</span>
132
- </div>
133
- </div>
134
- <div>
135
- {stages.map((s) => (
136
- <div key={s.name} style={styles.stage}>
137
- <div style={styles.stageHeader}>
138
- <span style={styles.stageName}>{s.name}</span>
139
- <span style={{ ...styles.stageStatus, color: s.passes ? "#4caf50" : "#ff8a80" }}>
140
- {s.passes ? "✓" : "✗"} {s.score}%
141
- </span>
142
- </div>
143
- <div style={styles.stageBar}>
144
- <div style={{ ...styles.barFill, width: `${s.score}%`, background: s.passes ? "#4caf50" : "#ff5252" }} />
145
- </div>
128
+
129
+ <table style={styles.table}>
130
+ <thead>
131
+ <tr>
132
+ <th style={styles.th}>Criterion</th>
133
+ <th style={styles.th}>Weight</th>
134
+ <th style={styles.th}>Option A</th>
135
+ <th style={styles.th}>Option B</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody>
139
+ {Object.keys(weights).map((c) => (
140
+ <tr key={c}>
141
+ <td style={styles.td}>{c}</td>
142
+ <td style={styles.td}>
143
+ <input
144
+ type="range"
145
+ min="1"
146
+ max="10"
147
+ value={weights[c]}
148
+ style={styles.slider}
149
+ onChange={(e) => setWeights({ ...weights, [c]: parseInt(e.target.value, 10) })}
150
+ />
151
+ </td>
152
+ <td style={styles.td}>
153
+ <input
154
+ type="range"
155
+ min="1"
156
+ max="10"
157
+ value={optAScores[c]}
158
+ style={styles.slider}
159
+ onChange={(e) => setOptAScores({ ...optAScores, [c]: parseInt(e.target.value, 10) })}
160
+ />
161
+ </td>
162
+ <td style={styles.td}>
163
+ <input
164
+ type="range"
165
+ min="1"
166
+ max="10"
167
+ value={optBScores[c]}
168
+ style={styles.slider}
169
+ onChange={(e) => setOptBScores({ ...optBScores, [c]: parseInt(e.target.value, 10) })}
170
+ />
171
+ </td>
172
+ </tr>
173
+ ))}
174
+ </tbody>
175
+ </table>
176
+
177
+ <div style={styles.winnerBox}>
178
+ <div>
179
+ <div style={{ fontSize: "11px", color: "#888" }}>RANKED OUTCOME</div>
180
+ <div style={{ fontSize: "16px", fontWeight: 700, color: "#fff" }}>
181
+ {winner} (Score: {Math.max(scoreA, scoreB)})
146
182
  </div>
147
- ))}
148
- </div>
149
- <div style={styles.fallbackNote}>
150
- {allPass
151
- ? "All gates passed — executing primary route"
152
- : "Mesh consensus below threshold — activating fallback route"}
183
+ </div>
184
+ <button
185
+ style={{
186
+ background: "linear-gradient(135deg, #7b1fa2, #4a148c)",
187
+ border: "none",
188
+ borderRadius: "6px",
189
+ padding: "8px 16px",
190
+ color: "#fff",
191
+ fontSize: "12px",
192
+ cursor: "pointer",
193
+ }}
194
+ onClick={handleRunEvaluation}
195
+ disabled={evaluating}
196
+ >
197
+ {evaluating ? "Evaluating…" : "Evaluate Decision"}
198
+ </button>
153
199
  </div>
200
+
201
+ {output && (
202
+ <div style={{ marginTop: "12px", fontSize: "11px", color: "#ce93d8" }}>
203
+ {output}
204
+ </div>
205
+ )}
154
206
  </div>
155
207
  )
156
208
  }
@@ -1,18 +1,19 @@
1
- import { type CSSProperties } from "react"
1
+ import { useState, type CSSProperties } from "react"
2
2
 
3
3
  const styles: Record<string, CSSProperties> = {
4
4
  container: {
5
- background: "linear-gradient(135deg, #0f1923, #1a1a2e)",
5
+ background: "linear-gradient(135deg, #0a1628, #1a1a2e)",
6
6
  borderRadius: "12px",
7
7
  padding: "24px",
8
8
  fontFamily: "var(--font-sans, system-ui, sans-serif)",
9
9
  color: "#e0e0e0",
10
- maxWidth: "480px",
10
+ maxWidth: "540px",
11
11
  },
12
12
  header: {
13
13
  display: "flex",
14
14
  justifyContent: "space-between",
15
- marginBottom: "20px",
15
+ alignItems: "center",
16
+ marginBottom: "16px",
16
17
  },
17
18
  label: {
18
19
  color: "#888",
@@ -21,97 +22,130 @@ const styles: Record<string, CSSProperties> = {
21
22
  letterSpacing: "1px",
22
23
  },
23
24
  badge: {
24
- background: "#2a1a3a",
25
- color: "#ce93d8",
25
+ background: "#3a2a1a",
26
+ color: "#ffb74d",
26
27
  padding: "4px 10px",
27
28
  borderRadius: "20px",
28
29
  fontSize: "11px",
30
+ fontWeight: 600,
29
31
  },
30
- palette: {
31
- display: "flex",
32
+ controlsGrid: {
33
+ display: "grid",
34
+ gridTemplateColumns: "1fr 1fr",
32
35
  gap: "12px",
33
- marginBottom: "20px",
34
- flexWrap: "wrap" as const,
35
- },
36
- swatch: {
37
- width: "44px",
38
- height: "44px",
39
- borderRadius: "10px",
40
- border: "2px solid #2a2a4a",
41
- },
42
- typography: {
43
36
  marginBottom: "16px",
44
37
  },
45
- h1: {
46
- fontSize: "24px",
47
- fontWeight: 700,
48
- color: "#ffffff",
49
- marginBottom: "4px",
50
- },
51
- h2: {
52
- fontSize: "18px",
53
- fontWeight: 600,
54
- color: "#d0d0ff",
55
- marginBottom: "4px",
38
+ control: {
39
+ display: "flex",
40
+ flexDirection: "column",
41
+ gap: "4px",
56
42
  },
57
- bodyText: {
58
- fontSize: "13px",
43
+ ctlLabel: {
44
+ fontSize: "11px",
59
45
  color: "#aaa",
60
- lineHeight: 1.6,
61
46
  },
62
- glass: {
63
- background: "rgba(255, 255, 255, 0.05)",
64
- backdropFilter: "blur(12px)",
65
- border: "1px solid rgba(255, 255, 255, 0.1)",
66
- borderRadius: "10px",
67
- padding: "14px 20px",
68
- fontSize: "13px",
69
- color: "#ccc",
70
- },
71
- labelSm: {
72
- fontSize: "10px",
73
- color: "#666",
74
- textTransform: "uppercase" as const,
75
- letterSpacing: "1px",
76
- marginBottom: "8px",
47
+ input: {
48
+ background: "#0d1117",
49
+ border: "1px solid #2a2a4a",
50
+ borderRadius: "6px",
51
+ padding: "6px 10px",
52
+ color: "#fff",
53
+ fontSize: "12px",
54
+ fontFamily: "var(--font-mono, monospace)",
77
55
  },
78
56
  }
79
57
 
80
- const swatches = [
81
- { name: "Primary", color: "#7c4dff" },
82
- { name: "Secondary", color: "#00bfa5" },
83
- { name: "Accent", color: "#ff6d00" },
84
- { name: "Surface", color: "#1a1a2e" },
85
- { name: "Error", color: "#ff1744" },
86
- ]
87
-
88
58
  export function DesignPreview() {
59
+ const [primaryColor, setPrimaryColor] = useState("#ec4899")
60
+ const [borderRadius, setBorderRadius] = useState("10px")
61
+ const [surfaceBg, setSurfaceBg] = useState("#1e1e38")
62
+ const [accentText, setAccentText] = useState("Generative UI Active")
63
+
89
64
  return (
90
65
  <div style={styles.container}>
91
66
  <div style={styles.header}>
92
- <span style={styles.label}>Design Tokens</span>
93
- <span style={styles.badge}>DESIGN.md</span>
67
+ <span style={styles.label}>Design System & Token Playground</span>
68
+ <span style={styles.badge}>Live Tokens</span>
94
69
  </div>
95
- <div style={styles.labelSm}>Color Palette</div>
96
- <div style={styles.palette}>
97
- {swatches.map((s) => (
98
- <div key={s.name} title={s.name}>
99
- <div style={{ ...styles.swatch, background: s.color }} />
100
- <div style={{ fontSize: "9px", color: "#666", textAlign: "center" as const, marginTop: "4px" }}>{s.name}</div>
101
- </div>
102
- ))}
103
- </div>
104
- <div style={styles.labelSm}>Typography</div>
105
- <div style={styles.typography}>
106
- <div style={styles.h1}>Heading 1</div>
107
- <div style={styles.h2}>Heading 2</div>
108
- <div style={styles.bodyText}>
109
- Body text with a clean 400-weight font at 13px. Designed for readability at scale.
70
+
71
+ <div style={styles.controlsGrid}>
72
+ <div style={styles.control}>
73
+ <label style={styles.ctlLabel}>--color-primary</label>
74
+ <input
75
+ type="color"
76
+ value={primaryColor}
77
+ onChange={(e) => setPrimaryColor(e.target.value)}
78
+ style={{ ...styles.input, height: "34px", padding: "2px", cursor: "pointer" }}
79
+ />
80
+ </div>
81
+ <div style={styles.control}>
82
+ <label style={styles.ctlLabel}>--border-radius</label>
83
+ <select
84
+ style={styles.input}
85
+ value={borderRadius}
86
+ onChange={(e) => setBorderRadius(e.target.value)}
87
+ >
88
+ <option value="4px">4px (Subtle)</option>
89
+ <option value="10px">10px (Default)</option>
90
+ <option value="18px">18px (Smooth)</option>
91
+ <option value="28px">28px (Pill)</option>
92
+ </select>
93
+ </div>
94
+ <div style={styles.control}>
95
+ <label style={styles.ctlLabel}>--surface-bg</label>
96
+ <input
97
+ type="color"
98
+ value={surfaceBg}
99
+ onChange={(e) => setSurfaceBg(e.target.value)}
100
+ style={{ ...styles.input, height: "34px", padding: "2px", cursor: "pointer" }}
101
+ />
110
102
  </div>
111
103
  </div>
112
- <div style={styles.labelSm}>Glassmorphic Surface</div>
113
- <div style={styles.glass}>
114
- backdrop-filter: blur(12px) — the modern glass aesthetic
104
+
105
+ {/* Live Component styled solely by the active token values */}
106
+ <div
107
+ style={{
108
+ background: surfaceBg,
109
+ borderRadius: borderRadius,
110
+ border: `1px solid ${primaryColor}40`,
111
+ padding: "20px",
112
+ transition: "all 0.2s ease",
113
+ boxShadow: `0 4px 20px ${primaryColor}20`,
114
+ }}
115
+ >
116
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "10px" }}>
117
+ <span style={{ fontSize: "14px", fontWeight: 700, color: "#fff" }}>Dynamic Token Card</span>
118
+ <span
119
+ style={{
120
+ background: `${primaryColor}25`,
121
+ color: primaryColor,
122
+ borderRadius: borderRadius,
123
+ padding: "4px 8px",
124
+ fontSize: "11px",
125
+ fontWeight: 600,
126
+ }}
127
+ >
128
+ Active
129
+ </span>
130
+ </div>
131
+ <div style={{ fontSize: "12px", color: "#bbb", marginBottom: "14px" }}>
132
+ Custom elements consume DESIGN.md tokens without modifying plugin source code.
133
+ </div>
134
+ <button
135
+ style={{
136
+ background: primaryColor,
137
+ color: "#fff",
138
+ border: "none",
139
+ borderRadius: borderRadius,
140
+ padding: "8px 16px",
141
+ fontSize: "12px",
142
+ fontWeight: 600,
143
+ cursor: "pointer",
144
+ }}
145
+ onClick={() => setAccentText(`Updated ${new Date().toLocaleTimeString()}`)}
146
+ >
147
+ {accentText}
148
+ </button>
115
149
  </div>
116
150
  </div>
117
151
  )