npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@directivsys/vue-sdk

v0.1.8

Published

Vue bindings for DirectivSys built on top of @directivsys/core-sdk.

Readme

@directivsys/vue-sdk

@directivsys/vue-sdk is the Vue 3 adapter for DirectivSys. It provides pre-built components, composables, and a theming system for building AI-powered chat and analytics interfaces. It builds on top of @directivsys/core-sdk and exposes Vue-native plugin installation, dependency injection, and composable APIs while reusing the shared transport and orchestration runtime from the core package.

Features

Chat InterfaceDirectivSysChatbox component with message history, voice input/output, and file uploads
🔍 SearchDirectivSysSearch component with intelligent dropdown results
📊 AnalyticsAnalyticsWidget and AnalyticsDashboard for monitoring directives and metrics
📈 ReportsReportsDashboard with tabbed views for executive, supply chain, portfolio, and data quality insights
💾 Chat Persistence — Automatic message history persistence with "load more" functionality
🎨 Themes — Built-in light/dark themes with customization support
🧩 Composables — Analytics hooks for configs, results, date ranges, and data fetching
Framework-agnostic utilities — Request caching, analytics API client, and date range utilities

Relationship to the core package

| Concern | Package | | --- | --- | | Transport clients, conversation controller, shared contracts, and browser voice adapters | @directivsys/core-sdk | | Vue components, composables, themes, and context injection | @directivsys/vue-sdk |

The Vue package keeps the framework-specific concerns centered on provide and inject, reactive refs, and composable ergonomics, while the orchestration lifecycle remains in the shared core runtime.

Installation

npm install @directivsys/vue-sdk @directivsys/core-sdk vue

or just

npm install @directivsys/vue-sdk

Plugin setup

import { createApp } from "vue";
import { createDirectivSysPlugin } from "@directivsys/vue-sdk";
import App from "./App.vue";

const app = createApp(App);

app.use(
  createDirectivSysPlugin({
    apiKey: "your-api-key",
    config: {
      timeout: 30000,
    },
    theme: {
      mode: "light", // "light" | "dark"
    },
  }),
);

app.mount("#app");

Components

DirectivSysChatbox

Full-featured chat interface with message history, voice I/O, and file uploads.

<script setup lang="ts">
import { ref } from "vue";
import { DirectivSysChatbox } from "@directivsys/vue-sdk";

const currentContext = ref({
  userId: "user-123",
  interfaceState: {
    currentPageName: "Dashboard",
  },
});
</script>

<template>
  <DirectivSysChatbox
    :current-context="currentContext"
    :on-intent-detected="handleIntent"
    placeholder="Ask me anything..."
    height="600px"
  />
</template>

Props:

  • onIntentDetected (required) — Callback when the agent detects an intent
  • currentContext (required) — Current user context (can be reactive ref)
  • placeholder — Input placeholder text
  • height — Component height (default: "500px")
  • theme — Partial theme override
  • onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse — Event callbacks

Features:

  • Auto-scrolling to newest messages
  • "Load earlier messages" button with scroll position restoration
  • Typing indicator animation
  • Voice input/output with start/stop controls
  • Auto-expanding textarea with Shift+Enter for newlines
  • File upload support for images and documents
  • Message expansion for long text

DirectivSysSearch

Intelligent search interface with dropdown results.

<script setup lang="ts">
import { ref } from "vue";
import { DirectivSysSearch } from "@directivsys/vue-sdk";

const currentContext = ref({
  userId: "user-123",
  interfaceState: { currentPageName: "Search" },
});
</script>

<template>
  <DirectivSysSearch
    :current-context="currentContext"
    :on-intent-detected="handleIntent"
    width="100%"
    max-results="5"
  />
</template>

Props:

  • onIntentDetected (required) — Intent detection callback
  • currentContext (required) — User context
  • placeholder — Search placeholder
  • width — Component width
  • maxResults — Max results to display (default: 5)
  • theme — Theme override
  • Event callbacks same as Chatbox

AnalyticsWidget

Floating button that displays enabled analytics count.

<template>
  <AnalyticsWidget
    position="bottom-right"
    @directive-action="handleDirectiveAction"
  />
</template>

Props:

  • position — Widget position ("bottom-right" | "bottom-left")
  • theme — Theme override
  • onDirectiveAction — Handle directive execute/decline

AnalyticsDashboard

Sidebar + content layout for viewing analytics configs and directives.

<template>
  <AnalyticsDashboard
    auto-refresh-interval="60000"
    @directive-action="handleDirectiveAction"
  />
</template>

ReportsDashboard

Tabbed dashboard with 5 report types:

  • Executive Dashboard (metrics, trends)
  • Supply Chain Risk (risk matrix, health gauges)
  • Execution Audit Trail (audit log, statuses)
  • Portfolio Health (health scores)
  • Data Quality Automation (quality metrics)
<template>
  <ReportsDashboard />
</template>

Utility Components

  • MetricCard.vue — KPI display with trend
  • StatusBadge.vue — Status indicator pill
  • ProgressBar.vue — Progress visualization
  • ReportLayout.vue — Shared report wrapper

Composables

useDirectivSys

Main composable for chat functionality.

const {
  messages,           // ComputedRef<ChatMessage[]>
  isLoading,          // ComputedRef<boolean>
  error,              // ComputedRef<Error | null>
  isListening,        // ComputedRef<boolean>
  hasMoreMessages,    // ComputedRef<boolean> — true if older messages available
  isLoadingHistory,   // ComputedRef<boolean> — true while loading history
  sendChatQuery,      // (query: string) => Promise<void>
  clearMessages,      // () => void
  loadMoreMessages,   // () => Promise<void>
  startVoiceInput,    // () => void
  stopVoiceInput,     // () => void
  stopSpeechPlayback, // () => void
} = useDirectivSys({
  currentContext,
  onIntentDetected,
  storageAdapter,     // Optional: custom storage (defaults to localStorage)
  // ... other callbacks
});

Chat Persistence: The controller automatically persists the last 50 messages to localStorage (key: directivsys_chat_{userId}). On mount, it restores the session and displays the last 20 messages. Older messages are loaded on-demand via loadMoreMessages().

Scroll Position Anchoring: When loading older messages, capture scroll height before calling loadMoreMessages(), then restore the scroll offset after render:

const scrollAnchorRef = ref(0);

const handleLoadMore = async () => {
  const el = messagesContainerRef.value;
  if (el) {
    scrollAnchorRef.value = el.scrollHeight;  // Capture height
  }
  await loadMoreMessages();
  // After DOM updates, restore scroll position:
  if (el) {
    el.scrollTop = el.scrollHeight - scrollAnchorRef.value;
  }
};

useAnalyticsConfigs

Fetch all analytics configurations.

const { configs, isLoading, error, refetch } = useAnalyticsConfigs();

useAnalyticsResult

Fetch result for a specific analytics type.

const { result, isLoading, error, refetch } = useAnalyticsResult(analyticsType);

useDateRange

Manage date range selection.

const { selectedOption, setSelectedOption, startDate, endDate, label } = useDateRange("past-month");
// Options: "past-week", "past-month", "past-3-months", "past-6-months", "past-year"

useDirectiveAction

Handle directive execute/decline actions.

const { handleAction, isProcessing, error } = useDirectiveAction(onDirectiveAction);
await handleAction(directive, "execute" | "decline");

useReportData

Generic data fetching with request caching (TTL: 5 minutes).

const { data, loading, error, refetch } = useReportData(
  () => fetchSomeData(),
  [dependency1, dependency2],
  { enabled: true, ttl: 5 * 60 * 1000 }
);

Themes

Built-in Themes

import { lightTheme, darkTheme } from "@directivsys/vue-sdk";

Custom Theme

import { createCustomTheme, lightTheme } from "@directivsys/vue-sdk";

const customTheme = createCustomTheme(lightTheme, {
  colors: {
    primary: "#5e35b1",
    secondary: "#ff6f00",
    // ... override other colors
  },
});

Theme Structure

interface Theme {
  name: string;
  colors: {
    primary: string;
    secondary: string;
    background: string;
    surface: string;
    text: string;
    textSecondary: string;
    border: string;
    error: string;
    success: string;
  };
  spacing: {
    xs: string;  // 4px
    sm: string;  // 8px
    md: string;  // 16px
    lg: string;  // 24px
    xl: string;  // 32px
  };
  fontSizes: {
    xs: string;  // 12px
    sm: string;  // 14px
    md: string;  // 16px
    lg: string;  // 18px
    xl: string;  // 24px
  };
  borderRadius: string;  // 8px
  boxShadow: string;
}

Composable Usage Example

import { ref } from "vue";
import { useDirectivSys, useAnalyticsConfigs } from "@directivsys/vue-sdk";

const currentContext = ref({
  userId: "user-123",
  interfaceState: {
    currentPageName: "Inventory Dashboard",
  },
});

const sdk = useDirectivSys({
  currentContext,
  onIntentDetected: async (toolCall) => ({
    status: "success",
    summary: `Handled ${toolCall.toolName}`,
  }),
});

await sdk.sendChatQuery("Summarize the latest supply chain risk.");

// Analytics
const { configs, isLoading } = useAnalyticsConfigs();

Utilities

AnalyticsAPI

HTTP client for analytics endpoints.

import { AnalyticsAPI } from "@directivsys/vue-sdk";

const api = new AnalyticsAPI(config);
const configs = await api.getConfigs();
const result = await api.getLatestResult("analyticsType");
await api.updateDirectiveStatus(directiveId, "executed");

requestCache

Singleton cache for deduplicating requests (5-minute TTL).

import { requestCache } from "@directivsys/vue-sdk";

const result = await requestCache.get(fetchFn, cacheKey, ttl);
requestCache.invalidate(fetchFn, cacheKey);

DateRangeService

Date range utilities.

import { DateRangeService } from "@directivsys/vue-sdk";

const range = DateRangeService.getDateRange("past-month");
// { startDate, endDate, label }

Exported Types

All types from @directivsys/core-sdk are re-exported, plus:

export type Theme;
export type ThemeMode; // "light" | "dark" | "custom"
export type ThemeColors;
export type AnalyticsConfig;
export type AnalyticsResult;
export type AnalyticsDirective;
export type AnalyticsMetric;
export type AnalyticsObservation;
export type DirectiveActionCallback;
// ... and more

Best Practices

Message History Loading

Implement scroll anchoring to keep the user at the same message when loading history:

<script setup>
const messagesContainerRef = ref();
const scrollAnchorRef = ref(0);

const handleLoadMore = async () => {
  const el = messagesContainerRef.value;
  if (el) {
    scrollAnchorRef.value = el.scrollHeight;
  }
  await sdk.loadMoreMessages();
  // Restore scroll position in next tick
  nextTick(() => {
    if (el) {
      el.scrollTop = el.scrollHeight - scrollAnchorRef.value;
    }
  });
};
</script>

Custom Storage Adapter

Use a custom storage backend instead of localStorage:

const customStorage = {
  getItem: (key) => sessionStorage.getItem(key),
  setItem: (key, value) => sessionStorage.setItem(key, value),
  removeItem: (key) => sessionStorage.removeItem(key),
};

const sdk = useDirectivSys({
  currentContext,
  onIntentDetected,
  storageAdapter: customStorage,
});

Error Handling

const { error, isLoading } = useDirectivSys({
  currentContext,
  onIntentDetected,
  onError: (error) => {
    console.error("DirectivSys error:", error);
    // Show user-facing error message
  },
});

Relationship to React SDK

This Vue SDK is feature-parity with @directivsys/react-sdk. Most concepts map directly:

  • React hooks → Vue composables
  • React components → Vue SFCs
  • Context API → provide/inject
  • useState → ref/reactive
  • useEffect → watch

The theme system, analytics utilities, and type definitions are fully shared across both SDKs.

License

MIT