@decido/plugin-dev-console 1.0.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.
Potentially problematic release.
This version of @decido/plugin-dev-console might be problematic. Click here for more details.
- package/.turbo/turbo-build.log +13 -0
- package/package.json +30 -0
- package/src/components/SafeComponentWrapper.tsx +120 -0
- package/src/components/react-shadow.d.ts +5 -0
- package/src/components/ui/CodeSnippet.tsx +39 -0
- package/src/components/ui/OSNode.tsx +25 -0
- package/src/data/tutorialSteps.tsx +120 -0
- package/src/engine/DependencyRegistry.ts +29 -0
- package/src/engine/PlaygroundEngine.ts +272 -0
- package/src/engine/SecurityProxy.ts +34 -0
- package/src/index.ts +142 -0
- package/src/widgets/DeveloperPlaygroundWidget.tsx +211 -0
- package/src/widgets/ForgeTerminalWidget.tsx +202 -0
- package/src/widgets/SDKShowcaseWidget.tsx +289 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Showcase Widget — Interactive demo for every @decido/sdk hook
|
|
3
|
+
*
|
|
4
|
+
* Renders a card per hook (useKernel, useAgent, useFileSystem, useNotify,
|
|
5
|
+
* usePermissions, useDecidoTheme) with live examples.
|
|
6
|
+
*/
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
import {
|
|
9
|
+
useKernel,
|
|
10
|
+
useNotify,
|
|
11
|
+
useAgent,
|
|
12
|
+
useFileSystem,
|
|
13
|
+
usePermissions,
|
|
14
|
+
useDecidoTheme,
|
|
15
|
+
useDecidoEvent,
|
|
16
|
+
} from '@decido/sdk';
|
|
17
|
+
|
|
18
|
+
// ─── Shared Card ───
|
|
19
|
+
const Card: React.FC<{ title: string; icon: string; children: React.ReactNode }> = ({ title, icon, children }) => (
|
|
20
|
+
<div style={{
|
|
21
|
+
background: 'rgba(255,255,255,0.04)',
|
|
22
|
+
border: '1px solid rgba(255,255,255,0.08)',
|
|
23
|
+
borderRadius: 12,
|
|
24
|
+
padding: 16,
|
|
25
|
+
display: 'flex',
|
|
26
|
+
flexDirection: 'column',
|
|
27
|
+
gap: 10,
|
|
28
|
+
}}>
|
|
29
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
30
|
+
<span style={{ fontSize: 20 }}>{icon}</span>
|
|
31
|
+
<strong style={{ fontSize: 14, color: '#e2e8f0' }}>{title}</strong>
|
|
32
|
+
</div>
|
|
33
|
+
{children}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const Btn: React.FC<{ onClick: () => void; children: React.ReactNode; disabled?: boolean }> = ({ onClick, children, disabled }) => (
|
|
38
|
+
<button
|
|
39
|
+
onClick={onClick}
|
|
40
|
+
disabled={disabled}
|
|
41
|
+
style={{
|
|
42
|
+
padding: '6px 14px',
|
|
43
|
+
background: disabled ? '#374151' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
|
44
|
+
border: 'none',
|
|
45
|
+
borderRadius: 8,
|
|
46
|
+
color: '#fff',
|
|
47
|
+
fontSize: 12,
|
|
48
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
49
|
+
opacity: disabled ? 0.5 : 1,
|
|
50
|
+
transition: 'all 0.2s',
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</button>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const Output: React.FC<{ data: any }> = ({ data }) => (
|
|
58
|
+
<pre style={{
|
|
59
|
+
background: 'rgba(0,0,0,0.3)',
|
|
60
|
+
padding: 8,
|
|
61
|
+
borderRadius: 6,
|
|
62
|
+
fontSize: 11,
|
|
63
|
+
color: '#a5b4fc',
|
|
64
|
+
overflow: 'auto',
|
|
65
|
+
maxHeight: 120,
|
|
66
|
+
margin: 0,
|
|
67
|
+
}}>
|
|
68
|
+
{typeof data === 'string' ? data : JSON.stringify(data, null, 2)}
|
|
69
|
+
</pre>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// ═══ Individual Hook Examples ═══
|
|
73
|
+
|
|
74
|
+
const KernelExample: React.FC = () => {
|
|
75
|
+
const { execute, isLoading, lastError } = useKernel();
|
|
76
|
+
const [result, setResult] = useState<any>(null);
|
|
77
|
+
|
|
78
|
+
const handleExecute = async () => {
|
|
79
|
+
const res = await execute('get_settings');
|
|
80
|
+
setResult(res);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Card title="useKernel" icon="⚡">
|
|
85
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
86
|
+
Ejecuta comandos del kernel con latency tracking.
|
|
87
|
+
</p>
|
|
88
|
+
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
|
89
|
+
<Btn onClick={handleExecute} disabled={isLoading}>
|
|
90
|
+
{isLoading ? '⏳ Ejecutando...' : 'kernel.execute("get_settings")'}
|
|
91
|
+
</Btn>
|
|
92
|
+
</div>
|
|
93
|
+
{lastError && <span style={{ color: '#ef4444', fontSize: 11 }}>❌ {lastError}</span>}
|
|
94
|
+
{result && <Output data={result} />}
|
|
95
|
+
</Card>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const NotifyExample: React.FC = () => {
|
|
100
|
+
const notify = useNotify();
|
|
101
|
+
const [sent, setSent] = useState(false);
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<Card title="useNotify" icon="🔔">
|
|
105
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
106
|
+
Notificaciones nativas del OS.
|
|
107
|
+
</p>
|
|
108
|
+
<Btn onClick={() => { notify('Hello!', 'Notificación de prueba desde el SDK', 'success'); setSent(true); }}>
|
|
109
|
+
{sent ? '✅ Enviada!' : 'Enviar Notificación'}
|
|
110
|
+
</Btn>
|
|
111
|
+
</Card>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const AgentExample: React.FC = () => {
|
|
116
|
+
const { dispatch, stream, reset } = useAgent();
|
|
117
|
+
const [prompt, setPrompt] = useState('Genera un reporte de ventas');
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<Card title="useAgent" icon="🤖">
|
|
121
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
122
|
+
Despacha tareas al swarm AI y recibe cognitive frames.
|
|
123
|
+
</p>
|
|
124
|
+
<input
|
|
125
|
+
value={prompt}
|
|
126
|
+
onChange={e => setPrompt(e.target.value)}
|
|
127
|
+
placeholder="Escribe una tarea..."
|
|
128
|
+
style={{
|
|
129
|
+
background: 'rgba(0,0,0,0.3)', border: '1px solid rgba(255,255,255,0.1)',
|
|
130
|
+
borderRadius: 6, padding: '6px 10px', color: '#e2e8f0', fontSize: 12,
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
<div style={{ display: 'flex', gap: 8 }}>
|
|
134
|
+
<Btn onClick={() => dispatch({ prompt, priority: 'high' })} disabled={stream.status === 'thinking'}>
|
|
135
|
+
{stream.status === 'thinking' ? '🧠 Pensando...' : '▶ Despachar'}
|
|
136
|
+
</Btn>
|
|
137
|
+
<Btn onClick={reset}>🔄 Reset</Btn>
|
|
138
|
+
</div>
|
|
139
|
+
<div style={{ fontSize: 11, color: '#94a3b8' }}>
|
|
140
|
+
Status: <strong style={{ color: stream.status === 'complete' ? '#4ade80' : '#fbbf24' }}>
|
|
141
|
+
{stream.status}
|
|
142
|
+
</strong>
|
|
143
|
+
{stream.frames.length > 0 && ` · ${stream.frames.length} frames`}
|
|
144
|
+
</div>
|
|
145
|
+
{stream.frames.length > 0 && (
|
|
146
|
+
<Output data={stream.frames.slice(-3).map(f => `💭 ${f.thought} → 🎯 ${f.action}`).join('\n')} />
|
|
147
|
+
)}
|
|
148
|
+
{stream.response && <Output data={`✅ ${stream.response}`} />}
|
|
149
|
+
</Card>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const FileSystemExample: React.FC = () => {
|
|
154
|
+
const fs = useFileSystem();
|
|
155
|
+
const [files, setFiles] = useState<any[]>([]);
|
|
156
|
+
const [content, setContent] = useState<string | null>(null);
|
|
157
|
+
|
|
158
|
+
const handleList = async () => {
|
|
159
|
+
const list = await fs.listDir('/');
|
|
160
|
+
setFiles(list);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const handleRead = async () => {
|
|
164
|
+
const result = await fs.readFile('config.json');
|
|
165
|
+
setContent(result.content);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const handleWrite = async () => {
|
|
169
|
+
await fs.writeFile('test.txt', 'Hello from SDK!');
|
|
170
|
+
setContent('✅ Archivo escrito: test.txt');
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<Card title="useFileSystem" icon="📂">
|
|
175
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
176
|
+
CRUD de archivos sandboxed por plugin.
|
|
177
|
+
</p>
|
|
178
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
179
|
+
<Btn onClick={handleList}>📑 listDir("/")</Btn>
|
|
180
|
+
<Btn onClick={handleRead}>📖 readFile</Btn>
|
|
181
|
+
<Btn onClick={handleWrite}>✏️ writeFile</Btn>
|
|
182
|
+
</div>
|
|
183
|
+
{files.length > 0 && <Output data={files} />}
|
|
184
|
+
{content && <Output data={content} />}
|
|
185
|
+
</Card>
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const PermissionsExample: React.FC = () => {
|
|
190
|
+
const { check, request, hasPermission } = usePermissions();
|
|
191
|
+
const [log, setLog] = useState<string[]>([]);
|
|
192
|
+
|
|
193
|
+
const handleCheck = async (scope: string) => {
|
|
194
|
+
const granted = await check(scope as any);
|
|
195
|
+
setLog(prev => [...prev, `check(${scope}) → ${granted ? '✅' : '❌'}`]);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const handleRequest = async (scope: string) => {
|
|
199
|
+
const status = await request(scope as any);
|
|
200
|
+
setLog(prev => [...prev, `request(${scope}) → ${status.granted ? '✅' : '❌'} ${status.reason || ''}`]);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<Card title="usePermissions" icon="🔐">
|
|
205
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
206
|
+
Zero-trust permission checks en runtime.
|
|
207
|
+
</p>
|
|
208
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
|
209
|
+
<Btn onClick={() => handleCheck('fs:write')}>Check fs:write</Btn>
|
|
210
|
+
<Btn onClick={() => handleRequest('agent:dispatch')}>Request agent:dispatch</Btn>
|
|
211
|
+
</div>
|
|
212
|
+
{log.length > 0 && <Output data={log.join('\n')} />}
|
|
213
|
+
</Card>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const ThemeExample: React.FC = () => {
|
|
218
|
+
const { colors } = useDecidoTheme();
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<Card title="useDecidoTheme" icon="🎨">
|
|
222
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
223
|
+
Tokens del tema morfológico actual.
|
|
224
|
+
</p>
|
|
225
|
+
<div style={{ display: 'flex', gap: 8 }}>
|
|
226
|
+
{Object.entries(colors).map(([key, val]) => (
|
|
227
|
+
<div key={key} style={{
|
|
228
|
+
display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
|
|
229
|
+
}}>
|
|
230
|
+
<div style={{
|
|
231
|
+
width: 32, height: 32, borderRadius: 8,
|
|
232
|
+
background: val, border: '1px solid rgba(255,255,255,0.15)',
|
|
233
|
+
}} />
|
|
234
|
+
<span style={{ fontSize: 10, color: '#94a3b8' }}>{key}</span>
|
|
235
|
+
</div>
|
|
236
|
+
))}
|
|
237
|
+
</div>
|
|
238
|
+
</Card>
|
|
239
|
+
);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const EventExample: React.FC = () => {
|
|
243
|
+
const [events, setEvents] = useState<string[]>([]);
|
|
244
|
+
const emit = useDecidoEvent('sdk:demo_ping', (data) => {
|
|
245
|
+
setEvents(prev => [...prev.slice(-4), `📨 ${JSON.stringify(data)}`]);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<Card title="useDecidoEvent" icon="📡">
|
|
250
|
+
<p style={{ fontSize: 12, color: '#94a3b8', margin: 0 }}>
|
|
251
|
+
Pub/Sub cross-plugin via Event Mesh.
|
|
252
|
+
</p>
|
|
253
|
+
<Btn onClick={() => emit({ message: 'ping', timestamp: Date.now() })}>
|
|
254
|
+
Emit "sdk:demo_ping"
|
|
255
|
+
</Btn>
|
|
256
|
+
{events.length > 0 && <Output data={events.join('\n')} />}
|
|
257
|
+
</Card>
|
|
258
|
+
);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// ═══ Main Showcase ═══
|
|
262
|
+
export const SDKShowcaseWidget: React.FC = () => {
|
|
263
|
+
return (
|
|
264
|
+
<div style={{
|
|
265
|
+
padding: 20,
|
|
266
|
+
display: 'grid',
|
|
267
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',
|
|
268
|
+
gap: 16,
|
|
269
|
+
maxHeight: '100%',
|
|
270
|
+
overflow: 'auto',
|
|
271
|
+
}}>
|
|
272
|
+
<div style={{ gridColumn: '1 / -1', marginBottom: 4 }}>
|
|
273
|
+
<h2 style={{ margin: 0, fontSize: 18, color: '#e2e8f0' }}>
|
|
274
|
+
🧪 SDK Hooks Showcase
|
|
275
|
+
</h2>
|
|
276
|
+
<p style={{ margin: '4px 0 0', fontSize: 13, color: '#64748b' }}>
|
|
277
|
+
Cada tarjeta es un hook del <code>@decido/sdk</code> con un ejemplo interactivo.
|
|
278
|
+
</p>
|
|
279
|
+
</div>
|
|
280
|
+
<KernelExample />
|
|
281
|
+
<NotifyExample />
|
|
282
|
+
<AgentExample />
|
|
283
|
+
<FileSystemExample />
|
|
284
|
+
<PermissionsExample />
|
|
285
|
+
<ThemeExample />
|
|
286
|
+
<EventExample />
|
|
287
|
+
</div>
|
|
288
|
+
);
|
|
289
|
+
};
|