Skip to content

mianjunaid1223/venesa-capabilities

Repository files navigation

Venesa Community Capability Repository

Official registry of community capabilities for the Venesa intelligence platform.

What are Venesa Capabilities?

Capabilities are self-contained JavaScript modules that extend the Venesa intelligence platform. Each capability gives Venesa a new skill — from fetching weather data and searching the web, to reading files, sending emails, or controlling system processes.

Venesa's orchestrator dynamically discovers and loads capabilities at runtime. Once installed, a capability becomes part of Venesa's tool chain and can be invoked by the AI to complete tasks on your behalf.

Repository Structure

This repository follows a simple, organized structure:

  • Every capability is a single .js file inside the /capabilities/ folder
  • No sub-packages or deeply nested structures
  • A registry.json is auto-generated by scripts/generate-registry.js and used by Venesa to discover capabilities

Venesa discovers capabilities by fetching registry.json from this repository and loading each capability directly by its raw file URL.

Installation

Capabilities are installed directly inside Venesa. From the Venesa UI, navigate to Capabilities → Browse Community and install any capability by file name — no manual downloads required.

Venesa fetches the raw capability file and loads it into its execution engine automatically.

Capability Rules

  • One capability per file
  • File extension must be .js
  • CommonJS only — require / module.exports. No import/export
  • Export exactly one object
  • handler must be async. No raw Promise chains
  • Every handler body wrapped in try/catch. Never throw unhandled
  • On error return { success: false, error: string }. Never throw
  • No console.log or logging calls inside capability files
  • No side effects during import
  • No ranges in dependencies — exact versions only
  • No shared state between capabilities

Example Capability

"use strict";

const { z } = require("zod");

module.exports = {
  name: "example",
  description: "Returns the provided query string as-is. Use as a minimal capability template.",
  returnType: "data",
  marker: "silently",
  tags: ["example"],

  schema: z.object({
    query: z.string().trim().min(1).describe("Input query string."),
  }),

  async handler({ query }) {
    try {
      return { success: true, result: query };
    } catch (err) {
      return { success: false, error: err.message };
    }
  },
};

For the full specification including schema validation, return types, lifecycle hooks, and UI rendering options, see the Capability Development Specification section below.


Capability Development Specification

The Unified Protocol Standard

Venesa's internal reasoning logic treats both core features and community extensions uniformly via a strictly typed capability standard. Every capability must export a compliant object (module.exports).

The architecture guarantees isolation; failed executions will be trapped and resolved cleanly by the orchestrator.

Field Reference

Field Required Type Description
name string Unique camelCase identifier. Matches filename in camelCase (e.g. get-weather.jsgetWeather).
description string Injected verbatim into the LLM system prompt. See Description Rules below.
returnType string data | action | ui | memory | hybrid
schema ZodObject z.object({...}). Every field must have .describe("..."). No bare z.any().
handler async fn async (validatedParams) => { success, result }. Never throw. Always wrapped in try/catch.
marker string silently | announce | confirm. See Marker Defaults below.
tags string[] Lowercase. Shared vocabulary across similar capabilities (e.g. system, web, apps, network).
dependencies string[] Exact npm specifiers only. No ranges (^, ~, >=, *). No git/http/file URLs.
lifecycle object onLoad, onUnload, onEnable, onDisable hooks.
ui string table | key-value | card-list | command-list. Omit the field entirely when no UI hint is needed — null is not a valid value and will be ignored by the platform.

Description Rules

The description is injected verbatim into the LLM system prompt. The model reads it to decide when to invoke this capability and what to pass. Write it to answer three things in one to two sentences:

  1. What it does — the concrete action or data it produces.
  2. When to use it — the user intent that should trigger it.
  3. What it needs — the required inputs, briefly.

Good:

"Fetches a 5-day weather forecast for a given city. Use when the user asks about weather, temperature, or conditions in any location. Requires a city name."

Bad:

"Gets weather." — too vague; AI cannot reliably decide when or how to call it.

"This capability allows Venesa to retrieve current and forecasted meteorological data from a remote API endpoint and..." — too long; wastes token budget.

Rules:

  • Present tense. No "this capability", "this skill", "this module".
  • No mention of internal implementation details unless they directly affect usage.
  • No filler. Every word must earn its place.

Marker Defaults

The marker field controls user-facing feedback before and after handler execution.

returnType / Behavior Default marker
data — read/query, returns data to reason about silently
action — non-destructive, no visible side effect silently
action — visible side effect (launch app, open URL, send message) announce
action — destructive (delete, wipe, shutdown, close all) confirm
ui — renders structured output silently

When no marker is set the platform infers one from returnType. Explicitly set marker whenever the inferred default would mislead the user.

Schema Declaration

"use strict";

const { z } = require("zod");

// Declare exact-version dependencies. Platform installs them into an isolated
// node_modules directory before first run. No ranges — exact versions only.
// dependencies: ['<dep_name>@1.7.9']

module.exports = {
  name: "my-capability",
  description: "Provides precise system queries to the execution engine.",
  returnType: "data", // 'data' | 'action' | 'ui' | 'memory' | 'hybrid'
  marker: "silently", // 'silently' | 'announce' | 'confirm'
  tags: ["monitoring", "query"],
  // dependencies: ['<dep_name>@1.7.9'],

  schema: z.object({
    query: z.string().optional(),
  }),

  // Optional static config
  config: z.object({
    /* params */
  }),

  // Optional lifecycle hooks
  lifecycle: {
    onLoad() {},
    onUnload() {},
    onEnable() {},
    onDisable() {},
  },

  async handler(params) {
    try {
      /* logic */
      return { success: true, result: null };
    } catch (err) {
      return { success: false, error: err.message };
    }
  },
};

Component Requirements

Handler Logic

The handler(params) encapsulates the functional operation.

  • Payload: The params object contains variables already sanitized against the defined schema.
  • Isolation: Operational context like the application thread is abstracted away from the parameter intake. The capability solely acts upon structured parameters.
  • Response Format: Returns a native object, JSON string, or standard string.
  • Error contract: Always return { success: false, error: string } on failure. Never throw.

Schema Validation

Extracted inputs are hard-validated against the schema variable before triggering the payload handler.

  • Pre-Validation: This avoids allocating computational resources for syntax-error LLM predictions. A runtime rejection instructs the model internally to attempt self-correction.
  • Type Casting: Zod parameters can implement .default() or .transform() to guarantee strict internal assumptions.

Configuration Binding

Capabilities can supply external variable structures via config, using the Zod syntax model. Values propagate internally at boot from application configurations or persistent stores. Ensure you attach .default() fallback states so modules perform cleanly immediately upon insertion.

Handling Outputs

returnType tells the orchestrator and the LLM how to treat the handler result.

Type When to use
data Read/query operations that return information the AI should reason about.
action System mutations: launching apps, writing files, sending messages, etc.
ui Structured output rendered as a list, table, or card for the user.
memory Context or note manipulation — reads/writes the AI's persistent memory.
hybrid Mixed behaviour where the result drives both data reasoning and a UI render.

DEP ENGINE — Isolated Dependencies

Each capability gets fully isolated npm dependencies installed to:

~/.venesa/capabilities/<capabilityName>/node_modules/

No capability shares another's dependencies. Declare packages via the dependencies array using exact version specifiers:

dependencies: ['<dep_name>@1.7.9', 'cheerio@1.0.0'],

Allowed specifiers:

Format Example
Package name only "<dep_name>" (pinned to latest at first install)
Exact version "<dep_name>@1.7.9"
Scoped exact "@scope/pkg@2.0.0"

Rejected specifiers — validation will reject these at install time:

Rejected Reason
"<dep_name>@^1.7.0" range (^)
"<dep_name>@~1.7" range (~)
"<dep_name>@>=1.0.0" range operator
"<dep_name>@*" wildcard
"git+https://…" git URL
"https://…" http URL
"file:…" local path

Prefer pinned versions ("pkg@x.y.z") to guarantee reproducible installs. Simply require('<dep_name>') in your handler — the platform resolves from the capability-local node_modules automatically.

Corrupted state: If a dependency fails to install 5 consecutive times, the capability is marked corrupted in the UI and will not load. Fix the dependency spec and publish a new version to clear the flag.

Token System

Venesa resolves {{token}} placeholders in all string parameters before the handler runs. Capabilities do not implement this — the platform orchestrator handles it automatically.

Available Tokens

Token Resolves to
{{user.home}} User home directory
{{user.desktop}} Desktop folder
{{user.downloads}} Downloads folder
{{user.documents}} Documents folder
{{user.name}} User's display name (from Settings, not the OS username)
{{clipboard.text}} Current clipboard text
{{system.date}} Current local date
{{system.time}} Current local time
{{runtime.temp}} System temp directory
{{system.hostname}} Machine hostname
{{env.KEY_NAME}} Value of a custom key saved in Settings → Custom Keys. If the key is not saved, execution pauses and the user is prompted to add it before retrying. Use for API keys and secrets. Not available for LLM-generated parameters.

Rules for capability authors

  1. Document token support in .describe() — If a param accepts a path or dynamic value, tell the LLM which tokens apply.
  2. Never resolve tokens manually — Do not call os.homedir(), os.userInfo(), or read process.env to replicate what tokens already provide. Accept the param as a string and use it directly.
  3. Never hardcode paths — Instead of path.join(os.homedir(), 'Desktop'), expose an optional param with a default of {{user.desktop}}.

API Keys via {{env.*}}

Declare each required key as a hidden schema field with z.string().default("{{env.KEY_NAME}}"). The platform resolves it before your handler runs. Do not add .describe() to key fields — they should be invisible to the LLM.

schema: z.object({
  // LLM-supplied param
  city: z.string().describe("City name to fetch weather for"),

  // Hidden key param — platform resolves from Settings → Custom Keys
  apiKey: z.string().default("{{env.OPENWEATHER_KEY}}"),
}),

Documenting tokens in .describe()

schema: z.object({
  savePath: z.string().optional().describe(
    "Output folder. Defaults to {{user.desktop}}. Supports tokens: {{user.desktop}}, {{user.documents}}, {{user.downloads}}"
  ),
}),

NET GUARD — Network Offline Handling

Any capability that makes HTTP/HTTPS calls must handle offline errors explicitly rather than letting the network call fail with an opaque error. Use error-code detection in the catch block:

const <dep_name> = require('<dep_name>');

async handler(params) {
    try {
        const res = await <dep_name>.get(`https://api.example.com?q=${encodeURIComponent(params.query)}`);
        return { success: true, result: res.data };
    } catch (err) {
        const isOffline =
            err.code === 'ENOTFOUND'   ||
            err.code === 'ECONNREFUSED'||
            err.code === 'ETIMEDOUT'   ||
            err.code === 'ERR_NETWORK' ||
            err.message?.toLowerCase().includes('network');

        if (isOffline) {
            return {
                success: false,
                error: 'No internet connection. Please check your connection and try again.',
            };
        }
        return { success: false, error: err.message };
    }
},

Do not import connectivity modules from platform internals. The error-code pattern above is portable and requires no platform-specific imports.

Electron APIs

Capabilities execute inside the Electron main process, so require('electron') is available and fully supported. Use it to access Electron APIs such as shell.openExternal(), clipboard, dialog, and others.

async handler(params) {
  try {
    const { shell } = require('electron');
    await shell.openExternal(`https://example.com?q=${encodeURIComponent(params.query)}`);
    return { success: true, result: 'Opened in browser.' };
  } catch (err) {
    return { success: false, error: err.message };
  }
},

Capabilities remain self-contained — do not import from the Venesa application source (e.g. src/lib/, src/brain/). Only use Node built-ins, declared dependencies, and Electron's own API surface.

Utilizing Lifecycles

Lifecycles tie specific actions directly to external triggers. Hooks enforce asynchronous wrappers natively. Error outputs invoke standard warnings to the console without breaking daemon continuity.

  • onLoad(): Executed immediately following cache allocation within the registry index.
  • onUnload(): Invoked during daemon termination or cache purging.
  • onEnable() / onDisable(): Triggers upon user-toggled UI events.

Directory Formatting

All capabilities live under the /capabilities/ structure.

  • A solitary file logic block: /capabilities/automation-feature.js
  • Packaged multi-module structures: /capabilities/automation-feature/skill.js (where skill.js serves as the target map).
  • Hidden logic elements (prefixed with . or _) are still loaded and executed by the system, but they are not indexed within the orchestrator loop. This means they will not appear in the AI's tool list and cannot be invoked by name through the orchestrator, though their side effects (e.g., lifecycle hooks) still run.

About

Community capabilities for the Venesa intelligence platform. One file = one capability.

Topics

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors