@bytespell/shella 0.2.0 → 0.2.2

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 (82) hide show
  1. package/bundled-plugins/agent/README.md +3 -0
  2. package/bundled-plugins/agent/components.json +24 -0
  3. package/bundled-plugins/agent/dist/assets/index-BGeDYr6P.css +1 -0
  4. package/bundled-plugins/agent/dist/assets/index-J14lI3Er.js +49 -0
  5. package/bundled-plugins/agent/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  6. package/bundled-plugins/agent/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  7. package/bundled-plugins/agent/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  8. package/bundled-plugins/agent/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  9. package/bundled-plugins/agent/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  10. package/bundled-plugins/agent/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  11. package/bundled-plugins/agent/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  12. package/bundled-plugins/agent/dist/index.html +14 -0
  13. package/bundled-plugins/agent/dist/vite.svg +1 -0
  14. package/bundled-plugins/agent/eslint.config.js +23 -0
  15. package/bundled-plugins/agent/index.html +13 -0
  16. package/bundled-plugins/agent/package-lock.json +11034 -0
  17. package/bundled-plugins/agent/package.json +52 -0
  18. package/bundled-plugins/agent/public/vite.svg +1 -0
  19. package/bundled-plugins/agent/server.js +240 -0
  20. package/bundled-plugins/agent/src/App.tsx +586 -0
  21. package/bundled-plugins/agent/src/assets/react.svg +1 -0
  22. package/bundled-plugins/agent/src/components/ui/alert-dialog.tsx +182 -0
  23. package/bundled-plugins/agent/src/components/ui/badge.tsx +45 -0
  24. package/bundled-plugins/agent/src/components/ui/button.tsx +60 -0
  25. package/bundled-plugins/agent/src/components/ui/card.tsx +94 -0
  26. package/bundled-plugins/agent/src/components/ui/combobox.tsx +294 -0
  27. package/bundled-plugins/agent/src/components/ui/dropdown-menu.tsx +253 -0
  28. package/bundled-plugins/agent/src/components/ui/field.tsx +225 -0
  29. package/bundled-plugins/agent/src/components/ui/input-group.tsx +147 -0
  30. package/bundled-plugins/agent/src/components/ui/input.tsx +19 -0
  31. package/bundled-plugins/agent/src/components/ui/label.tsx +24 -0
  32. package/bundled-plugins/agent/src/components/ui/select.tsx +185 -0
  33. package/bundled-plugins/agent/src/components/ui/separator.tsx +26 -0
  34. package/bundled-plugins/agent/src/components/ui/switch.tsx +31 -0
  35. package/bundled-plugins/agent/src/components/ui/textarea.tsx +18 -0
  36. package/bundled-plugins/agent/src/index.css +131 -0
  37. package/bundled-plugins/agent/src/lib/utils.ts +6 -0
  38. package/bundled-plugins/agent/src/main.tsx +11 -0
  39. package/bundled-plugins/agent/tsconfig.app.json +32 -0
  40. package/bundled-plugins/agent/tsconfig.json +13 -0
  41. package/bundled-plugins/agent/tsconfig.node.json +26 -0
  42. package/bundled-plugins/agent/vite.config.ts +14 -0
  43. package/bundled-plugins/terminal/index.html +24 -0
  44. package/bundled-plugins/terminal/package-lock.json +3316 -0
  45. package/bundled-plugins/terminal/package.json +37 -0
  46. package/bundled-plugins/terminal/server.ts +169 -0
  47. package/bundled-plugins/terminal/src/App.tsx +168 -0
  48. package/bundled-plugins/terminal/src/main.tsx +9 -0
  49. package/bundled-plugins/terminal/tsconfig.json +22 -0
  50. package/bundled-plugins/terminal/vite.config.ts +10 -0
  51. package/dist/bin/shella-init.js +2 -2
  52. package/dist/bin/shella-init.js.map +1 -1
  53. package/dist/src/api.d.ts.map +1 -1
  54. package/dist/src/api.js +51 -10
  55. package/dist/src/api.js.map +1 -1
  56. package/dist/src/bonjour.d.ts +3 -0
  57. package/dist/src/bonjour.d.ts.map +1 -0
  58. package/dist/src/bonjour.js +42 -0
  59. package/dist/src/bonjour.js.map +1 -0
  60. package/dist/src/index.d.ts.map +1 -1
  61. package/dist/src/index.js +7 -0
  62. package/dist/src/index.js.map +1 -1
  63. package/dist/src/logger.d.ts +19 -2
  64. package/dist/src/logger.d.ts.map +1 -1
  65. package/dist/src/logger.js +96 -16
  66. package/dist/src/logger.js.map +1 -1
  67. package/dist/src/paths.d.ts +1 -0
  68. package/dist/src/paths.d.ts.map +1 -1
  69. package/dist/src/paths.js +24 -0
  70. package/dist/src/paths.js.map +1 -1
  71. package/dist/src/plugin-manager.d.ts +14 -0
  72. package/dist/src/plugin-manager.d.ts.map +1 -1
  73. package/dist/src/plugin-manager.js +115 -7
  74. package/dist/src/plugin-manager.js.map +1 -1
  75. package/dist/src/sse.d.ts +45 -0
  76. package/dist/src/sse.d.ts.map +1 -0
  77. package/dist/src/sse.js +108 -0
  78. package/dist/src/sse.js.map +1 -0
  79. package/dist/src/types.d.ts +1 -0
  80. package/dist/src/types.d.ts.map +1 -1
  81. package/dist/src/types.js.map +1 -1
  82. package/package.json +4 -2
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "agent",
3
+ "private": true,
4
+ "version": "0.2.2",
5
+ "type": "module",
6
+ "main": "server.js",
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "tsc -b && vite build",
10
+ "lint": "eslint .",
11
+ "preview": "vite preview"
12
+ },
13
+ "dependencies": {
14
+ "@base-ui/react": "^1.1.0",
15
+ "@fontsource-variable/inter": "^5.2.8",
16
+ "@streamdown/code": "^1.0.1",
17
+ "@tailwindcss/typography": "^0.5.19",
18
+ "@tailwindcss/vite": "^4.1.17",
19
+ "class-variance-authority": "^0.7.1",
20
+ "clsx": "^2.1.1",
21
+ "express": "^5.0.0",
22
+ "lucide-react": "^0.562.0",
23
+ "radix-ui": "^1.4.3",
24
+ "react": "^19.2.0",
25
+ "react-dom": "^19.2.0",
26
+ "shadcn": "^3.7.0",
27
+ "streamdown": "^2.1.0",
28
+ "tailwind-merge": "^3.4.0",
29
+ "tailwindcss": "^4.1.17",
30
+ "tw-animate-css": "^1.4.0",
31
+ "use-stick-to-bottom": "^1.1.1",
32
+ "ws": "^8.19.0"
33
+ },
34
+ "devDependencies": {
35
+ "@eslint/js": "^9.39.1",
36
+ "@types/node": "^24.10.1",
37
+ "@types/react": "^19.2.5",
38
+ "@types/react-dom": "^19.2.3",
39
+ "@vitejs/plugin-react": "^5.1.1",
40
+ "eslint": "^9.39.1",
41
+ "eslint-plugin-react-hooks": "^7.0.1",
42
+ "eslint-plugin-react-refresh": "^0.4.24",
43
+ "globals": "^16.5.0",
44
+ "typescript": "~5.9.3",
45
+ "typescript-eslint": "^8.46.4",
46
+ "vite": "^7.2.4"
47
+ },
48
+ "shella": {
49
+ "displayName": "Agent",
50
+ "devCommand": "node server.js"
51
+ }
52
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,240 @@
1
+ import express from 'express';
2
+ import { createServer } from 'http';
3
+ import { WebSocketServer, WebSocket } from 'ws';
4
+ import { spawn } from 'child_process';
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import { fileURLToPath } from 'url';
9
+ import readline from 'readline';
10
+
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ const app = express();
13
+ const PORT = process.env.PORT;
14
+ const isDev = !fs.existsSync(path.join(__dirname, 'dist', 'index.html'));
15
+ const PI_AUTH_PATH = path.join(os.homedir(), '.pi', 'agent', 'auth.json');
16
+
17
+ // Allow embedding in iframes
18
+ app.use((req, res, next) => {
19
+ res.removeHeader('X-Frame-Options');
20
+ res.setHeader('Content-Security-Policy', 'frame-ancestors *');
21
+ next();
22
+ });
23
+
24
+ app.use(express.json());
25
+
26
+ // Health check
27
+ app.get('/api/health', (req, res) => {
28
+ res.json({ status: 'ok' });
29
+ });
30
+
31
+ // Check auth status
32
+ app.get('/api/auth/status', (req, res) => {
33
+ try {
34
+ if (fs.existsSync(PI_AUTH_PATH)) {
35
+ const authData = JSON.parse(fs.readFileSync(PI_AUTH_PATH, 'utf-8'));
36
+ const providers = Object.keys(authData);
37
+ res.json({ authenticated: providers.length > 0, providers });
38
+ } else {
39
+ res.json({ authenticated: false, providers: [] });
40
+ }
41
+ } catch {
42
+ res.json({ authenticated: false, providers: [] });
43
+ }
44
+ });
45
+
46
+ async function startServer() {
47
+ if (isDev) {
48
+ const { createServer: createViteServer } = await import('vite');
49
+ const vite = await createViteServer({
50
+ server: { middlewareMode: true, hmr: { port: Number(PORT) + 1000 } },
51
+ appType: 'spa',
52
+ });
53
+ app.use(vite.middlewares);
54
+ } else {
55
+ app.use(express.static(path.join(__dirname, 'dist')));
56
+ app.get('/{*splat}', (req, res) => {
57
+ res.sendFile(path.join(__dirname, 'dist', 'index.html'));
58
+ });
59
+ }
60
+
61
+ const server = createServer(app);
62
+
63
+ // Single pi process shared across all clients
64
+ let piProcess = null;
65
+ let rl = null;
66
+ const clients = new Set();
67
+
68
+ function broadcast(message) {
69
+ for (const client of clients) {
70
+ if (client.readyState === WebSocket.OPEN) {
71
+ client.send(message);
72
+ }
73
+ }
74
+ }
75
+
76
+ function sendCommand(cmd) {
77
+ if (piProcess?.stdin?.writable) {
78
+ console.log('[agent] Sending command:', JSON.stringify(cmd));
79
+ piProcess.stdin.write(JSON.stringify(cmd) + '\n');
80
+ }
81
+ }
82
+
83
+ function spawnPi() {
84
+ if (piProcess) return;
85
+
86
+ console.log('[agent] Spawning pi --mode rpc');
87
+
88
+ piProcess = spawn('pi', ['--mode', 'rpc'], {
89
+ stdio: ['pipe', 'pipe', 'pipe'],
90
+ env: { ...process.env },
91
+ });
92
+
93
+ rl = readline.createInterface({
94
+ input: piProcess.stdout,
95
+ crlfDelay: Infinity
96
+ });
97
+
98
+ rl.on('line', (line) => {
99
+ try {
100
+ const event = JSON.parse(line);
101
+ // Log different event types
102
+ switch (event.type) {
103
+ case 'response':
104
+ console.log('[agent] Response:', event.command, event.success ? 'success' : 'failed',
105
+ event.data ? `data keys: ${Object.keys(event.data)}` : 'no data');
106
+ break;
107
+ case 'agent_start':
108
+ console.log('[agent] Agent started');
109
+ break;
110
+ case 'agent_end':
111
+ console.log('[agent] Agent ended:', event.stopReason || 'unknown reason');
112
+ break;
113
+ case 'tool_execution_start':
114
+ console.log('[agent] Tool start:', event.toolName, 'id:', event.toolCallId);
115
+ if (event.args) {
116
+ const argsStr = JSON.stringify(event.args);
117
+ console.log('[agent] args:', argsStr.length > 200 ? argsStr.slice(0, 200) + '...' : argsStr);
118
+ }
119
+ break;
120
+ case 'tool_execution_update':
121
+ // Don't log updates to avoid spam, but could enable for debugging
122
+ break;
123
+ case 'tool_execution_end':
124
+ console.log('[agent] Tool end:', event.toolCallId, event.isError ? 'ERROR' : 'success');
125
+ break;
126
+ case 'message_start':
127
+ console.log('[agent] Message start:', event.message?.role || 'unknown role');
128
+ break;
129
+ case 'message_update':
130
+ // Don't log message updates to avoid spam
131
+ break;
132
+ case 'message_end':
133
+ console.log('[agent] Message end');
134
+ break;
135
+ default:
136
+ console.log('[agent] Event:', event.type);
137
+ }
138
+ broadcast(JSON.stringify({ type: 'rpc_event', event }));
139
+ } catch {
140
+ console.log('[agent] Non-JSON output:', line);
141
+ }
142
+ });
143
+
144
+ piProcess.stderr?.on('data', (data) => {
145
+ console.error('[agent] stderr:', data.toString());
146
+ });
147
+
148
+ piProcess.on('exit', (code, signal) => {
149
+ console.log(`[agent] pi exited: code=${code}, signal=${signal}`);
150
+ piProcess = null;
151
+ rl?.close();
152
+ rl = null;
153
+ broadcast(JSON.stringify({ type: 'process_exit', code, signal }));
154
+ });
155
+
156
+ piProcess.on('error', (err) => {
157
+ console.error('[agent] error:', err);
158
+ broadcast(JSON.stringify({
159
+ type: 'error',
160
+ message: `Failed to start pi: ${err.message}`
161
+ }));
162
+ });
163
+
164
+ sendCommand({ type: 'get_state' });
165
+ sendCommand({ type: 'get_messages' });
166
+ }
167
+
168
+ spawnPi();
169
+
170
+ const wss = new WebSocketServer({ server, path: '/ws' });
171
+
172
+ wss.on('connection', (ws) => {
173
+ console.log('[agent] Client connected');
174
+ clients.add(ws);
175
+
176
+ if (piProcess) {
177
+ ws.send(JSON.stringify({ type: 'ready' }));
178
+ sendCommand({ type: 'get_state' });
179
+ sendCommand({ type: 'get_messages' });
180
+ sendCommand({ type: 'get_session_stats' });
181
+ } else {
182
+ ws.send(JSON.stringify({ type: 'error', message: 'Pi process not running' }));
183
+ }
184
+
185
+ ws.on('message', (message) => {
186
+ try {
187
+ const msg = JSON.parse(message.toString());
188
+
189
+ switch (msg.type) {
190
+ case 'start':
191
+ if (!piProcess) spawnPi();
192
+ ws.send(JSON.stringify({ type: 'ready' }));
193
+ break;
194
+ case 'command':
195
+ if (msg.command) sendCommand(msg.command);
196
+ break;
197
+ case 'prompt':
198
+ sendCommand({ type: 'prompt', message: msg.message, images: msg.images });
199
+ break;
200
+ case 'abort':
201
+ sendCommand({ type: 'abort' });
202
+ break;
203
+ case 'steer':
204
+ sendCommand({ type: 'steer', message: msg.message });
205
+ break;
206
+ case 'extension_ui_response':
207
+ sendCommand(msg);
208
+ break;
209
+ }
210
+ } catch (err) {
211
+ console.error('[agent] Invalid message:', err);
212
+ }
213
+ });
214
+
215
+ ws.on('close', () => {
216
+ console.log('[agent] Client disconnected');
217
+ clients.delete(ws);
218
+ });
219
+
220
+ ws.on('error', (err) => {
221
+ console.error('[agent] WebSocket error:', err);
222
+ clients.delete(ws);
223
+ });
224
+ });
225
+
226
+ server.listen(PORT, () => {
227
+ console.log(`[agent] Running on port ${PORT}${isDev ? ' (dev mode)' : ''}`);
228
+ });
229
+
230
+ process.on('SIGTERM', () => {
231
+ console.log('[agent] Shutting down');
232
+ piProcess?.kill();
233
+ rl?.close();
234
+ for (const ws of clients) ws.close();
235
+ wss.close();
236
+ server.close(() => process.exit(0));
237
+ });
238
+ }
239
+
240
+ startServer();