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,838 @@
1
+ import * as vscode from 'vscode';
2
+ import { getCliClient } from '../../core/cliClient';
3
+ import { getAuthStatus } from '../../core/auth';
4
+ import { hasProject, getCurrentProject } from '../../core/project';
5
+ import { getDevServerManager } from '../devServer';
6
+
7
+ // Minimal CLI reference as fallback when dynamic help is unavailable
8
+ const CLI_REFERENCE_FALLBACK = `
9
+ # Agentuity CLI Quick Reference
10
+
11
+ ## Key Commands
12
+ - \`agentuity auth login\` - Login to Agentuity
13
+ - \`agentuity dev\` - Start the development server
14
+ - \`agentuity cloud deploy\` - Deploy to Agentuity Cloud
15
+ - \`agentuity cloud agent list\` - List deployed agents
16
+ - \`agentuity cloud session list\` - List sessions
17
+
18
+ ## JSON Output
19
+ Add \`--json\` before the command: \`agentuity --json cloud agent list\`
20
+
21
+ Use \`/help\` for complete documentation.
22
+ `;
23
+
24
+ interface SlashCommand {
25
+ name: string;
26
+ description: string;
27
+ }
28
+
29
+ const SLASH_COMMANDS: SlashCommand[] = [
30
+ { name: 'help', description: 'Show CLI reference and getting started guide' },
31
+ { name: 'agents', description: 'List agents in this project' },
32
+ { name: 'deploy', description: 'Deploy to Agentuity Cloud' },
33
+ { name: 'dev', description: 'Start or stop the dev server' },
34
+ { name: 'sessions', description: 'Show recent sessions' },
35
+ { name: 'status', description: 'Show project and auth status' },
36
+ { name: 'kv', description: 'List KV namespaces or keys in a namespace' },
37
+ { name: 'db', description: 'List databases with connection info' },
38
+ { name: 'vector', description: 'Search vectors in a namespace' },
39
+ { name: 'deployments', description: 'List deployments with details' },
40
+ { name: 'logs', description: 'View logs for a session' },
41
+ ];
42
+
43
+ export function registerChatParticipant(context: vscode.ExtensionContext): void {
44
+ if (!vscode.chat?.createChatParticipant) {
45
+ return;
46
+ }
47
+
48
+ try {
49
+ const participant = vscode.chat.createChatParticipant(
50
+ 'agentuity.assistant',
51
+ handleChatRequest
52
+ );
53
+
54
+ participant.iconPath = vscode.Uri.joinPath(context.extensionUri, 'resources', 'icon.svg');
55
+
56
+ context.subscriptions.push(participant);
57
+ } catch {
58
+ // Chat API not available in this version of VSCode
59
+ }
60
+ }
61
+
62
+ async function handleChatRequest(
63
+ request: vscode.ChatRequest,
64
+ context: vscode.ChatContext,
65
+ stream: vscode.ChatResponseStream,
66
+ token: vscode.CancellationToken
67
+ ): Promise<vscode.ChatResult> {
68
+ const authStatus = getAuthStatus();
69
+
70
+ if (authStatus.state === 'cli-missing') {
71
+ stream.markdown('## Agentuity CLI Not Found\n\n');
72
+ stream.markdown('The Agentuity CLI is required. Install it with:\n\n');
73
+ stream.markdown('```bash\nbun install -g @agentuity/cli\n```\n\n');
74
+ stream.markdown(
75
+ 'Or visit the [Getting Started Guide](https://agentuity.dev/Introduction/getting-started)'
76
+ );
77
+ stream.button({
78
+ title: 'Install CLI',
79
+ command: 'agentuity.installCli',
80
+ });
81
+ return { metadata: { command: 'error' } };
82
+ }
83
+
84
+ if (authStatus.state === 'unauthenticated') {
85
+ stream.markdown('## Login Required\n\n');
86
+ stream.markdown('Please login to Agentuity to continue:\n\n');
87
+ stream.markdown('```bash\nagentuity auth login\n```\n');
88
+ stream.button({
89
+ title: 'Login',
90
+ command: 'agentuity.login',
91
+ });
92
+ return { metadata: { command: 'error' } };
93
+ }
94
+
95
+ const command = request.command;
96
+ if (command) {
97
+ return handleSlashCommand(command, request.prompt, stream, token);
98
+ }
99
+
100
+ return handleNaturalLanguage(request, context, stream, token);
101
+ }
102
+
103
+ async function handleSlashCommand(
104
+ command: string,
105
+ args: string,
106
+ stream: vscode.ChatResponseStream,
107
+ _token: vscode.CancellationToken
108
+ ): Promise<vscode.ChatResult> {
109
+ switch (command) {
110
+ case 'help':
111
+ return handleHelp(stream);
112
+ case 'agents':
113
+ return handleListAgents(stream);
114
+ case 'deploy':
115
+ return handleDeploy(stream);
116
+ case 'dev':
117
+ return handleDevServer(args, stream);
118
+ case 'sessions':
119
+ return handleSessions(stream);
120
+ case 'status':
121
+ return handleStatus(stream);
122
+ case 'kv':
123
+ return handleKv(args, stream);
124
+ case 'db':
125
+ return handleDb(stream);
126
+ case 'vector':
127
+ return handleVector(args, stream);
128
+ case 'deployments':
129
+ return handleDeployments(stream);
130
+ case 'logs':
131
+ return handleLogs(args, stream);
132
+ default:
133
+ stream.markdown(`Unknown command: /${command}\n\nAvailable commands:\n`);
134
+ for (const cmd of SLASH_COMMANDS) {
135
+ stream.markdown(`- \`/${cmd.name}\` - ${cmd.description}\n`);
136
+ }
137
+ return { metadata: { command: 'unknown' } };
138
+ }
139
+ }
140
+
141
+ async function handleNaturalLanguage(
142
+ request: vscode.ChatRequest,
143
+ _context: vscode.ChatContext,
144
+ stream: vscode.ChatResponseStream,
145
+ token: vscode.CancellationToken
146
+ ): Promise<vscode.ChatResult> {
147
+ const prompt = request.prompt.toLowerCase();
148
+
149
+ if (prompt.includes('agent') && (prompt.includes('list') || prompt.includes('show'))) {
150
+ return handleListAgents(stream);
151
+ }
152
+
153
+ if (prompt.includes('deploy') && !prompt.includes('deployment')) {
154
+ return handleDeploy(stream);
155
+ }
156
+
157
+ if (prompt.includes('session') && (prompt.includes('list') || prompt.includes('show') || prompt.includes('recent'))) {
158
+ return handleSessions(stream);
159
+ }
160
+
161
+ if (prompt.includes('dev') && (prompt.includes('start') || prompt.includes('stop'))) {
162
+ const action = prompt.includes('stop') ? 'stop' : 'start';
163
+ return handleDevServer(action, stream);
164
+ }
165
+
166
+ if (prompt.includes('status') || prompt.includes('whoami')) {
167
+ return handleStatus(stream);
168
+ }
169
+
170
+ if (
171
+ prompt.includes('help') ||
172
+ prompt.includes('command') ||
173
+ prompt.includes('how do i') ||
174
+ prompt.includes('what can')
175
+ ) {
176
+ return handleHelp(stream);
177
+ }
178
+
179
+ // KV storage patterns
180
+ if (
181
+ prompt.includes('kv') ||
182
+ prompt.includes('key value') ||
183
+ prompt.includes('key-value') ||
184
+ (prompt.includes('storage') && prompt.includes('key'))
185
+ ) {
186
+ return handleKv('', stream);
187
+ }
188
+
189
+ // Database patterns
190
+ if (
191
+ prompt.includes('database') ||
192
+ prompt.includes('db') ||
193
+ prompt.includes('connection string') ||
194
+ prompt.includes('postgres')
195
+ ) {
196
+ return handleDb(stream);
197
+ }
198
+
199
+ // Vector search patterns
200
+ if (
201
+ prompt.includes('vector') ||
202
+ prompt.includes('embedding') ||
203
+ prompt.includes('semantic search')
204
+ ) {
205
+ return handleVector('', stream);
206
+ }
207
+
208
+ // Deployment patterns
209
+ if (
210
+ prompt.includes('deployment') ||
211
+ (prompt.includes('list') && prompt.includes('deploy'))
212
+ ) {
213
+ return handleDeployments(stream);
214
+ }
215
+
216
+ // Logs patterns
217
+ if (prompt.includes('log') && (prompt.includes('session') || prompt.includes('view') || prompt.includes('show'))) {
218
+ return handleLogs('', stream);
219
+ }
220
+
221
+ const models = await vscode.lm.selectChatModels({
222
+ vendor: 'copilot',
223
+ family: 'gpt-4o',
224
+ });
225
+
226
+ if (models.length === 0) {
227
+ return handleFallback(request.prompt, stream);
228
+ }
229
+
230
+ const model = models[0];
231
+
232
+ if (token.isCancellationRequested) {
233
+ return { metadata: { command: 'cancelled' } };
234
+ }
235
+
236
+ const projectContext = await gatherProjectContext(token);
237
+
238
+ const systemPrompt = `You are the Agentuity AI assistant, helping developers build and manage AI agents using the Agentuity platform.
239
+
240
+ ## Available Slash Commands
241
+ - /help - Show complete CLI documentation
242
+ - /agents - List agents in this project
243
+ - /deploy - Deploy to Agentuity Cloud
244
+ - /dev - Start or stop the dev server
245
+ - /sessions - Show recent sessions
246
+ - /status - Show project and auth status
247
+
248
+ ${CLI_REFERENCE_FALLBACK}
249
+
250
+ ## Current Project Context
251
+ ${projectContext}
252
+
253
+ ## Your Role
254
+ - Help users understand and use the Agentuity CLI and SDK
255
+ - Answer questions about building agents with Agentuity
256
+ - Suggest appropriate CLI commands for tasks
257
+ - Explain error messages and troubleshoot issues
258
+ - Suggest slash commands when they would be helpful
259
+
260
+ ## Guidelines
261
+ - Be concise and helpful
262
+ - Format CLI commands as code blocks
263
+ - For detailed CLI help, suggest the user type \`/help\`
264
+ - For destructive operations (delete, deploy), always confirm with the user first
265
+ - Link to https://agentuity.dev for documentation`;
266
+
267
+ const messages: vscode.LanguageModelChatMessage[] = [
268
+ vscode.LanguageModelChatMessage.User(systemPrompt),
269
+ vscode.LanguageModelChatMessage.User(request.prompt),
270
+ ];
271
+
272
+ try {
273
+ const response = await model.sendRequest(messages, {}, token);
274
+
275
+ for await (const chunk of response.text) {
276
+ if (token.isCancellationRequested) {
277
+ return { metadata: { command: 'cancelled' } };
278
+ }
279
+ stream.markdown(chunk);
280
+ }
281
+ } catch (err) {
282
+ if (token.isCancellationRequested) {
283
+ return { metadata: { command: 'cancelled' } };
284
+ }
285
+ if (err instanceof vscode.LanguageModelError) {
286
+ stream.markdown(`Error: ${err.message}\n\n`);
287
+ stream.markdown('Try asking a simpler question or use a slash command like `/help`.');
288
+ }
289
+ return { metadata: { command: 'error' } };
290
+ }
291
+
292
+ return { metadata: { command: 'chat' } };
293
+ }
294
+
295
+ async function gatherProjectContext(token?: vscode.CancellationToken): Promise<string> {
296
+ const lines: string[] = [];
297
+
298
+ const authStatus = getAuthStatus();
299
+ lines.push(`- Authenticated: ${authStatus.state === 'authenticated' ? 'Yes' : 'No'}`);
300
+ if (authStatus.user) {
301
+ lines.push(`- User: ${authStatus.user.email}`);
302
+ }
303
+
304
+ if (token?.isCancellationRequested) {
305
+ return lines.join('\n');
306
+ }
307
+
308
+ const project = getCurrentProject();
309
+ if (project) {
310
+ lines.push(`- Project ID: ${project.projectId}`);
311
+ lines.push(`- Org ID: ${project.orgId}`);
312
+ if (project.region) {
313
+ lines.push(`- Region: ${project.region}`);
314
+ }
315
+ } else {
316
+ lines.push('- No Agentuity project detected in workspace');
317
+ }
318
+
319
+ const devServer = getDevServerManager();
320
+ lines.push(`- Dev Server: ${devServer.getState()}`);
321
+
322
+ if (hasProject() && !token?.isCancellationRequested) {
323
+ try {
324
+ const cli = getCliClient();
325
+ const agentsResult = await cli.listAgents();
326
+ if (token?.isCancellationRequested) {
327
+ return lines.join('\n');
328
+ }
329
+ if (agentsResult.success && agentsResult.data) {
330
+ lines.push(`- Agents in project: ${agentsResult.data.length}`);
331
+ for (const agent of agentsResult.data.slice(0, 5)) {
332
+ lines.push(` - ${agent.name} (${agent.identifier || agent.id})`);
333
+ }
334
+ }
335
+ } catch {
336
+ // Ignore errors gathering context
337
+ }
338
+ }
339
+
340
+ return lines.join('\n');
341
+ }
342
+
343
+ async function handleHelp(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
344
+ stream.progress('Loading documentation from CLI...');
345
+
346
+ const cli = getCliClient();
347
+ const result = await cli.getAiPrompt();
348
+
349
+ if (result.success && result.data) {
350
+ stream.markdown(result.data);
351
+ } else {
352
+ stream.markdown('*Could not load dynamic help from CLI. Showing quick reference:*\n');
353
+ stream.markdown(CLI_REFERENCE_FALLBACK);
354
+ }
355
+
356
+ stream.markdown('\n\n## Quick Actions\n\n');
357
+ stream.button({ title: 'Start Dev Server', command: 'agentuity.dev.start' });
358
+ stream.button({ title: 'Deploy', command: 'agentuity.deploy' });
359
+ stream.button({ title: 'Open Workbench', command: 'agentuity.workbench.open' });
360
+
361
+ return { metadata: { command: 'help' } };
362
+ }
363
+
364
+ async function handleListAgents(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
365
+ if (!hasProject()) {
366
+ stream.markdown('## No Project Found\n\n');
367
+ stream.markdown('Open a folder containing `agentuity.json` to see your agents.\n\n');
368
+ stream.button({ title: 'Create Project', command: 'agentuity.createProject' });
369
+ return { metadata: { command: 'agents' } };
370
+ }
371
+
372
+ stream.progress('Fetching agents...');
373
+
374
+ const cli = getCliClient();
375
+ const result = await cli.listAgents();
376
+
377
+ if (!result.success) {
378
+ stream.markdown(`Failed to fetch agents: ${result.error}`);
379
+ return { metadata: { command: 'agents' } };
380
+ }
381
+
382
+ const agents = result.data || [];
383
+
384
+ if (agents.length === 0) {
385
+ stream.markdown('## No Agents Found\n\n');
386
+ stream.markdown('Create a new agent by adding a file in `src/agent/`.\n\n');
387
+ stream.markdown(
388
+ 'Check the [documentation](https://agentuity.dev/Introduction/getting-started) for examples.'
389
+ );
390
+ return { metadata: { command: 'agents' } };
391
+ }
392
+
393
+ stream.markdown(`## Agents (${agents.length})\n\n`);
394
+
395
+ for (const agent of agents) {
396
+ const identifier = agent.identifier || agent.metadata?.identifier || agent.id;
397
+ stream.markdown(`### ${agent.name}\n`);
398
+ if (agent.description) {
399
+ stream.markdown(`${agent.description}\n\n`);
400
+ }
401
+ stream.markdown(`\`${identifier}\`\n\n`);
402
+ }
403
+
404
+ stream.markdown('---\n\n');
405
+ stream.button({ title: 'View in Explorer', command: 'agentuity.agents.refresh' });
406
+
407
+ return { metadata: { command: 'agents' } };
408
+ }
409
+
410
+ async function handleDeploy(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
411
+ if (!hasProject()) {
412
+ stream.markdown('## No Project Found\n\n');
413
+ stream.markdown('You need an Agentuity project to deploy.\n\n');
414
+ stream.button({ title: 'Create Project', command: 'agentuity.createProject' });
415
+ return { metadata: { command: 'deploy' } };
416
+ }
417
+
418
+ stream.markdown('## Deploy to Agentuity Cloud\n\n');
419
+ stream.markdown('This will deploy your agents to Agentuity Cloud.\n\n');
420
+ stream.markdown('```bash\nagentuity cloud deploy\n```\n\n');
421
+ stream.button({ title: 'Deploy Now', command: 'agentuity.deploy' });
422
+
423
+ return { metadata: { command: 'deploy' } };
424
+ }
425
+
426
+ async function handleDevServer(
427
+ args: string,
428
+ stream: vscode.ChatResponseStream
429
+ ): Promise<vscode.ChatResult> {
430
+ const devServer = getDevServerManager();
431
+ const currentState = devServer.getState();
432
+
433
+ if (args.includes('stop')) {
434
+ if (currentState === 'stopped') {
435
+ stream.markdown('Dev server is not running.');
436
+ } else {
437
+ stream.markdown('Stopping dev server...\n\n');
438
+ stream.button({ title: 'Stop Dev Server', command: 'agentuity.dev.stop' });
439
+ }
440
+ return { metadata: { command: 'dev' } };
441
+ }
442
+
443
+ if (args.includes('start') || args.trim() === '') {
444
+ if (currentState === 'running') {
445
+ stream.markdown('Dev server is already running.\n\n');
446
+ stream.button({ title: 'Show Logs', command: 'agentuity.dev.showLogs' });
447
+ stream.button({ title: 'Restart', command: 'agentuity.dev.restart' });
448
+ } else {
449
+ stream.markdown('## Start Dev Server\n\n');
450
+ stream.markdown('This will start the Agentuity dev server for local testing.\n\n');
451
+ stream.markdown('```bash\nagentuity dev\n```\n\n');
452
+ stream.button({ title: 'Start Dev Server', command: 'agentuity.dev.start' });
453
+ }
454
+ return { metadata: { command: 'dev' } };
455
+ }
456
+
457
+ stream.markdown(`## Dev Server Status: ${currentState}\n\n`);
458
+ if (currentState === 'running') {
459
+ stream.button({ title: 'Stop', command: 'agentuity.dev.stop' });
460
+ stream.button({ title: 'Restart', command: 'agentuity.dev.restart' });
461
+ stream.button({ title: 'Show Logs', command: 'agentuity.dev.showLogs' });
462
+ } else {
463
+ stream.button({ title: 'Start', command: 'agentuity.dev.start' });
464
+ }
465
+
466
+ return { metadata: { command: 'dev' } };
467
+ }
468
+
469
+ async function handleSessions(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
470
+ if (!hasProject()) {
471
+ stream.markdown('## No Project Found\n\n');
472
+ stream.markdown('Open an Agentuity project to view sessions.\n\n');
473
+ return { metadata: { command: 'sessions' } };
474
+ }
475
+
476
+ stream.progress('Fetching recent sessions...');
477
+
478
+ const cli = getCliClient();
479
+ const result = await cli.listSessions({ count: 10 });
480
+
481
+ if (!result.success) {
482
+ stream.markdown(`Failed to fetch sessions: ${result.error}`);
483
+ return { metadata: { command: 'sessions' } };
484
+ }
485
+
486
+ const sessions = result.data || [];
487
+
488
+ if (sessions.length === 0) {
489
+ stream.markdown('## No Sessions Found\n\n');
490
+ stream.markdown('Run your agents to see session data here.\n\n');
491
+ stream.button({ title: 'Start Dev Server', command: 'agentuity.dev.start' });
492
+ return { metadata: { command: 'sessions' } };
493
+ }
494
+
495
+ stream.markdown(`## Recent Sessions (${sessions.length})\n\n`);
496
+ stream.markdown('| Status | ID | Time | Duration | Trigger |\n');
497
+ stream.markdown('|--------|-----|------|----------|--------|\n');
498
+
499
+ for (const session of sessions) {
500
+ const status = session.success ? '✓' : '✗';
501
+ const shortId = session.id.substring(0, 8);
502
+ const time = new Date(session.created_at).toLocaleString();
503
+ const duration = session.duration
504
+ ? `${(session.duration / 1_000_000).toFixed(0)}ms`
505
+ : '-';
506
+ stream.markdown(`| ${status} | ${shortId} | ${time} | ${duration} | ${session.trigger} |\n`);
507
+ }
508
+
509
+ stream.markdown('\n');
510
+
511
+ return { metadata: { command: 'sessions' } };
512
+ }
513
+
514
+ async function handleStatus(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
515
+ const authStatus = getAuthStatus();
516
+ const project = getCurrentProject();
517
+ const devServer = getDevServerManager();
518
+ const cli = getCliClient();
519
+
520
+ stream.markdown('## Agentuity Status\n\n');
521
+
522
+ stream.markdown('### Authentication\n');
523
+ if (authStatus.state === 'authenticated' && authStatus.user) {
524
+ stream.markdown(`✓ Logged in as **${authStatus.user.email}**\n\n`);
525
+ } else {
526
+ stream.markdown(`✗ Not logged in\n\n`);
527
+ stream.button({ title: 'Login', command: 'agentuity.login' });
528
+ }
529
+
530
+ // Show current CLI profile
531
+ const profileResult = await cli.getCurrentProfile();
532
+ if (profileResult.success && profileResult.data) {
533
+ stream.markdown(`### CLI Profile\n`);
534
+ stream.markdown(`Active: \`${profileResult.data}\`\n\n`);
535
+ }
536
+
537
+ stream.markdown('### Project\n');
538
+ if (project) {
539
+ stream.markdown(`✓ Project: \`${project.projectId}\`\n`);
540
+ stream.markdown(` Org: \`${project.orgId}\`\n`);
541
+ if (project.region) {
542
+ stream.markdown(` Region: ${project.region}\n`);
543
+ }
544
+ stream.markdown('\n');
545
+ } else {
546
+ stream.markdown('✗ No project detected\n\n');
547
+ stream.button({ title: 'Create Project', command: 'agentuity.createProject' });
548
+ }
549
+
550
+ stream.markdown('### Dev Server\n');
551
+ const state = devServer.getState();
552
+ const stateIcon = state === 'running' ? '✓' : state === 'error' ? '✗' : '○';
553
+ stream.markdown(`${stateIcon} ${state}\n\n`);
554
+
555
+ if (state === 'running') {
556
+ stream.button({ title: 'Stop', command: 'agentuity.dev.stop' });
557
+ stream.button({ title: 'Show Logs', command: 'agentuity.dev.showLogs' });
558
+ } else if (project) {
559
+ stream.button({ title: 'Start', command: 'agentuity.dev.start' });
560
+ }
561
+
562
+ return { metadata: { command: 'status' } };
563
+ }
564
+
565
+ async function handleKv(
566
+ args: string,
567
+ stream: vscode.ChatResponseStream
568
+ ): Promise<vscode.ChatResult> {
569
+ if (!hasProject()) {
570
+ stream.markdown('## No Project Found\n\n');
571
+ stream.markdown('Open an Agentuity project to view KV data.\n\n');
572
+ return { metadata: { command: 'kv' } };
573
+ }
574
+
575
+ const cli = getCliClient();
576
+ const namespace = args.trim();
577
+
578
+ if (namespace) {
579
+ stream.progress(`Fetching keys in ${namespace}...`);
580
+ const result = await cli.listKvKeys(namespace);
581
+
582
+ if (!result.success) {
583
+ stream.markdown(`Failed to fetch keys: ${result.error}`);
584
+ return { metadata: { command: 'kv' } };
585
+ }
586
+
587
+ const keys = result.data?.keys || [];
588
+
589
+ if (keys.length === 0) {
590
+ stream.markdown(`## KV Namespace: ${namespace}\n\n`);
591
+ stream.markdown('No keys found in this namespace.\n');
592
+ return { metadata: { command: 'kv' } };
593
+ }
594
+
595
+ stream.markdown(`## KV Namespace: ${namespace} (${keys.length} keys)\n\n`);
596
+ for (const key of keys.slice(0, 20)) {
597
+ stream.markdown(`- \`${key}\`\n`);
598
+ }
599
+ if (keys.length > 20) {
600
+ stream.markdown(`\n*...and ${keys.length - 20} more*\n`);
601
+ }
602
+ } else {
603
+ stream.progress('Fetching KV namespaces...');
604
+ const result = await cli.listKvNamespaces();
605
+
606
+ if (!result.success) {
607
+ stream.markdown(`Failed to fetch namespaces: ${result.error}`);
608
+ return { metadata: { command: 'kv' } };
609
+ }
610
+
611
+ const namespaces = result.data || [];
612
+
613
+ if (namespaces.length === 0) {
614
+ stream.markdown('## KV Namespaces\n\n');
615
+ stream.markdown('No KV namespaces found.\n');
616
+ return { metadata: { command: 'kv' } };
617
+ }
618
+
619
+ stream.markdown(`## KV Namespaces (${namespaces.length})\n\n`);
620
+ for (const ns of namespaces) {
621
+ stream.markdown(`- \`${ns}\` - use \`/kv ${ns}\` to list keys\n`);
622
+ }
623
+ }
624
+
625
+ return { metadata: { command: 'kv' } };
626
+ }
627
+
628
+ async function handleDb(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
629
+ if (!hasProject()) {
630
+ stream.markdown('## No Project Found\n\n');
631
+ stream.markdown('Open an Agentuity project to view databases.\n\n');
632
+ return { metadata: { command: 'db' } };
633
+ }
634
+
635
+ stream.progress('Fetching databases...');
636
+
637
+ const cli = getCliClient();
638
+ const result = await cli.listDatabases();
639
+
640
+ if (!result.success) {
641
+ stream.markdown(`Failed to fetch databases: ${result.error}`);
642
+ return { metadata: { command: 'db' } };
643
+ }
644
+
645
+ const databases = result.data?.databases || [];
646
+
647
+ if (databases.length === 0) {
648
+ stream.markdown('## Databases\n\n');
649
+ stream.markdown('No databases found.\n');
650
+ return { metadata: { command: 'db' } };
651
+ }
652
+
653
+ stream.markdown(`## Databases (${databases.length})\n\n`);
654
+ for (const db of databases) {
655
+ stream.markdown(`### ${db.name}\n`);
656
+ stream.markdown(`\`\`\`\n${db.url}\n\`\`\`\n\n`);
657
+ }
658
+
659
+ stream.button({ title: 'View in Data Explorer', command: 'agentuity.data.refresh' });
660
+
661
+ return { metadata: { command: 'db' } };
662
+ }
663
+
664
+ async function handleVector(
665
+ args: string,
666
+ stream: vscode.ChatResponseStream
667
+ ): Promise<vscode.ChatResult> {
668
+ if (!hasProject()) {
669
+ stream.markdown('## No Project Found\n\n');
670
+ stream.markdown('Open an Agentuity project to search vectors.\n\n');
671
+ return { metadata: { command: 'vector' } };
672
+ }
673
+
674
+ const parts = args.trim().split(/\s+/);
675
+ const namespace = parts[0];
676
+ const query = parts.slice(1).join(' ');
677
+
678
+ if (!namespace || !query) {
679
+ stream.markdown('## Vector Search\n\n');
680
+ stream.markdown('Usage: `/vector <namespace> <query>`\n\n');
681
+ stream.markdown('Example: `/vector my-namespace what is machine learning?`\n');
682
+ return { metadata: { command: 'vector' } };
683
+ }
684
+
685
+ stream.progress(`Searching vectors in ${namespace}...`);
686
+
687
+ const cli = getCliClient();
688
+ const result = await cli.vectorSearch(namespace, query);
689
+
690
+ if (!result.success) {
691
+ stream.markdown(`Failed to search vectors: ${result.error}`);
692
+ return { metadata: { command: 'vector' } };
693
+ }
694
+
695
+ const results = result.data?.results || [];
696
+
697
+ if (results.length === 0) {
698
+ stream.markdown(`## Vector Search: "${query}"\n\n`);
699
+ stream.markdown('No results found.\n');
700
+ return { metadata: { command: 'vector' } };
701
+ }
702
+
703
+ stream.markdown(`## Vector Search: "${query}" (${results.length} results)\n\n`);
704
+ for (const item of results.slice(0, 10)) {
705
+ const similarity = (item.similarity * 100).toFixed(1);
706
+ stream.markdown(`### ${item.key} (${similarity}% match)\n`);
707
+ if (item.metadata) {
708
+ stream.markdown(`\`\`\`json\n${JSON.stringify(item.metadata, null, 2)}\n\`\`\`\n\n`);
709
+ }
710
+ }
711
+
712
+ return { metadata: { command: 'vector' } };
713
+ }
714
+
715
+ async function handleDeployments(stream: vscode.ChatResponseStream): Promise<vscode.ChatResult> {
716
+ if (!hasProject()) {
717
+ stream.markdown('## No Project Found\n\n');
718
+ stream.markdown('Open an Agentuity project to view deployments.\n\n');
719
+ return { metadata: { command: 'deployments' } };
720
+ }
721
+
722
+ stream.progress('Fetching deployments...');
723
+
724
+ const cli = getCliClient();
725
+ const result = await cli.listDeployments();
726
+
727
+ if (!result.success) {
728
+ stream.markdown(`Failed to fetch deployments: ${result.error}`);
729
+ return { metadata: { command: 'deployments' } };
730
+ }
731
+
732
+ const deployments = result.data || [];
733
+
734
+ if (deployments.length === 0) {
735
+ stream.markdown('## Deployments\n\n');
736
+ stream.markdown('No deployments found. Deploy your project to see deployments here.\n\n');
737
+ stream.button({ title: 'Deploy Now', command: 'agentuity.deploy' });
738
+ return { metadata: { command: 'deployments' } };
739
+ }
740
+
741
+ stream.markdown(`## Deployments (${deployments.length})\n\n`);
742
+ stream.markdown('| Status | ID | Created | Tags |\n');
743
+ stream.markdown('|--------|-----|---------|------|\n');
744
+
745
+ for (const deployment of deployments.slice(0, 10)) {
746
+ const status = deployment.active ? '✓ Active' : deployment.state || 'Inactive';
747
+ const shortId = deployment.id.substring(0, 8);
748
+ const created = new Date(deployment.createdAt).toLocaleDateString();
749
+ const tags = deployment.tags?.join(', ') || '-';
750
+ stream.markdown(`| ${status} | ${shortId} | ${created} | ${tags} |\n`);
751
+ }
752
+
753
+ if (deployments.length > 10) {
754
+ stream.markdown(`\n*...and ${deployments.length - 10} more*\n`);
755
+ }
756
+
757
+ stream.markdown('\n');
758
+ stream.button({ title: 'View in Deployments Explorer', command: 'agentuity.deployments.refresh' });
759
+
760
+ return { metadata: { command: 'deployments' } };
761
+ }
762
+
763
+ async function handleLogs(
764
+ args: string,
765
+ stream: vscode.ChatResponseStream
766
+ ): Promise<vscode.ChatResult> {
767
+ if (!hasProject()) {
768
+ stream.markdown('## No Project Found\n\n');
769
+ stream.markdown('Open an Agentuity project to view logs.\n\n');
770
+ return { metadata: { command: 'logs' } };
771
+ }
772
+
773
+ const sessionId = args.trim();
774
+
775
+ if (!sessionId) {
776
+ stream.markdown('## Session Logs\n\n');
777
+ stream.markdown('Usage: `/logs <session-id>`\n\n');
778
+ stream.markdown('Get a session ID from `/sessions` first.\n\n');
779
+ stream.button({ title: 'View Sessions', command: 'workbench.action.chat.open', arguments: [{ query: '@agentuity /sessions' }] });
780
+ return { metadata: { command: 'logs' } };
781
+ }
782
+
783
+ stream.progress(`Fetching logs for session ${sessionId.substring(0, 8)}...`);
784
+
785
+ const cli = getCliClient();
786
+ const result = await cli.getSessionLogs(sessionId);
787
+
788
+ if (!result.success) {
789
+ stream.markdown(`Failed to fetch logs: ${result.error}`);
790
+ return { metadata: { command: 'logs' } };
791
+ }
792
+
793
+ const logs = result.data || [];
794
+
795
+ if (logs.length === 0) {
796
+ stream.markdown(`## Session Logs: ${sessionId.substring(0, 8)}...\n\n`);
797
+ stream.markdown('No logs found for this session.\n');
798
+ return { metadata: { command: 'logs' } };
799
+ }
800
+
801
+ stream.markdown(`## Session Logs (${logs.length} entries)\n\n`);
802
+ stream.markdown('```\n');
803
+ for (const log of logs.slice(0, 50)) {
804
+ const time = new Date(log.timestamp).toLocaleTimeString();
805
+ const severity = log.severity.padEnd(5);
806
+ stream.markdown(`[${time}] ${severity} ${log.body}\n`);
807
+ }
808
+ stream.markdown('```\n');
809
+
810
+ if (logs.length > 50) {
811
+ stream.markdown(`\n*...and ${logs.length - 50} more entries*\n`);
812
+ }
813
+
814
+ return { metadata: { command: 'logs' } };
815
+ }
816
+
817
+ async function handleFallback(
818
+ _prompt: string,
819
+ stream: vscode.ChatResponseStream
820
+ ): Promise<vscode.ChatResult> {
821
+ stream.markdown("I can help you with your Agentuity project. Here's what I can do:\n\n");
822
+
823
+ for (const cmd of SLASH_COMMANDS) {
824
+ stream.markdown(`- \`/${cmd.name}\` - ${cmd.description}\n`);
825
+ }
826
+
827
+ stream.markdown('\nOr ask me questions about:\n');
828
+ stream.markdown('- **Agents** - "List my agents", "What agents do I have?"\n');
829
+ stream.markdown('- **Development** - "Start the dev server", "How do I test locally?"\n');
830
+ stream.markdown('- **Deployment** - "Deploy my agents", "How do I deploy?"\n');
831
+ stream.markdown('- **Sessions** - "Show recent sessions", "View session logs"\n');
832
+ stream.markdown('- **CLI** - "What CLI commands are available?"\n\n');
833
+
834
+ stream.markdown('Type `/help` for complete CLI documentation.\n\n');
835
+ stream.button({ title: 'Show Help', command: 'workbench.action.chat.open', arguments: [{ query: '@agentuity /help' }] });
836
+
837
+ return { metadata: { command: 'fallback' } };
838
+ }