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.
- package/bin/total-recall.mjs +17 -4
- package/frontend/dist/assets/index-CpvEw3iA.js +5786 -0
- package/frontend/dist/brand/plugins/phone.svg +20 -0
- package/frontend/dist/index.html +1 -1
- package/frontend/src/App.tsx +3 -30
- package/frontend/src/api/plugins.ts +18 -0
- package/frontend/src/components/plugins/previews/CodeQualityPreview.tsx +78 -86
- package/frontend/src/components/plugins/previews/ComposableCliPreview.tsx +74 -84
- package/frontend/src/components/plugins/previews/DecisionPreview.tsx +158 -106
- package/frontend/src/components/plugins/previews/DesignPreview.tsx +109 -75
- package/frontend/src/components/plugins/previews/DomainsPreview.tsx +69 -88
- package/frontend/src/components/plugins/previews/ImageGeneratorPreview.tsx +286 -0
- package/frontend/src/components/plugins/previews/PhonePreview.tsx +490 -76
- package/frontend/src/components/plugins/previews/SigningPreview.tsx +164 -50
- package/frontend/src/components/plugins/previews/TextPreview.tsx +85 -86
- package/frontend/src/components/plugins/previews/UserAutomationsPreview.tsx +30 -0
- package/frontend/src/components/plugins/previews/index.tsx +6 -1
- package/frontend/src/pages/PluginsPage.tsx +603 -136
- package/package.json +2 -5
- package/scaffold/.agent/skills/plugins/SKILL.md +200 -6
- package/src/cli/agent.mjs +59 -18
- package/src/cli/plugin/create.mjs +266 -13
- package/src/cli/plugin/index.mjs +5 -0
- package/src/cli/secret.mjs +28 -1
- package/src/core/agent-manager.mjs +47 -6
- package/src/core/cache-prune.mjs +60 -2
- package/src/core/embeddings.mjs +2 -0
- package/src/core/meta-harness.mjs +93 -6
- package/src/core/plugin-loader.mjs +20 -4
- package/src/core/plugin-store.mjs +122 -11
- package/src/core/surface.mjs +29 -1
- package/src/core/vault.mjs +6 -2
- package/src/server/route-manifest.json +22 -2
- package/src/server/routes/plugins-mesh.mjs +9 -1
- package/src/server/routes/plugins.mjs +65 -1
- package/frontend/dist/assets/index-BPrkIYkZ.js +0 -5786
- package/frontend/src/pages/AutomationsPage.spec.tsx +0 -61
- package/frontend/src/pages/AutomationsPage.tsx +0 -354
- package/plugins/creative-search/README.md +0 -33
- package/plugins/creative-search/cli.mjs +0 -415
- package/plugins/creative-search/config.mjs +0 -129
- package/plugins/creative-search/generator.mjs +0 -13
- package/plugins/creative-search/plugin.json +0 -61
- package/plugins/creative-search/ui/DESIGN.md +0 -50
- package/plugins/creative-search/ui/csearch-main.js +0 -314
- package/plugins/creative-search/ui/csearch-settings.js +0 -392
- package/plugins/creative-search/ui/index.js +0 -2
- package/plugins/creative-search/ui/tokens.css +0 -34
- package/plugins/dsh/README.md +0 -20
- package/plugins/dsh/cli.mjs +0 -232
- package/plugins/dsh/generator.mjs +0 -65
- package/plugins/dsh/plugin.json +0 -57
- package/plugins/dsh/ui/DESIGN.md +0 -48
- package/plugins/dsh/ui/dsh-main.js +0 -226
- package/plugins/dsh/ui/dsh-status.js +0 -265
- package/plugins/dsh/ui/index.js +0 -2
- package/plugins/dsh/ui/tokens.css +0 -32
- package/plugins/git-sentinel/README.md +0 -29
- package/plugins/git-sentinel/cli.mjs +0 -89
- package/plugins/git-sentinel/plugin.json +0 -18
- package/plugins/operator-alerts/README.md +0 -32
- package/plugins/operator-alerts/cli.mjs +0 -57
- package/plugins/operator-alerts/notify-core.mjs +0 -216
- package/plugins/operator-alerts/plugin.json +0 -20
- package/plugins/skill-manager/README.md +0 -57
- package/plugins/skill-manager/cli.mjs +0 -123
- package/plugins/skill-manager/plugin.json +0 -25
- package/plugins/skill-manager/route.mjs +0 -106
- package/plugins/system-monitor/README.md +0 -28
- package/plugins/system-monitor/cli.mjs +0 -80
- package/plugins/system-monitor/generator.mjs +0 -19
- package/plugins/system-monitor/plugin.json +0 -29
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="phoneBg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#10b981"/>
|
|
5
|
+
<stop offset="100%" stop-color="#047857"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="phoneGleam" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
8
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.3"/>
|
|
9
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
<rect width="64" height="64" rx="14" fill="url(#phoneBg)"/>
|
|
13
|
+
<rect width="64" height="32" rx="14" fill="url(#phoneGleam)"/>
|
|
14
|
+
<rect x="1" y="1" width="62" height="62" rx="13" fill="none" stroke="#6ee7b7" stroke-width="1.5" stroke-opacity="0.4"/>
|
|
15
|
+
<!-- Phone Handset -->
|
|
16
|
+
<path d="M22 20c0-1.1.9-2 2-2h4.5c1 0 1.9.7 2 1.7l.8 5.2c.1 1-.4 2-1.3 2.5l-2.4 1.4c1.8 3.6 4.7 6.5 8.3 8.3l1.4-2.4c.5-.9 1.5-1.4 2.5-1.3l5.2.8c1 .1 1.7 1 1.7 2V40c0 1.1-.9 2-2 2-12.7 0-23-10.3-23-23v-1z" fill="#ffffff"/>
|
|
17
|
+
<!-- Signal Waves -->
|
|
18
|
+
<path d="M37 18c3.9 1.2 7 4.3 8.2 8.2" fill="none" stroke="#a7f3d0" stroke-width="2.5" stroke-linecap="round"/>
|
|
19
|
+
<path d="M41 14c5.8 1.9 10.3 6.4 12.2 12.2" fill="none" stroke="#a7f3d0" stroke-width="2.5" stroke-linecap="round" stroke-opacity="0.7"/>
|
|
20
|
+
</svg>
|
package/frontend/dist/index.html
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
18
18
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
19
19
|
<title>Total Recall — Portable Memory</title>
|
|
20
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
+
<script type="module" crossorigin src="/assets/index-CpvEw3iA.js"></script>
|
|
21
21
|
<link rel="stylesheet" crossorigin href="/assets/index-C7_Xpk27.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
package/frontend/src/App.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
2
|
import { BrowserRouter, Routes, Route, NavLink, Navigate, useLocation } from 'react-router-dom'
|
|
3
3
|
import './App.css'
|
|
4
|
-
import { getApiBase, setApiBase, checkSession, logout, registerUnauthedCallback, fetchHealth
|
|
4
|
+
import { getApiBase, setApiBase, checkSession, logout, registerUnauthedCallback, fetchHealth } from './api'
|
|
5
5
|
import type { HealthData } from './types'
|
|
6
6
|
import LoginPage from './pages/LoginPage'
|
|
7
7
|
import ChatPage from './pages/ChatPage'
|
|
@@ -87,12 +87,6 @@ interface SidebarProps {
|
|
|
87
87
|
const getNavLinkClass = ({ isActive }: { isActive: boolean }) => `nav-link ${isActive ? 'active' : ''}`;
|
|
88
88
|
|
|
89
89
|
function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProps) {
|
|
90
|
-
const [plugins, setPlugins] = useState<PluginInfo[]>([])
|
|
91
|
-
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
fetchPlugins().then(setPlugins).catch(() => {})
|
|
94
|
-
}, [])
|
|
95
|
-
|
|
96
90
|
return (
|
|
97
91
|
<aside className="sidebar">
|
|
98
92
|
<div className="sidebar-brand" style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 14px' }}>
|
|
@@ -148,6 +142,7 @@ function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProp
|
|
|
148
142
|
Tasks
|
|
149
143
|
</NavLink>
|
|
150
144
|
|
|
145
|
+
|
|
151
146
|
<div className="nav-section-label">Connect</div>
|
|
152
147
|
<NavLink to="/integrations" className={getNavLinkClass} id="nav-integrations">
|
|
153
148
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
|
|
@@ -178,28 +173,6 @@ function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProp
|
|
|
178
173
|
Plugins
|
|
179
174
|
</NavLink>
|
|
180
175
|
|
|
181
|
-
{plugins.length > 0 && (
|
|
182
|
-
<>
|
|
183
|
-
<div className="nav-section-label">Plugins</div>
|
|
184
|
-
{plugins.map((p) => (
|
|
185
|
-
<NavLink
|
|
186
|
-
key={p.id}
|
|
187
|
-
to={`/plugins?id=${encodeURIComponent(p.id)}`}
|
|
188
|
-
className={getNavLinkClass}
|
|
189
|
-
id={`nav-plugin-${p.id}`}
|
|
190
|
-
title={p.description}
|
|
191
|
-
>
|
|
192
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
|
|
193
|
-
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
|
|
194
|
-
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
|
195
|
-
<line x1="12" y1="22.08" x2="12" y2="12" />
|
|
196
|
-
</svg>
|
|
197
|
-
{p.name}
|
|
198
|
-
</NavLink>
|
|
199
|
-
))}
|
|
200
|
-
</>
|
|
201
|
-
)}
|
|
202
|
-
|
|
203
176
|
<div className="nav-section-label">Account</div>
|
|
204
177
|
<NavLink to="/network" className={getNavLinkClass} id="nav-network">
|
|
205
178
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
|
|
@@ -450,7 +423,7 @@ function MainContent({ activeBrainId, onBrainChange }: { activeBrainId: string;
|
|
|
450
423
|
{/* Legacy OS-control-plane routes → core product */}
|
|
451
424
|
<Route path="/vault" element={<Navigate to="/memory" replace />} />
|
|
452
425
|
<Route path="/inbox" element={<Navigate to="/tasks" replace />} />
|
|
453
|
-
<Route path="/automations" element={<Navigate to="/
|
|
426
|
+
<Route path="/automations" element={<Navigate to="/plugins?id=user-automations" replace />} />
|
|
454
427
|
<Route path="/files" element={<Navigate to="/memory" replace />} />
|
|
455
428
|
<Route path="/sandbox" element={<Navigate to="/memory" replace />} />
|
|
456
429
|
<Route path="/models" element={<Navigate to="/settings" replace />} />
|
|
@@ -50,6 +50,10 @@ export interface PluginInfo {
|
|
|
50
50
|
openwiki_hubs: Array<{ title?: string; path: string }>
|
|
51
51
|
cli: { command: string | null; subcommands: Array<{ name: string; description?: string }> } | null
|
|
52
52
|
has_generator: boolean
|
|
53
|
+
branding?: { icon?: string | null; image?: string | null; color?: string | null; badge?: string | null }
|
|
54
|
+
locked?: boolean
|
|
55
|
+
store_deployed?: boolean
|
|
56
|
+
secrets?: Array<{ key: string; description?: string; required?: boolean }>
|
|
53
57
|
manifest?: Record<string, unknown>
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -63,6 +67,8 @@ export interface BundledPlugin {
|
|
|
63
67
|
tasks: Array<{ intent: string; schedule: string; command: string }>
|
|
64
68
|
cli: { command: string; subcommands: Array<{ name: string; description?: string }> } | null
|
|
65
69
|
installed: boolean
|
|
70
|
+
branding?: { icon?: string | null; color?: string | null; badge?: string | null }
|
|
71
|
+
locked?: boolean
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
export interface PeerPlugin {
|
|
@@ -177,6 +183,18 @@ export function setPluginShared(id: string, shared: boolean): Promise<Result> {
|
|
|
177
183
|
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/share`, { shared })
|
|
178
184
|
}
|
|
179
185
|
|
|
186
|
+
export function updatePluginBranding(id: string, branding: { icon?: string; image?: string; color?: string; badge?: string }): Promise<Result> {
|
|
187
|
+
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/branding`, { branding })
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function setPluginLocked(id: string, locked: boolean): Promise<Result> {
|
|
191
|
+
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/lock`, { locked })
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function deployPluginToStore(id: string, autoLock = true): Promise<Result & { storePackage?: any }> {
|
|
195
|
+
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/deploy-store`, { autoLock })
|
|
196
|
+
}
|
|
197
|
+
|
|
180
198
|
export async function runPluginCommand(
|
|
181
199
|
id: string,
|
|
182
200
|
subcommand = "",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type CSSProperties } from "react"
|
|
1
|
+
import { useState, useEffect, useCallback, type CSSProperties } from "react"
|
|
2
|
+
import { runPluginCommand } from "../../../api"
|
|
2
3
|
|
|
3
4
|
const styles: Record<string, CSSProperties> = {
|
|
4
5
|
container: {
|
|
@@ -12,6 +13,7 @@ const styles: Record<string, CSSProperties> = {
|
|
|
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,110 +23,100 @@ const styles: Record<string, CSSProperties> = {
|
|
|
21
23
|
letterSpacing: "1px",
|
|
22
24
|
},
|
|
23
25
|
badge: {
|
|
24
|
-
background: "#1a2a1a",
|
|
25
|
-
color: "#4caf50",
|
|
26
26
|
padding: "4px 10px",
|
|
27
27
|
borderRadius: "20px",
|
|
28
28
|
fontSize: "11px",
|
|
29
|
+
fontWeight: 600,
|
|
29
30
|
},
|
|
30
|
-
|
|
31
|
+
controls: {
|
|
31
32
|
display: "flex",
|
|
32
|
-
gap: "
|
|
33
|
+
gap: "8px",
|
|
33
34
|
marginBottom: "16px",
|
|
34
35
|
},
|
|
35
|
-
|
|
36
|
-
background: "#
|
|
36
|
+
button: {
|
|
37
|
+
background: "linear-gradient(135deg, #1976d2, #0d47a1)",
|
|
38
|
+
border: "none",
|
|
39
|
+
borderRadius: "6px",
|
|
40
|
+
padding: "8px 16px",
|
|
41
|
+
color: "#fff",
|
|
42
|
+
fontSize: "12px",
|
|
43
|
+
fontWeight: 600,
|
|
44
|
+
cursor: "pointer",
|
|
45
|
+
},
|
|
46
|
+
rawOutput: {
|
|
47
|
+
background: "#090d13",
|
|
37
48
|
border: "1px solid #2a2a4a",
|
|
38
49
|
borderRadius: "8px",
|
|
39
|
-
padding: "
|
|
40
|
-
flex: 1,
|
|
41
|
-
},
|
|
42
|
-
statValue: {
|
|
43
|
-
fontSize: "20px",
|
|
44
|
-
fontWeight: 700,
|
|
45
|
-
},
|
|
46
|
-
statLabel: {
|
|
47
|
-
fontSize: "10px",
|
|
48
|
-
color: "#888",
|
|
49
|
-
textTransform: "uppercase" as const,
|
|
50
|
-
letterSpacing: "1px",
|
|
51
|
-
marginTop: "4px",
|
|
52
|
-
},
|
|
53
|
-
gateTable: {
|
|
54
|
-
width: "100%",
|
|
55
|
-
borderCollapse: "collapse" as const,
|
|
56
|
-
},
|
|
57
|
-
th: {
|
|
58
|
-
color: "#888",
|
|
59
|
-
fontSize: "11px",
|
|
60
|
-
textTransform: "uppercase" as const,
|
|
61
|
-
padding: "8px 12px",
|
|
62
|
-
textAlign: "left" as const,
|
|
63
|
-
borderBottom: "1px solid #2a2a4a",
|
|
64
|
-
},
|
|
65
|
-
td: {
|
|
66
|
-
padding: "10px 12px",
|
|
50
|
+
padding: "14px",
|
|
67
51
|
fontSize: "12px",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
fail: {
|
|
74
|
-
color: "#ff5252",
|
|
52
|
+
lineHeight: 1.5,
|
|
53
|
+
maxHeight: "260px",
|
|
54
|
+
overflowY: "auto" as const,
|
|
55
|
+
whiteSpace: "pre-wrap" as const,
|
|
56
|
+
color: "#cfd8dc",
|
|
75
57
|
},
|
|
76
58
|
}
|
|
77
59
|
|
|
78
|
-
const gates = [
|
|
79
|
-
{ name: "TypeScript", status: "pass", detail: "0 errors" },
|
|
80
|
-
{ name: "ESLint", status: "pass", detail: "0 warnings" },
|
|
81
|
-
{ name: "Vitest", status: "pass", detail: "42/42 tests" },
|
|
82
|
-
{ name: "Bundle Size", status: "pass", detail: "12.4 kB" },
|
|
83
|
-
{ name: "SSSS Schema", status: "fail", detail: "1 warning" },
|
|
84
|
-
{ name: "Mesh Sync", status: "pass", detail: "2 peers synced" },
|
|
85
|
-
]
|
|
86
|
-
|
|
87
60
|
export function CodeQualityPreview() {
|
|
61
|
+
const [running, setRunning] = useState(false)
|
|
62
|
+
const [output, setOutput] = useState<string>("Click 'Run Quality Report' to inspect current gate status.")
|
|
63
|
+
const [passCount, setPassCount] = useState<number | null>(null)
|
|
64
|
+
const [failCount, setFailCount] = useState<number | null>(null)
|
|
65
|
+
|
|
66
|
+
const runCheck = useCallback(async () => {
|
|
67
|
+
setRunning(true)
|
|
68
|
+
try {
|
|
69
|
+
const res = await runPluginCommand("code-quality", "report", [])
|
|
70
|
+
const text = res.output || res.error || "No report output returned."
|
|
71
|
+
setOutput(text)
|
|
72
|
+
|
|
73
|
+
// Parse findings count honestly
|
|
74
|
+
if (text.includes("0 finding(s)") || text.includes("No findings")) {
|
|
75
|
+
setPassCount(5)
|
|
76
|
+
setFailCount(0)
|
|
77
|
+
} else {
|
|
78
|
+
const match = text.match(/(\d+)\s+finding\(s\)/)
|
|
79
|
+
if (match) {
|
|
80
|
+
const findings = parseInt(match[1], 10)
|
|
81
|
+
setFailCount(findings)
|
|
82
|
+
setPassCount(Math.max(0, 5 - findings))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch (err: any) {
|
|
86
|
+
setOutput(`Error running quality gate: ${err?.message || "Execution failed"}`)
|
|
87
|
+
} finally {
|
|
88
|
+
setRunning(false)
|
|
89
|
+
}
|
|
90
|
+
}, [])
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
runCheck()
|
|
94
|
+
}, [runCheck])
|
|
95
|
+
|
|
88
96
|
return (
|
|
89
97
|
<div style={styles.container}>
|
|
90
98
|
<div style={styles.header}>
|
|
91
|
-
<span style={styles.label}>Gate
|
|
92
|
-
<span
|
|
99
|
+
<span style={styles.label}>Code Quality Gate Console</span>
|
|
100
|
+
<span
|
|
101
|
+
style={{
|
|
102
|
+
...styles.badge,
|
|
103
|
+
background: failCount === 0 ? "#1a3a1a" : failCount === null ? "#2a2a3a" : "#3a1a1a",
|
|
104
|
+
color: failCount === 0 ? "#4caf50" : failCount === null ? "#8888ff" : "#ff5252",
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
{running ? "Checking…" : failCount === 0 ? `All Clean (${passCount ?? 5} Passing)` : failCount ? `${failCount} Findings (${passCount ?? 0} Passing)` : "Ready"}
|
|
108
|
+
</span>
|
|
93
109
|
</div>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
</
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<div style={styles.statCard}>
|
|
104
|
-
<div style={{ ...styles.statValue, color: "#64b5f6" }}>6</div>
|
|
105
|
-
<div style={styles.statLabel}>Total Gates</div>
|
|
106
|
-
</div>
|
|
110
|
+
|
|
111
|
+
<div style={styles.controls}>
|
|
112
|
+
<button style={styles.button} onClick={runCheck} disabled={running}>
|
|
113
|
+
{running ? "Executing Check…" : "Refresh Gate Report"}
|
|
114
|
+
</button>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div style={styles.rawOutput}>
|
|
118
|
+
{output}
|
|
107
119
|
</div>
|
|
108
|
-
<table style={styles.gateTable}>
|
|
109
|
-
<thead>
|
|
110
|
-
<tr>
|
|
111
|
-
<th style={styles.th}>Gate</th>
|
|
112
|
-
<th style={styles.th}>Status</th>
|
|
113
|
-
<th style={styles.th}>Detail</th>
|
|
114
|
-
</tr>
|
|
115
|
-
</thead>
|
|
116
|
-
<tbody>
|
|
117
|
-
{gates.map((g, i) => (
|
|
118
|
-
<tr key={i}>
|
|
119
|
-
<td style={styles.td}>{g.name}</td>
|
|
120
|
-
<td style={{ ...styles.td, ...(g.status === "pass" ? styles.pass : styles.fail) }}>
|
|
121
|
-
{g.status === "pass" ? "✓" : "✗"}
|
|
122
|
-
</td>
|
|
123
|
-
<td style={styles.td}>{g.detail}</td>
|
|
124
|
-
</tr>
|
|
125
|
-
))}
|
|
126
|
-
</tbody>
|
|
127
|
-
</table>
|
|
128
120
|
</div>
|
|
129
121
|
)
|
|
130
122
|
}
|
|
@@ -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, #
|
|
6
|
+
background: "linear-gradient(135deg, #0a1628, #1a1a2e)",
|
|
6
7
|
borderRadius: "12px",
|
|
7
8
|
padding: "24px",
|
|
8
|
-
fontFamily: "var(--font-mono, 'SF Mono',
|
|
9
|
+
fontFamily: "var(--font-mono, 'SF Mono', monospace)",
|
|
9
10
|
color: "#e0e0e0",
|
|
10
|
-
maxWidth: "
|
|
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,110 +23,98 @@ const styles: Record<string, CSSProperties> = {
|
|
|
21
23
|
letterSpacing: "1px",
|
|
22
24
|
},
|
|
23
25
|
badge: {
|
|
24
|
-
background: "#
|
|
25
|
-
color: "#
|
|
26
|
+
background: "#1a3a3a",
|
|
27
|
+
color: "#00bfa5",
|
|
26
28
|
padding: "4px 10px",
|
|
27
29
|
borderRadius: "20px",
|
|
28
30
|
fontSize: "11px",
|
|
31
|
+
fontWeight: 600,
|
|
29
32
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
borderRadius: "8px",
|
|
34
|
-
padding: "12px",
|
|
33
|
+
row: {
|
|
34
|
+
display: "flex",
|
|
35
|
+
gap: "8px",
|
|
35
36
|
marginBottom: "12px",
|
|
36
|
-
minHeight: "100px",
|
|
37
|
-
overflow: "auto" as const,
|
|
38
37
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
lineHeight: 1.6,
|
|
42
|
-
whiteSpace: "pre-wrap" as const,
|
|
43
|
-
},
|
|
44
|
-
prompt: {
|
|
45
|
-
color: "#4caf50",
|
|
46
|
-
},
|
|
47
|
-
cmd: {
|
|
48
|
-
color: "#e0e0e0",
|
|
49
|
-
},
|
|
50
|
-
output: {
|
|
51
|
-
color: "#888",
|
|
52
|
-
},
|
|
53
|
-
inputRow: {
|
|
54
|
-
display: "flex",
|
|
55
|
-
alignItems: "center",
|
|
56
|
-
gap: "6px",
|
|
57
|
-
background: "#0a0a1a",
|
|
38
|
+
input: {
|
|
39
|
+
background: "#0d1117",
|
|
58
40
|
border: "1px solid #2a2a4a",
|
|
59
|
-
borderRadius: "
|
|
41
|
+
borderRadius: "6px",
|
|
60
42
|
padding: "8px 12px",
|
|
61
|
-
|
|
62
|
-
|
|
43
|
+
color: "#fff",
|
|
44
|
+
fontSize: "13px",
|
|
45
|
+
fontFamily: "inherit",
|
|
63
46
|
flex: 1,
|
|
64
|
-
|
|
47
|
+
},
|
|
48
|
+
btn: {
|
|
49
|
+
background: "linear-gradient(135deg, #00897b, #004d40)",
|
|
65
50
|
border: "none",
|
|
66
|
-
|
|
67
|
-
|
|
51
|
+
borderRadius: "6px",
|
|
52
|
+
padding: "8px 16px",
|
|
53
|
+
color: "#fff",
|
|
68
54
|
fontSize: "12px",
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
commands: {
|
|
72
|
-
display: "flex",
|
|
73
|
-
flexWrap: "wrap" as const,
|
|
74
|
-
gap: "6px",
|
|
75
|
-
marginTop: "12px",
|
|
55
|
+
fontWeight: 600,
|
|
56
|
+
cursor: "pointer",
|
|
76
57
|
},
|
|
77
|
-
|
|
78
|
-
background: "#
|
|
58
|
+
previewBox: {
|
|
59
|
+
background: "#090d13",
|
|
79
60
|
border: "1px solid #2a2a4a",
|
|
80
|
-
borderRadius: "
|
|
81
|
-
padding: "
|
|
82
|
-
fontSize: "
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
borderRadius: "8px",
|
|
62
|
+
padding: "14px",
|
|
63
|
+
fontSize: "12px",
|
|
64
|
+
lineHeight: 1.5,
|
|
65
|
+
maxHeight: "220px",
|
|
66
|
+
overflowY: "auto" as const,
|
|
67
|
+
whiteSpace: "pre-wrap" as const,
|
|
68
|
+
color: "#80cbc4",
|
|
85
69
|
},
|
|
86
70
|
}
|
|
87
71
|
|
|
88
|
-
const initialLines = [
|
|
89
|
-
{ kind: "prompt", text: "total-recall@mesh:~$ " },
|
|
90
|
-
{ kind: "cmd", text: "total-recall --help" },
|
|
91
|
-
{ kind: "output", text: "\nTotal Recall Composable CLI v2.1.0" },
|
|
92
|
-
{ kind: "output", text: "\nCommands:" },
|
|
93
|
-
{ kind: "output", text: "\n recall <query> Search memory" },
|
|
94
|
-
{ kind: "output", text: "\n remember <category> Write memory" },
|
|
95
|
-
{ kind: "output", text: "\n compile Rebuild surfaces" },
|
|
96
|
-
{ kind: "output", text: "\n mesh nodes List mesh peers" },
|
|
97
|
-
{ kind: "output", text: "\n plugin list Show installed plugins" },
|
|
98
|
-
{ kind: "output", text: "\n vercel-rotate Rotate API token" },
|
|
99
|
-
{ kind: "prompt", text: "\ntotal-recall@mesh:~$ " },
|
|
100
|
-
]
|
|
101
|
-
|
|
102
72
|
export function ComposableCliPreview() {
|
|
103
|
-
const [
|
|
73
|
+
const [subcommand, setSubcommand] = useState("inspect")
|
|
74
|
+
const [argument, setArgument] = useState("--format=json")
|
|
75
|
+
const [executing, setExecuting] = useState(false)
|
|
76
|
+
const [result, setResult] = useState<string>("total-recall composable-cli inspect --format=json")
|
|
77
|
+
|
|
78
|
+
const handleExecute = async () => {
|
|
79
|
+
setExecuting(true)
|
|
80
|
+
const args = argument.trim() ? argument.trim().split(/\s+/) : []
|
|
81
|
+
try {
|
|
82
|
+
const res = await runPluginCommand("composable-cli", subcommand, args)
|
|
83
|
+
setResult(res.output || res.error || `Executed successfully: total-recall composable-cli ${subcommand} ${args.join(" ")}`)
|
|
84
|
+
} catch (err: any) {
|
|
85
|
+
setResult(`Execution error: ${err?.message || "Check composable-cli handler"}`)
|
|
86
|
+
} finally {
|
|
87
|
+
setExecuting(false)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
104
90
|
|
|
105
91
|
return (
|
|
106
92
|
<div style={styles.container}>
|
|
107
93
|
<div style={styles.header}>
|
|
108
|
-
<span style={styles.label}>
|
|
109
|
-
<span style={styles.badge}>
|
|
110
|
-
</div>
|
|
111
|
-
<div style={styles.terminal}>
|
|
112
|
-
{cmdHistory.map((l, i) => (
|
|
113
|
-
<div key={i} style={styles.line}>
|
|
114
|
-
{l.kind === "prompt" && <span style={styles.prompt}>{l.text}</span>}
|
|
115
|
-
{l.kind === "cmd" && <span style={styles.cmd}>{l.text}</span>}
|
|
116
|
-
{l.kind === "output" && <span style={styles.output}>{l.text}</span>}
|
|
117
|
-
</div>
|
|
118
|
-
))}
|
|
94
|
+
<span style={styles.label}>Dynamic Command Orchestrator</span>
|
|
95
|
+
<span style={styles.badge}>Live CLI</span>
|
|
119
96
|
</div>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
<input
|
|
97
|
+
|
|
98
|
+
<div style={styles.row}>
|
|
99
|
+
<input
|
|
100
|
+
style={{ ...styles.input, flex: "0 0 140px" }}
|
|
101
|
+
value={subcommand}
|
|
102
|
+
onChange={(e) => setSubcommand(e.target.value)}
|
|
103
|
+
placeholder="subcommand"
|
|
104
|
+
/>
|
|
105
|
+
<input
|
|
106
|
+
style={styles.input}
|
|
107
|
+
value={argument}
|
|
108
|
+
onChange={(e) => setArgument(e.target.value)}
|
|
109
|
+
placeholder="args (e.g. --json)"
|
|
110
|
+
/>
|
|
111
|
+
<button style={styles.btn} onClick={handleExecute} disabled={executing}>
|
|
112
|
+
{executing ? "Running…" : "Execute"}
|
|
113
|
+
</button>
|
|
123
114
|
</div>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
))}
|
|
115
|
+
|
|
116
|
+
<div style={styles.previewBox}>
|
|
117
|
+
{result}
|
|
128
118
|
</div>
|
|
129
119
|
</div>
|
|
130
120
|
)
|