Cyphon

Frontend

Cyphon UI Components

Location: app/ui/modules/monitor-ui/src/vue/CyphonTest/

This document explains each UI component in the Cyphon feature.


Component Hierarchy

CyphonTest.vue (Main Container)
├── CyphonHero.vue (Welcome screen)
├── CommandBox.vue (Input area)
├── ResultView.vue (Results display)
│   ├── SearchBar.vue (Mini search in header)
│   ├── AISummaryCard.vue (AI-generated summary)
│   └── SearchResults.vue (Per-command results)
│       └── [Dynamic Cards] (Whois, DNS, etc.)
└── CommandsModal.vue (Command reference modal)

1. CyphonTest.vue (Main Container)

Purpose: The brain of Cyphon. Manages state and coordinates all other components.

State Machine


data() {
  return {
    state: "idle",      // idle | responding | complete
    messages: [],       // Conversation history
    showCommandsModal: false
  };
}
State What's Shown
idle CyphonHero + CommandBox
responding ResultView with loading spinner
complete ResultView with results + AI summary

Key Method: handleSubmit(question)

This is the most important method. Here's what happens:


async handleSubmit(question) {
  // 1. Update URL (for sharing/bookmarking)
  this.updateUrlQuery(question);

  // 2. Add user message to conversation
  this.messages = [{
    role: "user",
    type: "text",
    content: question
  }];

  // 3. Add loading placeholder
  this.messages.push({
    role: "ai",
    type: "loading",
    content: null
  });

  this.state = "responding";

  // 4. Call backend to get relevant commands
  const fullResponse = await discoveryAPI.executeCyphonQuery({
    question
  });

  // 5. Replace loading with actual results
  if (fullResponse?.relevantCommands?.length > 0) {
    this.messages[loadingIndex] = {
      role: "ai",
      type: "cards",
      content: fullResponse.relevantCommands
    };
  }

  this.state = "complete";
}

URL Query Support

Cyphon supports deep linking. If someone visits ?query=whois("google.com"), it auto-runs that search.


checkUrlQuery() {
  const urlParams = new URLSearchParams(window.location.search);
  const query = urlParams.get("query");
  if (query) {
    this.handleSubmit(query);
  }
}

2. CommandBox.vue

Purpose: The input area where users type their questions.

Features

  • Auto-resizing textarea
  • Enter to send (Shift+Enter for new line)
  • Commands dropdown button
  • Send button (enabled when text is present)

Key Props/Events

// Emits
$emit("submit", message); // When user sends message
$emit("open-commands"); // When user clicks Commands button

User Experience

┌──────────────────────────────────────────────┐
│ ✨ Ask Cyphon about security threats...      │
│                                              │
├──────────────────────────────────────────────┤
│                        [/Commands ▼] [Send]  │
└──────────────────────────────────────────────┘
        Press Enter to send, Shift+Enter for new line

3. ResultView.vue

Purpose: Displays the results after a search. This is where the magic happens.

Props


props: {
  messages: Array,     // Conversation history from parent
  isTyping: Boolean    // Shows loading state
}

Computed Properties


computed: {
	userQuery(); // Extracts the user's question
	cards(); // Extracts the relevant commands to display
	noResultsMessage; // Handles empty results
}

The Results Flow

messages (from parent)
    │
    ├── userQuery: "whois google.com"
    │
    └── cards: [
          { id: "whois", formattedOutput: "whois(\"google.com\")" }
        ]
           │
           ▼
    For each card, render <SearchResults :keyword="cmd.formattedOutput" />

AI Summary Generation

When search results come in, ResultView generates an AI summary:


async generateAISummary() {
  const allResults = this.collectedResults.flatMap(r => r.results);

  const response = await discoveryAPI.summarizeCyphonResults({
    userQuery: this.userQuery,
    results: allResults
  });

  this.aiSummary = response;  // { summary: "...", highlights: [...] }
}

4. SearchResults.vue

Purpose: Executes a single command and renders the results.

Location: app/ui/modules/monitor-ui/src/vue/cyphon/components/SearchResults.vue

How It Works

  1. Receives a keyword (e.g., whois("google.com"))
  2. Calls intelAPI.search({ keyword })
  3. Polls for results every 3 seconds (configurable)
  4. Renders dynamic card components based on cardType

The Polling Mechanism


async startResultLoader() {
  await this.loadResults();  // First call immediately

  // Then poll every 3 seconds
  this.resultLoader = setInterval(
    this.loadResults,
    this.resultRefreshInterval  // 3000ms default
  );
}

async loadResults() {
  // Rate limit: max 20 calls
  if (this.loadResultsCallCount >= this.rateLimit) {
    this.stopResultLoader();
    return;
  }

  const searchResponse = await intelAPI.search({
    keyword: this.keyword,
    id: this.searchResponse?.id  // Pass ID to get updates
  });

  if (searchResponse.done) {
    this.stopResultLoader();
  }
}

Dynamic Card Rendering

<component
	:is="card.cardType"
	v-for="card in searchResponse.results"
	:key="card.facts.factId"
	v-bind="card.facts.data"
/>

The cardType determines which Vue component renders:

  • Whois → Whois.vue
  • IntelOverview → IntelOverview.vue
  • Chart → UniChartCard.vue
  • etc.

5. CommandsModal.vue

Purpose: A modal showing all available Cyphon commands.

Features

  • Searchable command list
  • Grouped by category
  • Click to auto-fill command

Command Structure

{
  name: "whois",
  description: "Retrieves WHOIS information for the provided domain.",
  syntax: "whois(domain)",
  example: 'whois("example.com")',
  category: "Domain Intelligence",
  icon: "mdi:domain"
}

Categories

  • DNS (txt, passiveDns)
  • Domain Intelligence (whois)
  • Web Analysis (technologies, pageIntel)
  • OSINT (username, Email)
  • Reconnaissance (findSubdomain)
  • Security (blacklist, domainSpoof)
  • Network (host, port)
  • Geolocation (geolocateIp)

6. AISummaryCard.vue

Purpose: Displays the AI-generated summary at the top of results.

Props


props: {
  summary: Object,    // { summary: "...", highlights: [...] }
  loading: Boolean,
  error: String
}

States

State Display
Loading Shimmer animation + "Generating AI summary..."
Success Summary text + highlights list
Error Error message

7. CyphonHero.vue

Purpose: The welcome screen shown in idle state.

Visual Elements

  • Animated logo with orbital rings
  • Particle effects background
  • "Hello, I'm Cyphon" greeting
  • Subtitle about cybersecurity

Component Communication

CyphonTest.vue
    │
    │──── @submit ────► handleSubmit(question)
    │                         │
    │                         ▼
    │               discoveryAPI.executeCyphonQuery()
    │                         │
    │                         ▼
    │◄──── messages ──────────┘
    │
    ▼
ResultView.vue
    │
    │──── creates ────► SearchResults (one per command)
    │                         │
    │                         ▼
    │                   intelAPI.search()
    │                         │
    │◄─── @results ───────────┘
    │
    ▼
generateAISummary()