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.
@@ -0,0 +1,91 @@
1
+ import * as vscode from 'vscode';
2
+ import { getCliClient } from '../../core/cliClient';
3
+
4
+ const DESTRUCTIVE_PATTERNS = [
5
+ /^auth\s+logout/i,
6
+ /\bdelete\b/i,
7
+ /\bremove\b/i,
8
+ /\bdestroy\b/i,
9
+ /\bdrop\b/i,
10
+ ];
11
+
12
+ const CONFIRMATION_PATTERNS = [/^cloud\s+deploy/i];
13
+
14
+ export interface CliToolInput {
15
+ command: string;
16
+ jsonOutput?: boolean;
17
+ }
18
+
19
+ export class AgentuityCliTool implements vscode.LanguageModelTool<CliToolInput> {
20
+ async invoke(
21
+ options: vscode.LanguageModelToolInvocationOptions<CliToolInput>,
22
+ _token: vscode.CancellationToken
23
+ ): Promise<vscode.LanguageModelToolResult> {
24
+ const { command, jsonOutput = true } = options.input;
25
+
26
+ if (!command || command.trim() === '') {
27
+ throw new Error('Command is required. Provide an agentuity CLI subcommand.');
28
+ }
29
+
30
+ for (const pattern of DESTRUCTIVE_PATTERNS) {
31
+ if (pattern.test(command)) {
32
+ throw new Error(
33
+ `Destructive command detected: "${command}". This command is not allowed via the AI assistant. Please run it manually in the terminal.`
34
+ );
35
+ }
36
+ }
37
+
38
+ const args = command.split(/\s+/).filter((arg) => arg.length > 0);
39
+
40
+ const cli = getCliClient();
41
+ const result = await cli.exec(args, { format: jsonOutput ? 'json' : 'text' });
42
+
43
+ if (!result.success) {
44
+ throw new Error(`CLI command failed: ${result.error}`);
45
+ }
46
+
47
+ const output =
48
+ typeof result.data === 'string' ? result.data : JSON.stringify(result.data, null, 2);
49
+
50
+ return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(output)]);
51
+ }
52
+
53
+ async prepareInvocation(
54
+ options: vscode.LanguageModelToolInvocationPrepareOptions<CliToolInput>,
55
+ _token: vscode.CancellationToken
56
+ ): Promise<vscode.PreparedToolInvocation | undefined> {
57
+ const { command } = options.input;
58
+
59
+ for (const pattern of CONFIRMATION_PATTERNS) {
60
+ if (pattern.test(command)) {
61
+ return {
62
+ invocationMessage: `Run deployment command: \`agentuity ${command}\``,
63
+ confirmationMessages: {
64
+ title: 'Deploy to Agentuity Cloud',
65
+ message: new vscode.MarkdownString(
66
+ `This will deploy your project to Agentuity Cloud.\n\n\`\`\`bash\nagentuity ${command}\n\`\`\`\n\nDo you want to continue?`
67
+ ),
68
+ },
69
+ };
70
+ }
71
+ }
72
+
73
+ return {
74
+ invocationMessage: `Running: \`agentuity ${command}\``,
75
+ };
76
+ }
77
+ }
78
+
79
+ export function registerCliTool(context: vscode.ExtensionContext): void {
80
+ if (!vscode.lm?.registerTool) {
81
+ return;
82
+ }
83
+
84
+ try {
85
+ const tool = new AgentuityCliTool();
86
+ const disposable = vscode.lm.registerTool('agentuity_run_cli', tool);
87
+ context.subscriptions.push(disposable);
88
+ } catch {
89
+ // LM API not available
90
+ }
91
+ }
@@ -0,0 +1,2 @@
1
+ export { registerChatParticipant } from './agentuityParticipant';
2
+ export { registerCliTool } from './cliTool';
@@ -0,0 +1,116 @@
1
+ import * as vscode from 'vscode';
2
+
3
+ export class AgentCodeLensProvider implements vscode.CodeLensProvider {
4
+ private _onDidChangeCodeLenses = new vscode.EventEmitter<void>();
5
+ readonly onDidChangeCodeLenses = this._onDidChangeCodeLenses.event;
6
+
7
+ // Match both: createAgent('name', { and createAgent({
8
+ private createAgentRegex = /createAgent\s*\(/g;
9
+
10
+ refresh(): void {
11
+ this._onDidChangeCodeLenses.fire();
12
+ }
13
+
14
+ provideCodeLenses(
15
+ document: vscode.TextDocument,
16
+ _token: vscode.CancellationToken
17
+ ): vscode.CodeLens[] | Thenable<vscode.CodeLens[]> {
18
+ const codeLenses: vscode.CodeLens[] = [];
19
+ const text = document.getText();
20
+
21
+ let match: RegExpExecArray | null;
22
+ this.createAgentRegex.lastIndex = 0;
23
+
24
+ while ((match = this.createAgentRegex.exec(text)) !== null) {
25
+ const position = document.positionAt(match.index);
26
+ const range = new vscode.Range(position, position);
27
+
28
+ const agentInfo = this.extractAgentInfo(document, match.index);
29
+
30
+ codeLenses.push(
31
+ new vscode.CodeLens(range, {
32
+ title: '$(play) Open in Workbench',
33
+ command: 'agentuity.codeLens.openInWorkbench',
34
+ arguments: [agentInfo],
35
+ tooltip: 'Open this agent in the Agentuity Workbench (requires dev server running)',
36
+ })
37
+ );
38
+
39
+ codeLenses.push(
40
+ new vscode.CodeLens(range, {
41
+ title: '$(pulse) View Sessions',
42
+ command: 'agentuity.codeLens.viewSessions',
43
+ arguments: [agentInfo],
44
+ tooltip: 'View sessions for this agent',
45
+ })
46
+ );
47
+ }
48
+
49
+ return codeLenses;
50
+ }
51
+
52
+ private extractAgentInfo(
53
+ document: vscode.TextDocument,
54
+ startIndex: number
55
+ ): AgentCodeLensInfo {
56
+ const text = document.getText();
57
+ const afterCreateAgent = text.substring(startIndex);
58
+
59
+ let name: string | undefined;
60
+ let identifier: string | undefined;
61
+
62
+ // Try to match createAgent('identifier', { pattern (first arg is the identifier)
63
+ const firstArgMatch = afterCreateAgent.match(/createAgent\s*\(\s*['"`]([^'"`]+)['"`]/);
64
+ if (firstArgMatch) {
65
+ identifier = firstArgMatch[1];
66
+ name = firstArgMatch[1];
67
+ }
68
+
69
+ // Also check for name property in the config object
70
+ const nameMatch = afterCreateAgent.match(/name\s*:\s*['"`]([^'"`]+)['"`]/);
71
+ if (nameMatch) {
72
+ name = nameMatch[1];
73
+ }
74
+
75
+ // Check for explicit identifier property (overrides first arg)
76
+ const identifierMatch = afterCreateAgent.match(/identifier\s*:\s*['"`]([^'"`]+)['"`]/);
77
+ if (identifierMatch) {
78
+ identifier = identifierMatch[1];
79
+ }
80
+
81
+ // Fallback: derive identifier from file path
82
+ if (!identifier) {
83
+ const relativePath = vscode.workspace.asRelativePath(document.uri);
84
+ const pathParts = relativePath.split('/');
85
+ const agentsIndex = pathParts.indexOf('agents');
86
+ if (agentsIndex !== -1 && agentsIndex < pathParts.length - 1) {
87
+ const agentPathParts = pathParts.slice(agentsIndex + 1);
88
+ const lastPart = agentPathParts[agentPathParts.length - 1];
89
+ if (lastPart === 'agent.ts' || lastPart === 'index.ts') {
90
+ agentPathParts.pop();
91
+ } else {
92
+ agentPathParts[agentPathParts.length - 1] = lastPart.replace(/\.(ts|js)$/, '');
93
+ }
94
+ if (agentPathParts.length > 0) {
95
+ identifier = agentPathParts.join('/');
96
+ }
97
+ }
98
+ }
99
+
100
+ return {
101
+ name,
102
+ identifier,
103
+ filePath: document.uri.fsPath,
104
+ };
105
+ }
106
+
107
+ dispose(): void {
108
+ this._onDidChangeCodeLenses.dispose();
109
+ }
110
+ }
111
+
112
+ export interface AgentCodeLensInfo {
113
+ name?: string;
114
+ identifier?: string;
115
+ filePath: string;
116
+ }
@@ -0,0 +1,132 @@
1
+ import * as vscode from 'vscode';
2
+ import { AgentCodeLensProvider, type AgentCodeLensInfo } from './agentCodeLensProvider';
3
+ import { getDevServerManager } from '../devServer';
4
+ import { getCurrentProject } from '../../core/project';
5
+ import { getAgentProvider } from '../agentExplorer';
6
+
7
+ const SESSIONS_BASE_URL = 'https://app-v1.agentuity.com';
8
+
9
+ export function registerCodeLens(context: vscode.ExtensionContext): AgentCodeLensProvider {
10
+ const provider = new AgentCodeLensProvider();
11
+
12
+ const selector: vscode.DocumentSelector = [
13
+ { language: 'typescript', scheme: 'file' },
14
+ { language: 'javascript', scheme: 'file' },
15
+ ];
16
+
17
+ context.subscriptions.push(
18
+ vscode.languages.registerCodeLensProvider(selector, provider)
19
+ );
20
+
21
+ context.subscriptions.push(
22
+ vscode.commands.registerCommand(
23
+ 'agentuity.codeLens.openInWorkbench',
24
+ async (info: AgentCodeLensInfo) => {
25
+ const devServer = getDevServerManager();
26
+
27
+ if (devServer.getState() !== 'running') {
28
+ const action = await vscode.window.showWarningMessage(
29
+ 'Dev server is not running. Start it to open the Workbench.',
30
+ 'Start Dev Server',
31
+ 'Cancel'
32
+ );
33
+
34
+ if (action === 'Start Dev Server') {
35
+ await vscode.commands.executeCommand('agentuity.dev.start');
36
+ await waitForDevServer(5000);
37
+
38
+ if (devServer.getState() !== 'running') {
39
+ vscode.window.showErrorMessage('Failed to start dev server');
40
+ return;
41
+ }
42
+ } else {
43
+ return;
44
+ }
45
+ }
46
+
47
+ const port = vscode.workspace.getConfiguration('agentuity').get<number>('devServer.port', 3500);
48
+ let url = `http://localhost:${port}/workbench`;
49
+ if (info.identifier) {
50
+ url += `?agent=${encodeURIComponent(info.identifier)}`;
51
+ }
52
+
53
+ await vscode.env.openExternal(vscode.Uri.parse(url));
54
+ }
55
+ )
56
+ );
57
+
58
+ context.subscriptions.push(
59
+ vscode.commands.registerCommand(
60
+ 'agentuity.codeLens.viewSessions',
61
+ async (info: AgentCodeLensInfo) => {
62
+ const project = getCurrentProject();
63
+ if (!project) {
64
+ vscode.window.showErrorMessage('No Agentuity project found');
65
+ return;
66
+ }
67
+
68
+ if (!info.identifier) {
69
+ vscode.window.showErrorMessage('Could not determine agent identifier');
70
+ return;
71
+ }
72
+
73
+ const agentProvider = getAgentProvider();
74
+ if (!agentProvider) {
75
+ vscode.window.showErrorMessage('Agent explorer not initialized');
76
+ return;
77
+ }
78
+
79
+ const agent = agentProvider.findAgentByIdentifier(info.identifier);
80
+
81
+ if (!agent) {
82
+ vscode.window.showWarningMessage(
83
+ `Agent "${info.identifier}" not found. Deploy your project first to view sessions.`
84
+ );
85
+ return;
86
+ }
87
+
88
+ const url = `${SESSIONS_BASE_URL}/projects/${project.projectId}/sessions?agent=${agent.id}`;
89
+ await vscode.env.openExternal(vscode.Uri.parse(url));
90
+ }
91
+ )
92
+ );
93
+
94
+ const devServer = getDevServerManager();
95
+ devServer.onStateChanged(() => {
96
+ provider.refresh();
97
+ });
98
+
99
+ context.subscriptions.push({ dispose: () => provider.dispose() });
100
+
101
+ return provider;
102
+ }
103
+
104
+ async function waitForDevServer(timeoutMs: number): Promise<boolean> {
105
+ const devServer = getDevServerManager();
106
+
107
+ return new Promise((resolve) => {
108
+ if (devServer.getState() === 'running') {
109
+ resolve(true);
110
+ return;
111
+ }
112
+
113
+ const timeout = setTimeout(() => {
114
+ disposable.dispose();
115
+ resolve(false);
116
+ }, timeoutMs);
117
+
118
+ const disposable = devServer.onStateChanged((state) => {
119
+ if (state === 'running') {
120
+ clearTimeout(timeout);
121
+ disposable.dispose();
122
+ resolve(true);
123
+ } else if (state === 'error' || state === 'stopped') {
124
+ clearTimeout(timeout);
125
+ disposable.dispose();
126
+ resolve(false);
127
+ }
128
+ });
129
+ });
130
+ }
131
+
132
+ export { AgentCodeLensProvider, type AgentCodeLensInfo };