Atlas / Skills / wavetermdev / Wps Events

Wps EventsSAFE

skills/wavetermdev/wps-events

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
Apache-2.0
Stars
22,418
01

Overview

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Read from source at commit 63907843412fOBSERVED · 2026-10-05
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: wps-events
description: Guide for working with Wave Terminal's WPS (Wave PubSub) event system. Use when implementing new event types, publishing events, subscribing to events, or adding asynchronous communication between components.
---

# WPS Events Guide

## Overview

WPS (Wave PubSub) is Wave Terminal's publish-subscribe event system that enables different parts of the application to communicate asynchronously. The system uses a broker pattern to route events from publishers to subscribers based on event types and scopes.

## Key Files

- `pkg/wps/wpstypes.go` - Event type constants and data structures
- `pkg/wps/wps.go` - Broker implementation and core logic
- `pkg/wcore/wcore.go` - Example usage patterns

## Event Structure

Events in WPS have the following structure:

```go
type WaveEvent struct {
    Event   string   `json:"event"`      // Event type constant
    Scopes  []string `json:"scopes,omitempty"` // Optional scopes for targeted delivery
    Sender  string   `json:"sender,omitempty"` // Optional sender identifier
    Persist int      `json:"persist,omitempty"` // Number of events to persist in history
    Data    any      `json:"data,omitempty"`    // Event payload
}
```

## Adding a New Event Type

### Step 1: Define the Event Constant

Add your event type constant to `pkg/wps/wpstypes.go`:

```go
const (
    Event_BlockClose       = "blockclose"
    Event_ConnChange       = "connchange"
    // ... other events ...
    Event_YourNewEvent     = "your:newevent"  // type: YourEventData (or "none" if no data)
)
```

**Naming Convention:**

- Use descriptive PascalCase for the constant name with `Event_` prefix
- Use lowercase with colons for the string value (e.g., "namespace:eventname")
- Group related events with the same namespace prefix
- Always add a `// type: <TypeName>` comment; use `// type: none` if no data is sent

### Step 2: Add to AllEvents

Add your new constant to the `AllEvents` slice in `pkg/wps/wpstypes.go`:

```go
var AllEvents []string = []string{
    // ... existing events ...
    Event_YourNewEvent,
}
```

### Step 3: Register in WaveEventDataTypes (REQUIRED)

You **must** add an entry to `WaveEventDataTypes` in `pkg/tsgen/tsgenevent.go`. This drives TypeScript type generation for the event's `data` field:

```go
var WaveEventDataTypes = map[string]reflect.Type{
    // ... existing entries ...
    wps.Event_YourNewEvent: reflect.TypeOf(YourEventData{}),        // value type
    // wps.Event_YourNewEvent: reflect.TypeOf((*YourEventData)(nil)), // pointer type
    // wps.Event_YourNewEvent: nil,                                   // no data (type: none)
}
```

- Use `reflect.TypeOf(YourType{})` for value types
- Use `reflect.TypeOf((*YourType)(nil))` for pointer types
- Use `nil` if no data is sent for the event

### Step 4: Define Event Data Structure (Optional)

If your event carries structured data, define a type for it:

```go
type YourEventData struct {
    Field1 string `json:"field1"`
    Field2 int    `json:"field2"`
}
```

### Step 5: Expose Type to Frontend (If Needed)

If your event data type isn't already exposed via an RPC call, you need to add it to `pkg/tsgen/tsgen.go` so TypeScript types are generated:

```go
// add extra types to generate here
var ExtraTypes = []any{
    waveobj.ORef{},
    // ... other types ...
    uctypes.RateLimitInfo{},  // Example: already added
    YourEventData{},          // Add your new type here
}
```

Then run code generation:

```bash
task generate
```

This will update `frontend/types/gotypes.d.ts` with TypeScript definitions for your type, ensuring type safety in the frontend when handling these events.

## Publishing Events

### Basic Publishing

To publish an event, use the global broker:

```go
import "github.com/wavetermdev/waveterm/pkg/wps"

wps.Broker.Publish(wps.WaveEvent{
    Event: wps.Event_YourNewEvent,
    Data:  yourData,
})
```

### Publishing with Scopes

Scopes allow targeted event delivery. Subscribers can filter events by scope:

```go
wps.Broker.Publish(wps.WaveEvent{
    Event:  wps.Event_WaveObjUpdate,
    Scopes: []string{oref.String()},  // Target specific object
    Data:   updateData,
})
```

### Publishing in a Goroutine

To avoid blocking the caller, publish events asynchronously:

```go
go func() {
    wps.Broker.Publish(wps.WaveEvent{
        Event: wps.Event_YourNewEvent,
        Data:  data,
    })
}()
```

**When to use goroutines:**

- When publishing from performance-critical code paths
- When the event is informational and doesn't need immediate delivery
- When publishing from code that holds locks (to prevent deadlocks)

### Event Persistence

Events can be persisted in memory for late subscribers:

```go
wps.Broker.Publish(wps.WaveEvent{
    Event:   wps.Event_YourNewEvent,
    Persist: 100,  // Keep last 100 events
    Data:    data,
})
```

## Complete Example: Rate Limit Updates

This example shows how rate limit information is published when AI chat responses include rate limit headers.

### 1. Define the Event Type

In `pkg/wps/wpstypes.go`:

```go
const (
    // ... other events ...
    Event_WaveAIRateLimit  = "waveai:ratelimit"
)
```

### 2. Publish the Event

In `pkg/aiusechat/usechat.go`:

```go
import "github.com/wavetermdev/waveterm/pkg/wps"

func updateRateLimit(info *uctypes.RateLimitInfo) {
    if info == nil {
        return
    }
    rateLimitLock.Lock()
    defer rateLimitLock.Unlock()
    globalRateLimitInfo = info

    // Publish event in goroutine to avoid blocking
    go func() {
        wps.Broker.Publish(wps.WaveEvent{
            Event: wps.Event_WaveAIRateLimit,
            Data:  info,  // RateLimitInfo struct
        })
    }()
}
```

### 3. Subscribe to the Event (Frontend)

In the frontend, subscribe to events via WebSocket:

```typescript
// Subscribe to rate limit updates
const subscription = {
  event: "waveai:ratelimit",
  allscopes: true, // Receive all rate limit events
};
```

## Subscribing to Events

### From Go Code

```go
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (0)

No findings outside the package's declared scope.

Gates applied: no_behavioural_pass.

Audited 2026-10-05 · audit v0.4.1 · source sha 63907843412ffull audit observations/trust-audit/skill/wavetermdev__wps-events.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-0563907843412fSAFEB89first audit
05

Questions

What does the Wps Events skill do?

An open-source, AI-integrated, cross-platform terminal for seamless workflows

Is Wps Events safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Wps Events access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (63907843412f), read on 2026-10-05. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement