agentuity-vscode 0.0.86
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/.vscode/launch.json +26 -0
- package/.vscode/tasks.json +22 -0
- package/.vscodeignore +22 -0
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/package.json +476 -0
- package/resources/icon.png +0 -0
- package/resources/icon.svg +1 -0
- package/src/core/auth.ts +128 -0
- package/src/core/baseTreeDataProvider.ts +92 -0
- package/src/core/cliClient.ts +777 -0
- package/src/core/index.ts +5 -0
- package/src/core/project.ts +98 -0
- package/src/core/readonlyDocument.ts +57 -0
- package/src/core/service.ts +208 -0
- package/src/extension.ts +260 -0
- package/src/features/agentExplorer/agentTreeData.ts +149 -0
- package/src/features/agentExplorer/index.ts +105 -0
- package/src/features/chat/agentuityParticipant.ts +838 -0
- package/src/features/chat/cliTool.ts +91 -0
- package/src/features/chat/index.ts +2 -0
- package/src/features/codeLens/agentCodeLensProvider.ts +116 -0
- package/src/features/codeLens/index.ts +132 -0
- package/src/features/dataExplorer/dataTreeData.ts +480 -0
- package/src/features/dataExplorer/index.ts +362 -0
- package/src/features/deploymentExplorer/deploymentTreeData.ts +238 -0
- package/src/features/deploymentExplorer/index.ts +107 -0
- package/src/features/devServer/devServerManager.ts +258 -0
- package/src/features/devServer/index.ts +52 -0
- package/src/features/workbench/index.ts +19 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import * as vscode from 'vscode';
|
|
2
|
+
import { spawn, exec, type ChildProcess } from 'child_process';
|
|
3
|
+
import { getCurrentProject } from '../../core/project';
|
|
4
|
+
import { getCliClient } from '../../core/cliClient';
|
|
5
|
+
|
|
6
|
+
export type DevServerState = 'stopped' | 'starting' | 'running' | 'error';
|
|
7
|
+
|
|
8
|
+
export class DevServerManager {
|
|
9
|
+
private process: ChildProcess | undefined;
|
|
10
|
+
private state: DevServerState = 'stopped';
|
|
11
|
+
private outputChannel: vscode.OutputChannel;
|
|
12
|
+
private statusBarItem: vscode.StatusBarItem;
|
|
13
|
+
private startupTimeoutId: NodeJS.Timeout | undefined;
|
|
14
|
+
private hasReceivedOutput = false;
|
|
15
|
+
|
|
16
|
+
private _onStateChanged = new vscode.EventEmitter<DevServerState>();
|
|
17
|
+
readonly onStateChanged = this._onStateChanged.event;
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
this.outputChannel = vscode.window.createOutputChannel('Agentuity Dev Server');
|
|
21
|
+
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
|
|
22
|
+
this.updateStatusBar();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private setState(state: DevServerState): void {
|
|
26
|
+
this.state = state;
|
|
27
|
+
this.updateStatusBar();
|
|
28
|
+
this._onStateChanged.fire(state);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private updateStatusBar(): void {
|
|
32
|
+
switch (this.state) {
|
|
33
|
+
case 'stopped':
|
|
34
|
+
this.statusBarItem.text = '$(debug-stop) Agentuity: Stopped';
|
|
35
|
+
this.statusBarItem.backgroundColor = undefined;
|
|
36
|
+
this.statusBarItem.command = 'agentuity.dev.start';
|
|
37
|
+
this.statusBarItem.tooltip = 'Click to start dev server';
|
|
38
|
+
break;
|
|
39
|
+
case 'starting':
|
|
40
|
+
this.statusBarItem.text = '$(loading~spin) Agentuity: Starting...';
|
|
41
|
+
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
|
|
42
|
+
'statusBarItem.warningBackground'
|
|
43
|
+
);
|
|
44
|
+
this.statusBarItem.command = undefined;
|
|
45
|
+
this.statusBarItem.tooltip = 'Dev server is starting';
|
|
46
|
+
break;
|
|
47
|
+
case 'running':
|
|
48
|
+
this.statusBarItem.text = '$(debug-start) Agentuity: Running';
|
|
49
|
+
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
|
|
50
|
+
'statusBarItem.prominentBackground'
|
|
51
|
+
);
|
|
52
|
+
this.statusBarItem.command = 'agentuity.dev.stop';
|
|
53
|
+
this.statusBarItem.tooltip = 'Click to stop dev server';
|
|
54
|
+
break;
|
|
55
|
+
case 'error':
|
|
56
|
+
this.statusBarItem.text = '$(error) Agentuity: Error';
|
|
57
|
+
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
|
|
58
|
+
'statusBarItem.errorBackground'
|
|
59
|
+
);
|
|
60
|
+
this.statusBarItem.command = 'agentuity.dev.showLogs';
|
|
61
|
+
this.statusBarItem.tooltip = 'Click to view logs';
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
this.statusBarItem.show();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getState(): DevServerState {
|
|
68
|
+
return this.state;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async start(): Promise<void> {
|
|
72
|
+
if (this.state === 'running' || this.state === 'starting') {
|
|
73
|
+
vscode.window.showWarningMessage('Dev server is already running');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const project = getCurrentProject();
|
|
78
|
+
if (!project) {
|
|
79
|
+
vscode.window.showErrorMessage('No Agentuity project found');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.setState('starting');
|
|
84
|
+
this.outputChannel.clear();
|
|
85
|
+
this.outputChannel.show(true);
|
|
86
|
+
this.hasReceivedOutput = false;
|
|
87
|
+
|
|
88
|
+
const cli = getCliClient();
|
|
89
|
+
const cliPath = cli.getCliPath();
|
|
90
|
+
const env = cli.getCliEnv();
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
this.process = spawn(cliPath, ['dev'], {
|
|
94
|
+
cwd: project.rootPath,
|
|
95
|
+
shell: true,
|
|
96
|
+
env,
|
|
97
|
+
// On Unix, create a new process group so we can kill the entire tree
|
|
98
|
+
detached: process.platform !== 'win32',
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
this.process.stdout?.on('data', (data: Buffer) => {
|
|
102
|
+
const text = data.toString();
|
|
103
|
+
this.outputChannel.append(text);
|
|
104
|
+
this.hasReceivedOutput = true;
|
|
105
|
+
|
|
106
|
+
// Detect ready signals from the dev server
|
|
107
|
+
if (text.includes('listening') || text.includes('started') || text.includes('ready')) {
|
|
108
|
+
this.clearStartupTimeout();
|
|
109
|
+
this.setState('running');
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
this.process.stderr?.on('data', (data: Buffer) => {
|
|
114
|
+
this.outputChannel.append(data.toString());
|
|
115
|
+
this.hasReceivedOutput = true;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
this.process.on('error', (err: Error) => {
|
|
119
|
+
this.clearStartupTimeout();
|
|
120
|
+
this.outputChannel.appendLine(`Error: ${err.message}`);
|
|
121
|
+
this.setState('error');
|
|
122
|
+
this.process = undefined;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
this.process.on('close', (code: number | null) => {
|
|
126
|
+
this.clearStartupTimeout();
|
|
127
|
+
this.outputChannel.appendLine(`\nDev server exited with code ${code}`);
|
|
128
|
+
if (this.state !== 'stopped') {
|
|
129
|
+
this.setState(code === 0 ? 'stopped' : 'error');
|
|
130
|
+
}
|
|
131
|
+
this.process = undefined;
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Timeout: if no ready signal after 10s, check if we got any output
|
|
135
|
+
this.startupTimeoutId = setTimeout(() => {
|
|
136
|
+
if (this.state === 'starting') {
|
|
137
|
+
if (this.hasReceivedOutput) {
|
|
138
|
+
// Got output but no ready signal - assume running
|
|
139
|
+
this.setState('running');
|
|
140
|
+
} else {
|
|
141
|
+
// No output at all - likely failed to start
|
|
142
|
+
this.setState('error');
|
|
143
|
+
void vscode.window
|
|
144
|
+
.showErrorMessage(
|
|
145
|
+
'Dev server failed to start. No output received.',
|
|
146
|
+
'View Logs'
|
|
147
|
+
)
|
|
148
|
+
.then((action) => {
|
|
149
|
+
if (action === 'View Logs') {
|
|
150
|
+
this.showLogs();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}, 10000);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
158
|
+
this.outputChannel.appendLine(`Failed to start: ${message}`);
|
|
159
|
+
this.setState('error');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private clearStartupTimeout(): void {
|
|
164
|
+
if (this.startupTimeoutId) {
|
|
165
|
+
clearTimeout(this.startupTimeoutId);
|
|
166
|
+
this.startupTimeoutId = undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async stop(): Promise<void> {
|
|
171
|
+
this.clearStartupTimeout();
|
|
172
|
+
|
|
173
|
+
if (!this.process) {
|
|
174
|
+
this.setState('stopped');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.outputChannel.appendLine('\nStopping dev server...');
|
|
179
|
+
this.setState('stopped');
|
|
180
|
+
|
|
181
|
+
const pid = this.process.pid;
|
|
182
|
+
if (pid) {
|
|
183
|
+
// Kill the entire process tree, not just the shell
|
|
184
|
+
await this.killProcessTree(pid);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.process = undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private async killProcessTree(pid: number): Promise<void> {
|
|
191
|
+
return new Promise((resolve) => {
|
|
192
|
+
if (process.platform === 'win32') {
|
|
193
|
+
// Windows: use taskkill to kill process tree
|
|
194
|
+
exec(`taskkill /pid ${pid} /T /F`, () => resolve());
|
|
195
|
+
} else {
|
|
196
|
+
// Unix: kill the process group (negative pid)
|
|
197
|
+
try {
|
|
198
|
+
process.kill(-pid, 'SIGTERM');
|
|
199
|
+
} catch {
|
|
200
|
+
// Process group might not exist, try killing just the pid
|
|
201
|
+
try {
|
|
202
|
+
process.kill(pid, 'SIGTERM');
|
|
203
|
+
} catch {
|
|
204
|
+
// Process already dead
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Force kill after timeout
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
try {
|
|
211
|
+
process.kill(-pid, 'SIGKILL');
|
|
212
|
+
} catch {
|
|
213
|
+
try {
|
|
214
|
+
process.kill(pid, 'SIGKILL');
|
|
215
|
+
} catch {
|
|
216
|
+
// Already dead
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
resolve();
|
|
220
|
+
}, 2000);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async restart(): Promise<void> {
|
|
226
|
+
await this.stop();
|
|
227
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
228
|
+
await this.start();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
showLogs(): void {
|
|
232
|
+
this.outputChannel.show();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
dispose(): void {
|
|
236
|
+
this.clearStartupTimeout();
|
|
237
|
+
this.stop();
|
|
238
|
+
this.outputChannel.dispose();
|
|
239
|
+
this.statusBarItem.dispose();
|
|
240
|
+
this._onStateChanged.dispose();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let _devServerManager: DevServerManager | undefined;
|
|
245
|
+
|
|
246
|
+
export function getDevServerManager(): DevServerManager {
|
|
247
|
+
if (!_devServerManager) {
|
|
248
|
+
_devServerManager = new DevServerManager();
|
|
249
|
+
}
|
|
250
|
+
return _devServerManager;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function disposeDevServerManager(): void {
|
|
254
|
+
if (_devServerManager) {
|
|
255
|
+
_devServerManager.dispose();
|
|
256
|
+
_devServerManager = undefined;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as vscode from 'vscode';
|
|
2
|
+
import { getDevServerManager, disposeDevServerManager } from './devServerManager';
|
|
3
|
+
import { requireProject } from '../../core/project';
|
|
4
|
+
import { requireAuth } from '../../core/auth';
|
|
5
|
+
|
|
6
|
+
export function registerDevServerCommands(context: vscode.ExtensionContext): void {
|
|
7
|
+
const manager = getDevServerManager();
|
|
8
|
+
|
|
9
|
+
void vscode.commands.executeCommand(
|
|
10
|
+
'setContext',
|
|
11
|
+
'agentuity.devServerRunning',
|
|
12
|
+
manager.getState() === 'running'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
manager.onStateChanged((state) => {
|
|
16
|
+
void vscode.commands.executeCommand('setContext', 'agentuity.devServerRunning', state === 'running');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
context.subscriptions.push(
|
|
20
|
+
vscode.commands.registerCommand('agentuity.dev.start', async () => {
|
|
21
|
+
if (!(await requireAuth()) || !requireProject()) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await manager.start();
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
context.subscriptions.push(
|
|
29
|
+
vscode.commands.registerCommand('agentuity.dev.stop', async () => {
|
|
30
|
+
await manager.stop();
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
context.subscriptions.push(
|
|
35
|
+
vscode.commands.registerCommand('agentuity.dev.restart', async () => {
|
|
36
|
+
if (!(await requireAuth()) || !requireProject()) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await manager.restart();
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
context.subscriptions.push(
|
|
44
|
+
vscode.commands.registerCommand('agentuity.dev.showLogs', () => {
|
|
45
|
+
manager.showLogs();
|
|
46
|
+
})
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
context.subscriptions.push({ dispose: () => disposeDevServerManager() });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { getDevServerManager, type DevServerState } from './devServerManager';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as vscode from 'vscode';
|
|
2
|
+
import { getCurrentProject } from '../../core/project';
|
|
3
|
+
|
|
4
|
+
const WORKBENCH_BASE_URL = 'https://app.agentuity.com';
|
|
5
|
+
|
|
6
|
+
export function registerWorkbenchCommands(context: vscode.ExtensionContext): void {
|
|
7
|
+
context.subscriptions.push(
|
|
8
|
+
vscode.commands.registerCommand('agentuity.workbench.open', async () => {
|
|
9
|
+
const project = getCurrentProject();
|
|
10
|
+
|
|
11
|
+
let url = WORKBENCH_BASE_URL;
|
|
12
|
+
if (project) {
|
|
13
|
+
url = `${WORKBENCH_BASE_URL}/projects/${project.projectId}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await vscode.env.openExternal(vscode.Uri.parse(url));
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"outDir": "./dist",
|
|
16
|
+
"rootDir": "./src"
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
20
|
+
}
|