Wps EventsSAFE
An open-source, AI-integrated, cross-platform terminal for seamless workflows
Overview
An open-source, AI-integrated, cross-platform terminal for seamless workflows
63907843412fOBSERVED · 2026-10-05What 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
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.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (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.
63907843412ffull audit observations/trust-audit/skill/wavetermdev__wps-events.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-05 | 63907843412f | SAFE | B | 89 | first audit |
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.