@vfarcic/dot-ai 0.179.0 → 0.181.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.
Files changed (38) hide show
  1. package/dist/core/generic-session-manager.d.ts +5 -0
  2. package/dist/core/generic-session-manager.d.ts.map +1 -1
  3. package/dist/core/generic-session-manager.js +8 -1
  4. package/dist/core/mermaid-tools.d.ts +27 -0
  5. package/dist/core/mermaid-tools.d.ts.map +1 -0
  6. package/dist/core/mermaid-tools.js +115 -0
  7. package/dist/core/providers/vercel-provider.d.ts.map +1 -1
  8. package/dist/core/providers/vercel-provider.js +14 -13
  9. package/dist/core/visualization.d.ts +77 -0
  10. package/dist/core/visualization.d.ts.map +1 -0
  11. package/dist/core/visualization.js +80 -0
  12. package/dist/interfaces/rest-api.d.ts +19 -2
  13. package/dist/interfaces/rest-api.d.ts.map +1 -1
  14. package/dist/interfaces/rest-api.js +120 -47
  15. package/dist/tools/generate-manifests.d.ts.map +1 -1
  16. package/dist/tools/generate-manifests.js +93 -23
  17. package/dist/tools/operate-analysis.d.ts.map +1 -1
  18. package/dist/tools/operate-analysis.js +5 -0
  19. package/dist/tools/operate.d.ts +4 -1
  20. package/dist/tools/operate.d.ts.map +1 -1
  21. package/dist/tools/operate.js +9 -1
  22. package/dist/tools/organizational-data.d.ts +1 -1
  23. package/dist/tools/query.d.ts +2 -1
  24. package/dist/tools/query.d.ts.map +1 -1
  25. package/dist/tools/query.js +4 -15
  26. package/dist/tools/recommend.d.ts +22 -0
  27. package/dist/tools/recommend.d.ts.map +1 -1
  28. package/dist/tools/recommend.js +41 -16
  29. package/dist/tools/remediate.d.ts +3 -1
  30. package/dist/tools/remediate.d.ts.map +1 -1
  31. package/dist/tools/remediate.js +31 -12
  32. package/dist/tools/version.d.ts +16 -0
  33. package/dist/tools/version.d.ts.map +1 -1
  34. package/dist/tools/version.js +55 -29
  35. package/package.json +2 -1
  36. package/prompts/visualize.md +86 -0
  37. package/scripts/dot-ai.nu +43 -5
  38. package/prompts/visualize-query.md +0 -116
@@ -13,10 +13,12 @@ const resource_sync_handler_1 = require("./resource-sync-handler");
13
13
  const prompts_1 = require("../tools/prompts");
14
14
  const generic_session_manager_1 = require("../core/generic-session-manager");
15
15
  const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
16
+ const visualization_1 = require("../core/visualization");
16
17
  const ai_provider_factory_1 = require("../core/ai-provider-factory");
17
18
  const capability_tools_1 = require("../core/capability-tools");
18
19
  const resource_tools_1 = require("../core/resource-tools");
19
20
  const kubectl_tools_1 = require("../core/kubectl-tools");
21
+ const mermaid_tools_1 = require("../core/mermaid-tools");
20
22
  /**
21
23
  * HTTP status codes for REST responses
22
24
  */
@@ -146,7 +148,7 @@ class RestApiRouter {
146
148
  break;
147
149
  case 'visualize':
148
150
  if (req.method === 'GET' && pathMatch.sessionId) {
149
- await this.handleVisualize(req, res, requestId, pathMatch.sessionId);
151
+ await this.handleVisualize(req, res, requestId, pathMatch.sessionId, url.searchParams);
150
152
  }
151
153
  else if (req.method !== 'GET') {
152
154
  await this.sendErrorResponse(res, requestId, HttpStatus.METHOD_NOT_ALLOWED, 'METHOD_NOT_ALLOWED', 'Only GET method allowed for visualization');
@@ -469,30 +471,49 @@ class RestApiRouter {
469
471
  /**
470
472
  * Handle visualization requests (PRD #317)
471
473
  * Returns structured visualization data for a query session
474
+ * PRD #320: Supports ?reload=true to regenerate visualization from current session data
472
475
  */
473
- async handleVisualize(req, res, requestId, sessionId) {
476
+ async handleVisualize(req, res, requestId, sessionIdParam, searchParams) {
474
477
  try {
475
- this.logger.info('Processing visualization request', { requestId, sessionId });
476
- // Load session data using GenericSessionManager with 'qry' prefix (matches query tool)
477
- const sessionManager = new generic_session_manager_1.GenericSessionManager('qry');
478
- const session = sessionManager.getSession(sessionId);
479
- if (!session) {
480
- await this.sendErrorResponse(res, requestId, HttpStatus.NOT_FOUND, 'SESSION_NOT_FOUND', `Session '${sessionId}' not found or has expired`);
481
- return;
478
+ // PRD #320: Support multiple session IDs separated by +
479
+ const sessionIds = sessionIdParam.split('+').filter(id => id.length > 0);
480
+ const isMultiSession = sessionIds.length > 1;
481
+ // PRD #320: Support ?reload=true to regenerate visualization from current session data
482
+ const reload = searchParams.get('reload') === 'true';
483
+ this.logger.info('Processing visualization request', {
484
+ requestId,
485
+ sessionIds,
486
+ isMultiSession,
487
+ reload
488
+ });
489
+ // Fetch all sessions
490
+ const sessions = [];
491
+ for (const sessionId of sessionIds) {
492
+ const sessionPrefix = (0, visualization_1.extractPrefixFromSessionId)(sessionId);
493
+ const sessionManager = new generic_session_manager_1.GenericSessionManager(sessionPrefix);
494
+ const session = sessionManager.getSession(sessionId);
495
+ if (!session) {
496
+ await this.sendErrorResponse(res, requestId, HttpStatus.NOT_FOUND, 'SESSION_NOT_FOUND', `Session '${sessionId}' not found or has expired`);
497
+ return;
498
+ }
499
+ sessions.push({ sessionId, data: session.data });
482
500
  }
483
- // Check for cached visualization - return immediately if available
484
- if (session.data.cachedVisualization) {
501
+ // For single session, check cache (multi-session doesn't use cache yet)
502
+ // PRD #320: Skip cache if reload=true to regenerate from current session data
503
+ const primarySession = sessions[0];
504
+ if (!isMultiSession && !reload && primarySession.data.cachedVisualization) {
485
505
  this.logger.info('Returning cached visualization', {
486
506
  requestId,
487
- sessionId,
488
- generatedAt: session.data.cachedVisualization.generatedAt
507
+ sessionId: sessionIds[0],
508
+ generatedAt: primarySession.data.cachedVisualization.generatedAt
489
509
  });
490
510
  const cachedResponse = {
491
511
  success: true,
492
512
  data: {
493
- title: session.data.cachedVisualization.title,
494
- visualizations: session.data.cachedVisualization.visualizations,
495
- insights: session.data.cachedVisualization.insights
513
+ title: primarySession.data.cachedVisualization.title,
514
+ visualizations: primarySession.data.cachedVisualization.visualizations,
515
+ insights: primarySession.data.cachedVisualization.insights,
516
+ toolsUsed: primarySession.data.cachedVisualization.toolsUsed // PRD #320
496
517
  },
497
518
  meta: {
498
519
  timestamp: new Date().toISOString(),
@@ -509,12 +530,43 @@ class RestApiRouter {
509
530
  await this.sendErrorResponse(res, requestId, HttpStatus.SERVICE_UNAVAILABLE, 'AI_NOT_CONFIGURED', 'AI provider is not configured. Set ANTHROPIC_API_KEY or other AI provider credentials.');
510
531
  return;
511
532
  }
533
+ // PRD #320: Select prompt based on tool name (defaults to 'query' for backwards compatibility)
534
+ const toolName = primarySession.data.toolName || 'query';
535
+ const promptName = (0, visualization_1.getPromptForTool)(toolName);
536
+ this.logger.info('Loading visualization prompt', { requestId, sessionIds, toolName, promptName });
512
537
  // Load system prompt with session context
513
- const systemPrompt = (0, shared_prompt_loader_1.loadPrompt)('visualize-query', {
514
- intent: session.data.intent,
515
- toolCallsData: JSON.stringify(session.data.toolCallsExecuted, null, 2)
516
- });
517
- // Tool executor - same as query tool
538
+ // PRD #320: Unified visualization prompt with tool-aware data selection
539
+ let intent;
540
+ let data;
541
+ switch (toolName) {
542
+ case 'recommend':
543
+ intent = primarySession.data.intent || '';
544
+ data = isMultiSession ? sessions.map(s => s.data) : primarySession.data;
545
+ break;
546
+ case 'remediate':
547
+ intent = primarySession.data.issue || '';
548
+ data = primarySession.data.finalAnalysis || primarySession.data;
549
+ break;
550
+ case 'operate':
551
+ intent = primarySession.data.intent || '';
552
+ data = primarySession.data;
553
+ break;
554
+ case 'version':
555
+ // PRD #320: Version tool provides system health status
556
+ intent = `System health: ${primarySession.data.summary?.overall || 'unknown'}`;
557
+ data = primarySession.data;
558
+ break;
559
+ default:
560
+ // Query and other tools: use toolCallsExecuted or full data
561
+ intent = primarySession.data.intent || '';
562
+ data = primarySession.data.toolCallsExecuted || primarySession.data;
563
+ }
564
+ const promptData = {
565
+ intent,
566
+ data: JSON.stringify(data, null, 2)
567
+ };
568
+ const systemPrompt = (0, shared_prompt_loader_1.loadPrompt)(promptName, promptData);
569
+ // Tool executor - same as query tool, plus mermaid validation
518
570
  const executeVisualizationTools = async (toolName, input) => {
519
571
  if (toolName.startsWith('search_capabilities') || toolName.startsWith('query_capabilities')) {
520
572
  return (0, capability_tools_1.executeCapabilityTools)(toolName, input);
@@ -525,6 +577,10 @@ class RestApiRouter {
525
577
  if (toolName.startsWith('kubectl_')) {
526
578
  return (0, kubectl_tools_1.executeKubectlTools)(toolName, input);
527
579
  }
580
+ // PRD #320: Mermaid validation tools
581
+ if (toolName === 'validate_mermaid') {
582
+ return (0, mermaid_tools_1.executeMermaidTools)(toolName, input);
583
+ }
528
584
  return {
529
585
  success: false,
530
586
  error: `Unknown tool: ${toolName}`,
@@ -540,24 +596,27 @@ class RestApiRouter {
540
596
  kubectl_tools_1.KUBECTL_EVENTS_TOOL,
541
597
  kubectl_tools_1.KUBECTL_GET_CRD_SCHEMA_TOOL
542
598
  ];
543
- this.logger.info('Starting AI visualization generation with tools', { requestId, sessionId });
599
+ this.logger.info('Starting AI visualization generation with tools', { requestId, sessionIds, toolName });
544
600
  // Execute tool loop - AI can gather additional data if needed
545
601
  const result = await aiProvider.toolLoop({
546
602
  systemPrompt,
547
603
  userMessage: 'Generate visualizations based on the query results provided. Use tools if you need additional information about any resources.',
548
- tools: [...capability_tools_1.CAPABILITY_TOOLS, ...resource_tools_1.RESOURCE_TOOLS, ...KUBECTL_READONLY_TOOLS],
604
+ // PRD #320: Include MERMAID_TOOLS for diagram validation
605
+ tools: [...capability_tools_1.CAPABILITY_TOOLS, ...resource_tools_1.RESOURCE_TOOLS, ...KUBECTL_READONLY_TOOLS, ...mermaid_tools_1.MERMAID_TOOLS],
549
606
  toolExecutor: executeVisualizationTools,
550
- maxIterations: 5, // Limit iterations for visualization
551
- operation: 'visualize-query'
607
+ maxIterations: 10, // Allow enough iterations for tool calls + JSON generation
608
+ operation: `visualize-${toolName}` // PRD #320: Include tool name for debugging
552
609
  });
553
610
  this.logger.info('AI visualization generation completed', {
554
611
  requestId,
555
- sessionId,
612
+ sessionIds,
613
+ toolName,
556
614
  iterations: result.iterations,
557
615
  toolsUsed: [...new Set(result.toolCallsExecuted.map(tc => tc.tool))]
558
616
  });
559
617
  // Parse AI response as JSON
560
618
  let visualizationResponse;
619
+ let isFallbackResponse = false;
561
620
  try {
562
621
  // Extract JSON from response - it may have text before/after the JSON block
563
622
  let jsonContent = result.finalMessage.trim();
@@ -584,7 +643,7 @@ class RestApiRouter {
584
643
  if (!viz.id || !viz.label || !viz.type || viz.content === undefined) {
585
644
  throw new Error(`Invalid visualization: missing required fields in ${JSON.stringify(viz)}`);
586
645
  }
587
- if (!['mermaid', 'cards', 'code', 'table'].includes(viz.type)) {
646
+ if (!['mermaid', 'cards', 'code', 'table', 'diff'].includes(viz.type)) {
588
647
  throw new Error(`Invalid visualization type: ${viz.type}`);
589
648
  }
590
649
  }
@@ -600,47 +659,60 @@ class RestApiRouter {
600
659
  }
601
660
  return String(insight);
602
661
  });
662
+ // PRD #320: Include toolsUsed for test validation
663
+ const toolsUsed = [...new Set(result.toolCallsExecuted.map(tc => tc.tool))];
603
664
  visualizationResponse = {
604
665
  ...parsed,
605
- insights: normalizedInsights
666
+ insights: normalizedInsights,
667
+ toolsUsed
606
668
  };
607
669
  }
608
670
  catch (parseError) {
609
671
  this.logger.error('Failed to parse AI visualization response', parseError instanceof Error ? parseError : new Error(String(parseError)), {
610
672
  requestId,
611
- sessionId,
673
+ sessionIds,
612
674
  rawResponse: result.finalMessage.substring(0, 500)
613
675
  });
614
676
  // Fallback to basic visualization on parse error
677
+ // NOTE: isFallbackResponse flag prevents caching this response
678
+ isFallbackResponse = true;
615
679
  visualizationResponse = {
616
- title: `Query: ${session.data.intent}`,
680
+ title: `Query: ${primarySession.data.intent}`,
617
681
  visualizations: [
618
682
  {
619
683
  id: 'raw-data',
620
- label: 'Query Results',
684
+ label: 'Raw Data',
621
685
  type: 'code',
622
686
  content: {
623
687
  language: 'json',
624
- code: JSON.stringify(session.data.toolCallsExecuted, null, 2)
688
+ code: JSON.stringify(isMultiSession ? sessions.map(s => s.data) : primarySession.data, null, 2)
625
689
  }
626
690
  }
627
691
  ],
628
692
  insights: [
629
- 'AI visualization generation failed - showing raw query results',
630
- `Query executed in ${session.data.iterations} iteration(s)`
693
+ 'AI visualization generation failed - showing raw data'
631
694
  ]
632
695
  };
633
696
  }
634
- // Cache the visualization in the session for subsequent requests
635
- sessionManager.updateSession(sessionId, {
636
- cachedVisualization: {
637
- title: visualizationResponse.title,
638
- visualizations: visualizationResponse.visualizations,
639
- insights: visualizationResponse.insights,
640
- generatedAt: new Date().toISOString()
641
- }
642
- });
643
- this.logger.info('Visualization cached in session', { requestId, sessionId });
697
+ // Cache the visualization in the session for subsequent requests (single session only)
698
+ // Don't cache fallback responses - let subsequent requests retry AI generation
699
+ if (!isMultiSession && !isFallbackResponse) {
700
+ const sessionPrefix = (0, visualization_1.extractPrefixFromSessionId)(sessionIds[0]);
701
+ const cacheManager = new generic_session_manager_1.GenericSessionManager(sessionPrefix);
702
+ cacheManager.updateSession(sessionIds[0], {
703
+ cachedVisualization: {
704
+ title: visualizationResponse.title,
705
+ visualizations: visualizationResponse.visualizations,
706
+ insights: visualizationResponse.insights,
707
+ toolsUsed: visualizationResponse.toolsUsed, // PRD #320: Cache toolsUsed
708
+ generatedAt: new Date().toISOString()
709
+ }
710
+ });
711
+ this.logger.info('Visualization cached in session', { requestId, sessionId: sessionIds[0] });
712
+ }
713
+ else if (isFallbackResponse) {
714
+ this.logger.warn('Skipping cache for fallback visualization response', { requestId, sessionId: sessionIds[0] });
715
+ }
644
716
  const response = {
645
717
  success: true,
646
718
  data: visualizationResponse,
@@ -653,16 +725,17 @@ class RestApiRouter {
653
725
  await this.sendJsonResponse(res, HttpStatus.OK, response);
654
726
  this.logger.info('Visualization request completed', {
655
727
  requestId,
656
- sessionId,
728
+ sessionIds,
657
729
  visualizationCount: visualizationResponse.visualizations.length,
658
- cached: true
730
+ cached: !isMultiSession && !isFallbackResponse,
731
+ isFallback: isFallbackResponse
659
732
  });
660
733
  }
661
734
  catch (error) {
662
735
  const errorMessage = error instanceof Error ? error.message : String(error);
663
736
  this.logger.error('Visualization request failed', error instanceof Error ? error : new Error(String(error)), {
664
737
  requestId,
665
- sessionId
738
+ sessionIdParam
666
739
  });
667
740
  await this.sendErrorResponse(res, requestId, HttpStatus.INTERNAL_SERVER_ERROR, 'VISUALIZATION_ERROR', 'Failed to generate visualization', { error: errorMessage });
668
741
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,KAAK,EAA2B,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAyBhD,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAA+I,CAAC;AAG/L,eAAO,MAAM,mCAAmC;;;CAG/C,CAAC;AAstBF;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACrD,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAoRxD"}
1
+ {"version":3,"file":"generate-manifests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-manifests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,KAAK,EAA2B,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA0BhD,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAC/D,eAAO,MAAM,kCAAkC,+IAA+I,CAAC;AAG/L,eAAO,MAAM,mCAAmC;;;CAG/C,CAAC;AAuvBF;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACrD,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAsUxD"}
@@ -57,6 +57,7 @@ const crd_availability_1 = require("../core/crd-availability");
57
57
  const solution_cr_1 = require("../core/solution-cr");
58
58
  const helm_utils_1 = require("../core/helm-utils");
59
59
  const packaging_1 = require("../core/packaging");
60
+ const visualization_1 = require("../core/visualization");
60
61
  const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
61
62
  // Tool metadata for direct MCP registration
62
63
  exports.GENERATEMANIFESTS_TOOL_NAME = 'generateManifests';
@@ -337,7 +338,7 @@ async function validateHelmInstallation(chart, releaseName, namespace, valuesPat
337
338
  /**
338
339
  * Handle Helm solution generation
339
340
  */
340
- async function handleHelmGeneration(solution, solutionId, dotAI, logger, requestId, interaction_id) {
341
+ async function handleHelmGeneration(solution, solutionId, dotAI, logger, requestId, sessionManager, interaction_id) {
341
342
  const maxAttempts = 10;
342
343
  const chart = solution.chart;
343
344
  const userAnswers = (0, solution_utils_1.extractUserAnswers)(solution);
@@ -387,6 +388,27 @@ async function handleHelmGeneration(solution, solutionId, dotAI, logger, request
387
388
  const helmCommand = (0, helm_utils_1.buildHelmCommand)(chart, releaseName, namespace, 'values.yaml');
388
389
  // Check if we should show feedback message
389
390
  const feedbackMessage = (0, index_1.maybeGetFeedbackMessage)();
391
+ // PRD #320: Update session with generateManifests data for visualization
392
+ sessionManager.updateSession(solutionId, {
393
+ ...solution,
394
+ stage: 'generateManifests',
395
+ generatedManifests: {
396
+ type: 'helm',
397
+ valuesYaml: valuesYaml,
398
+ helmCommand: helmCommand,
399
+ chart: {
400
+ repository: chart.repository,
401
+ repositoryName: chart.repositoryName,
402
+ chartName: chart.chartName,
403
+ version: chart.version
404
+ },
405
+ releaseName: releaseName,
406
+ namespace: namespace,
407
+ validationAttempts: attempt
408
+ }
409
+ });
410
+ // PRD #320: Generate visualization URL
411
+ const visualizationUrl = (0, visualization_1.getVisualizationUrl)(solutionId);
390
412
  const response = {
391
413
  success: true,
392
414
  status: 'helm_command_generated',
@@ -404,14 +426,21 @@ async function handleHelmGeneration(solution, solutionId, dotAI, logger, request
404
426
  namespace: namespace,
405
427
  validationAttempts: attempt,
406
428
  timestamp: new Date().toISOString(),
407
- ...(feedbackMessage ? { message: feedbackMessage } : {})
408
- };
409
- return {
410
- content: [{
411
- type: 'text',
412
- text: JSON.stringify(response, null, 2)
413
- }]
429
+ ...(feedbackMessage ? { message: feedbackMessage } : {}),
430
+ ...(visualizationUrl && { visualizationUrl })
414
431
  };
432
+ // PRD #320: Return two content blocks - JSON for REST API, text instruction for MCP agents
433
+ const content = [{
434
+ type: 'text',
435
+ text: JSON.stringify(response, null, 2)
436
+ }];
437
+ if (visualizationUrl) {
438
+ content.push({
439
+ type: 'text',
440
+ text: `šŸ“Š **View visualization**: ${visualizationUrl}`
441
+ });
442
+ }
443
+ return { content };
415
444
  }
416
445
  // Validation failed, prepare error context for next attempt
417
446
  lastError = {
@@ -647,7 +676,7 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
647
676
  solutionId: args.solutionId,
648
677
  chart: solution.chart ? `${solution.chart.repositoryName}/${solution.chart.chartName}` : 'unknown'
649
678
  });
650
- return await handleHelmGeneration(solution, args.solutionId, dotAI, logger, requestId, args.interaction_id);
679
+ return await handleHelmGeneration(solution, args.solutionId, dotAI, logger, requestId, sessionManager, args.interaction_id);
651
680
  }
652
681
  // Capability-based solution: Generate Kubernetes manifests
653
682
  logger.info('Using capability-based manifest generation flow', {
@@ -731,6 +760,20 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
731
760
  // Handle packaging based on outputFormat
732
761
  if (outputFormat === 'helm' || outputFormat === 'kustomize') {
733
762
  const packagingResult = await packageAndValidate(manifests, solution, outputFormat, outputPath, args.solutionId, dotAI, logger, args.interaction_id);
763
+ // PRD #320: Update session with generateManifests data for visualization
764
+ sessionManager.updateSession(args.solutionId, {
765
+ ...solution,
766
+ stage: 'generateManifests',
767
+ generatedManifests: {
768
+ type: outputFormat,
769
+ outputPath,
770
+ files: packagingResult.files,
771
+ validationAttempts: attempt,
772
+ packagingAttempts: packagingResult.attempts
773
+ }
774
+ });
775
+ // PRD #320: Generate visualization URL
776
+ const visualizationUrl = (0, visualization_1.getVisualizationUrl)(args.solutionId);
734
777
  const response = {
735
778
  success: true,
736
779
  status: 'manifests_generated',
@@ -742,15 +785,35 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
742
785
  packagingAttempts: packagingResult.attempts,
743
786
  timestamp: new Date().toISOString(),
744
787
  agentInstructions: `Write the files to "${outputPath}". The output is a ${outputFormat === 'helm' ? 'Helm chart' : 'Kustomize overlay'}. If immediate deployment is desired, call the recommend tool with stage: "deployManifests".`,
745
- ...(feedbackMessage ? { message: feedbackMessage } : {})
746
- };
747
- return {
748
- content: [{
749
- type: 'text',
750
- text: JSON.stringify(response, null, 2)
751
- }]
788
+ ...(feedbackMessage ? { message: feedbackMessage } : {}),
789
+ ...(visualizationUrl && { visualizationUrl })
752
790
  };
791
+ // PRD #320: Return two content blocks - JSON for REST API, text instruction for MCP agents
792
+ const content = [{
793
+ type: 'text',
794
+ text: JSON.stringify(response, null, 2)
795
+ }];
796
+ if (visualizationUrl) {
797
+ content.push({
798
+ type: 'text',
799
+ text: `šŸ“Š **View visualization**: ${visualizationUrl}`
800
+ });
801
+ }
802
+ return { content };
753
803
  }
804
+ // PRD #320: Update session with generateManifests data for visualization (raw format)
805
+ sessionManager.updateSession(args.solutionId, {
806
+ ...solution,
807
+ stage: 'generateManifests',
808
+ generatedManifests: {
809
+ type: 'raw',
810
+ outputPath,
811
+ files: [{ relativePath: 'manifests.yaml', content: manifests }],
812
+ validationAttempts: attempt
813
+ }
814
+ });
815
+ // PRD #320: Generate visualization URL
816
+ const visualizationUrl = (0, visualization_1.getVisualizationUrl)(args.solutionId);
754
817
  // Raw format - return manifests as-is
755
818
  const response = {
756
819
  success: true,
@@ -764,14 +827,21 @@ async function handleGenerateManifestsTool(args, dotAI, logger, requestId) {
764
827
  validationAttempts: attempt,
765
828
  timestamp: new Date().toISOString(),
766
829
  agentInstructions: `Write the files to "${outputPath}". If immediate deployment is desired, call the recommend tool with stage: "deployManifests".`,
767
- ...(feedbackMessage ? { message: feedbackMessage } : {})
768
- };
769
- return {
770
- content: [{
771
- type: 'text',
772
- text: JSON.stringify(response, null, 2)
773
- }]
830
+ ...(feedbackMessage ? { message: feedbackMessage } : {}),
831
+ ...(visualizationUrl && { visualizationUrl })
774
832
  };
833
+ // PRD #320: Return two content blocks - JSON for REST API, text instruction for MCP agents
834
+ const content = [{
835
+ type: 'text',
836
+ text: JSON.stringify(response, null, 2)
837
+ }];
838
+ if (visualizationUrl) {
839
+ content.push({
840
+ type: 'text',
841
+ text: `šŸ“Š **View visualization**: ${visualizationUrl}`
842
+ });
843
+ }
844
+ return { content };
775
845
  }
776
846
  // Validation failed, prepare error context for next attempt
777
847
  // Only pass AI-generated manifests to avoid duplicates on retry
@@ -1 +1 @@
1
- {"version":3,"file":"operate-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/operate-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAGxE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAEL,kBAAkB,EAMnB,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,EACzD,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,GAAG,CAAC,CAgDd"}
1
+ {"version":3,"file":"operate-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/operate-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAGxE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAEL,kBAAkB,EAMnB,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,EACzD,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,GAAG,CAAC,CAoDd"}
@@ -4,6 +4,7 @@ exports.analyzeIntent = analyzeIntent;
4
4
  const kubectl_tools_1 = require("../core/kubectl-tools");
5
5
  const ai_provider_factory_1 = require("../core/ai-provider-factory");
6
6
  const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
7
+ const visualization_1 = require("../core/visualization");
7
8
  const operate_1 = require("./operate");
8
9
  /**
9
10
  * Analyzes user intent and generates operational proposal using AI tool loop
@@ -29,10 +30,13 @@ async function analyzeIntent(intent, logger, sessionManager, sessionId, interact
29
30
  // 5. Create and save session
30
31
  const session = await saveAnalysisSession(intent, context, proposedChanges, sessionManager, sessionId, interaction_id, logger);
31
32
  logger.info('Operate analysis complete', { sessionId: session.sessionId });
33
+ // PRD #320: Generate visualization URL for analysis response
34
+ const visualizationUrl = (0, visualization_1.getVisualizationUrl)(session.sessionId);
32
35
  // 6. Return formatted output for user
33
36
  return {
34
37
  status: 'awaiting_user_approval',
35
38
  sessionId: session.sessionId,
39
+ ...(visualizationUrl && { visualizationUrl }), // PRD #320: Include visualization URL if WEB_UI_BASE_URL is set
36
40
  analysis: {
37
41
  summary: proposedChanges.analysis,
38
42
  currentState: proposedChanges.currentState,
@@ -212,6 +216,7 @@ function parseAIResponse(response, logger) {
212
216
  */
213
217
  async function saveAnalysisSession(intent, context, proposedChanges, sessionManager, sessionId, interaction_id, logger) {
214
218
  const sessionData = {
219
+ toolName: 'operate', // PRD #320: Tool identifier for visualization prompt selection
215
220
  intent,
216
221
  interaction_id,
217
222
  context,
@@ -5,6 +5,7 @@ import { z } from 'zod';
5
5
  import { Logger } from '../core/error-handling';
6
6
  import { OrganizationalPattern, PolicyIntent } from '../core/organizational-types';
7
7
  import { ResourceCapability } from '../core/capabilities';
8
+ import { BaseVisualizationData } from '../core/visualization';
8
9
  export declare const OPERATE_TOOL_NAME = "operate";
9
10
  export declare const OPERATE_TOOL_DESCRIPTION = "AI-powered Kubernetes application operations tool for Day 2 operations. Handles updates, scaling, enhancements, rollbacks, and deletions through natural language intents. Analyzes current state, applies organizational patterns and policies, validates changes via dry-run, and executes approved operations safely.";
10
11
  export declare const OPERATE_TOOL_INPUT_SCHEMA: {
@@ -21,7 +22,8 @@ export interface OperateInput {
21
22
  refinedIntent?: string;
22
23
  interaction_id?: string;
23
24
  }
24
- export interface OperateSessionData {
25
+ export interface OperateSessionData extends BaseVisualizationData {
26
+ toolName: 'operate';
25
27
  intent: string;
26
28
  interaction_id?: string;
27
29
  context: EmbeddedContext;
@@ -76,6 +78,7 @@ export interface ExecutionResult {
76
78
  export interface OperateOutput {
77
79
  status: 'success' | 'failed' | 'awaiting_user_approval';
78
80
  sessionId: string;
81
+ visualizationUrl?: string;
79
82
  analysis?: {
80
83
  summary: string;
81
84
  currentState: any;
@@ -1 +1 @@
1
- {"version":3,"file":"operate.d.ts","sourceRoot":"","sources":["../../src/tools/operate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operate.d.ts","sourceRoot":"","sources":["../../src/tools/operate.ts"],"names":[],"mappings":"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"}
@@ -228,10 +228,18 @@ async function operate(args) {
228
228
  */
229
229
  async function handleOperateTool(args) {
230
230
  const result = await operate(args);
231
+ // PRD #320: Embed visualization URL in message so agents display it to users
232
+ const messageWithVisualization = result.visualizationUrl
233
+ ? `${result.message}\n\nšŸ“Š View visualization: ${result.visualizationUrl}`
234
+ : result.message;
235
+ // PRD #320: Return JSON with visualization URL in message (for agents) and visualizationUrl field (for REST API)
231
236
  return {
232
237
  content: [{
233
238
  type: 'text',
234
- text: JSON.stringify(result, null, 2)
239
+ text: JSON.stringify({
240
+ ...result,
241
+ message: messageWithVisualization
242
+ }, null, 2)
235
243
  }]
236
244
  };
237
245
  }
@@ -21,9 +21,9 @@ export declare const ORGANIZATIONAL_DATA_TOOL_INPUT_SCHEMA: {
21
21
  operation: z.ZodEnum<{
22
22
  search: "search";
23
23
  get: "get";
24
+ delete: "delete";
24
25
  create: "create";
25
26
  list: "list";
26
- delete: "delete";
27
27
  deleteAll: "deleteAll";
28
28
  progress: "progress";
29
29
  scan: "scan";
@@ -18,6 +18,7 @@ export interface QueryInput {
18
18
  interaction_id?: string;
19
19
  }
20
20
  export interface QuerySessionData {
21
+ toolName: 'query';
21
22
  intent: string;
22
23
  summary: string;
23
24
  toolsUsed: string[];
@@ -32,7 +33,7 @@ export interface QuerySessionData {
32
33
  visualizations: Array<{
33
34
  id: string;
34
35
  label: string;
35
- type: 'mermaid' | 'cards' | 'code' | 'table';
36
+ type: 'mermaid' | 'cards' | 'code' | 'table' | 'diff';
36
37
  content: any;
37
38
  }>;
38
39
  insights: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,sBAAsB,iWAAuV,CAAC;AAG3X,eAAO,MAAM,uBAAuB;;;CAGnC,CAAC;AAGF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,KAAK,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,GAAG,CAAC;QACX,MAAM,EAAE,GAAG,CAAC;KACb,CAAC,CAAC;IAEH,mBAAmB,CAAC,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,KAAK,CAAC;YACpB,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;YAC7C,OAAO,EAAE,GAAG,CAAC;SACd,CAAC,CAAC;QACH,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAGD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AA8ED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CA2I7D"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoBxB,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,sBAAsB,iWAAuV,CAAC;AAG3X,eAAO,MAAM,uBAAuB;;;CAGnC,CAAC;AAGF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,KAAK,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,GAAG,CAAC;QACX,MAAM,EAAE,GAAG,CAAC;KACb,CAAC,CAAC;IAEH,mBAAmB,CAAC,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,KAAK,CAAC;YACpB,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;YACtD,OAAO,EAAE,GAAG,CAAC;SACd,CAAC,CAAC;QACH,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAGD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAgED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CA4I7D"}