Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cli/spec/draft/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,18 @@ The default interactive mode uses Ink (React for CLI) to provide a modern termin
- Real-time participant status and typing indicators
- Auto-approval rules for trusted operations

#### Interactive Envelope Authoring (ADR-006)

The advanced UI includes a guided **Envelope Editor** that can be launched from anywhere in the session without breaking focus.

- **Hotkeys**: `Ctrl+E` opens the generic editor, while `Ctrl+P` (or `Ctrl+Shift+P` for tool-centric flows) jumps directly to proposal-oriented templates.
- **Type Selection**: Users pick the envelope kind first; the form adapts in real time using schema metadata declared in `src/config/envelopeForms.js`.
- **Field Editing**: Each envelope kind exposes a curated set of fields (recipients, payload summaries, JSON arguments, etc.) with inline validation and helpers for lists and JSON blobs.
- **Preview**: Before submission the editor renders the final MEW envelope (including protocol metadata) so operators can confirm exactly what will be sent.
- **Drafts**: Pressing `s`/`d` in the preview saves the envelope JSON to `.mew/drafts/<timestamp>-<kind>.json`, allowing later reuse via a forthcoming draft browser.

The editor is implemented as an Ink overlay component (`EnvelopeEditor`) that suspends the main input composer while active, ensuring a focused authoring workflow that still shares history and validation utilities with the rest of the UI.

**Architecture:**
- Message history uses Ink's `Static` component for native scrolling
- Persistent bottom panel stays fixed during scrolling
Expand Down
76 changes: 76 additions & 0 deletions cli/spec/draft/proposed/ADR-006-interactive-envelope-authoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ADR-006: Interactive Envelope Authoring in the MEW Protocol CLI

## Status
Proposed

## Date
2025-09-21

## Context

The MEW Protocol CLI currently supports manual construction and submission of envelopes using either direct YAML/JSON or command-line arguments. While powerful, this process can be error-prone and unintuitive, especially for:

- Non-technical users (e.g., human reviewers or analysts)
- High-frequency use cases (e.g., streaming movement updates or chat events)
- Envelope types with deeply nested or dynamic payloads (e.g., `stream/open`, `tool/request`)

To support faster iteration, richer interactivity, and on-demand control of agents and streams, we propose adding an interactive CLI mode for envelope creation and review.

## Decision

We will implement an **interactive envelope authoring interface** within the MEW CLI using a text-based UI framework (e.g., [Ink](https://github.com/vadimdemedes/ink)). This feature will allow users to:

- Trigger envelope creation via keyboard shortcuts (e.g., `Ctrl+E`, `Ctrl+P`)
- Walk through a type-specific form to populate envelope fields
- Preview the final envelope JSON
- Send the envelope or save it as a draft

### Core Capabilities

- **Hotkey activation**:
- `Ctrl+E`: Launch generic envelope editor
- `Ctrl+P`: Shortcut for `message/propose` or `tool/request`

- **Type-aware forms**:
- Envelope type is selected first
- Form updates dynamically based on schema (from config)
- Supports nested field editing (e.g. `schema`, `payload` objects)

- **Schema-driven configuration**:
- Schema definitions are built into the CLI and reflect the official MEW Protocol spec
- Each supported envelope type has a corresponding form definition derived from the protocol type system
- Enables type-safe editing and validation at runtime without external config files

- **Draft handling**:
- Drafts can be saved to `.mew/drafts/*.json`
- CLI can list/load/edit previously saved drafts

## Consequences

### Pros
- Enables envelope construction with reduced errors
- Supports new UX for human-in-the-loop workflows
- Makes the CLI viable for power users and novices alike
- Allows fast iteration of complex envelope types (e.g., live streaming, proposal flows)

### Cons
- Increases CLI implementation complexity
- Requires consistent schema updates to reflect protocol changes
- Terminal-only; not yet accessible via GUI or web

## Alternatives Considered

- Static template generators (e.g., `mew gen stream/open`) — lacks dynamic interactivity
- Full GUI app — potentially overkill and inconsistent with terminal-first goals
- Read-only CLI preview — useful, but doesn't help with authoring

## Open Questions
- Should we allow multiple envelopes to be composed/sent in sequence?
- How will this interact with proposal approval/denial tools or gateways?
- Should we allow live editing of matchers within the CLI?

## Next Steps
- Define schema format for `envelope-forms.json`
- Build `EnvelopeEditor` component using Ink or similar
- Wire up hotkey handling and matcher trigger preview
- Add integration tests for form flow + envelope validation
14 changes: 14 additions & 0 deletions cli/spec/draft/proposed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ All ADRs in this directory are currently **proposed** and under review. They doc
- ⚠️ Breaking change requiring client migration
- ⚠️ Temporary dual-format complexity during transition

---

### [ADR-006: Interactive Envelope Authoring in the MEW Protocol CLI](./ADR-006-interactive-envelope-authoring.md)
**Decision**: Add an Ink-powered interactive authoring flow for composing and reviewing MEW envelopes inside the CLI.

**Context**: Manual JSON entry is error-prone for complex envelopes (e.g., streaming or tool interactions) and slows down human-in-the-loop workflows.

**Impact**:
- ✅ Keyboard shortcuts launch guided forms for common envelope kinds
- ✅ Schema-driven prompts reduce mistakes and improve validation
- ✅ Drafts can be saved and resumed from `.mew/drafts/`
- ⚠️ Requires ongoing maintenance to track protocol schema updates
- ⚠️ Adds UI complexity that must work in both debug and advanced modes

## Architecture Overview

The ADRs collectively document a **layered architecture** that separates protocol implementation from operational concerns:
Expand Down
154 changes: 154 additions & 0 deletions cli/src/config/envelopeForms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Schema-driven envelope form definitions for the interactive editor.
*
* Each entry describes the base message structure and field prompts
* for a supported MEW envelope kind.
*/

const envelopeForms = {
'message/propose': {
label: 'message/propose',
description: 'Propose a message or decision for review by human participants.',
base: {
kind: 'message/propose',
to: [],
payload: {
summary: '',
body: '',
tags: []
}
},
fields: [
{
path: 'to',
label: 'Recipients',
type: 'list',
description: 'Comma-separated participant IDs that should receive the proposal (optional).',
defaultValue: []
},
{
path: 'payload.summary',
label: 'Summary',
type: 'string',
description: 'Short headline that will be displayed in inboxes and notifications.',
required: true,
defaultValue: ''
},
{
path: 'payload.body',
label: 'Body',
type: 'string',
description: 'Full proposal body. Markdown is supported by most clients.',
multiline: true,
defaultValue: ''
},
{
path: 'payload.tags',
label: 'Tags',
type: 'list',
description: 'Optional tags to help downstream automation filter proposals.',
defaultValue: []
}
]
},
'tool/request': {
label: 'tool/request',
description: 'Request that a tool be executed on behalf of the participant.',
base: {
kind: 'tool/request',
to: [],
payload: {
name: '',
arguments: {},
context: ''
}
},
fields: [
{
path: 'to',
label: 'Target Participants',
type: 'list',
description: 'Comma-separated participant IDs to route the tool request to (optional).',
defaultValue: []
},
{
path: 'payload.name',
label: 'Tool Name',
type: 'string',
description: 'Identifier of the tool capability to invoke (e.g., `mcp://fs/read`).',
required: true,
defaultValue: ''
},
{
path: 'payload.arguments',
label: 'Arguments (JSON)',
type: 'json',
description: 'JSON object containing the call arguments for the tool.',
defaultValue: {}
},
{
path: 'payload.context',
label: 'Context',
type: 'string',
description: 'Optional human-readable context or justification for the tool run.',
defaultValue: ''
}
]
},
'stream/open': {
label: 'stream/open',
description: 'Open a new event stream for structured, high-frequency updates.',
base: {
kind: 'stream/open',
to: [],
payload: {
stream: {
name: '',
kind: 'custom',
channel: '',
metadata: {}
}
}
},
fields: [
{
path: 'to',
label: 'Recipients',
type: 'list',
description: 'Comma-separated participant IDs that should receive the stream notifications.',
defaultValue: []
},
{
path: 'payload.stream.name',
label: 'Stream Name',
type: 'string',
description: 'Human-readable name for the stream (e.g., `movement-tracking`).',
required: true,
defaultValue: ''
},
{
path: 'payload.stream.kind',
label: 'Stream Kind',
type: 'string',
description: 'Stream type (e.g., `position`, `chat`, or custom taxonomy).',
defaultValue: 'custom'
},
{
path: 'payload.stream.channel',
label: 'Channel',
type: 'string',
description: 'Optional routing key for multiplexed stream consumers.',
defaultValue: ''
},
{
path: 'payload.stream.metadata',
label: 'Metadata (JSON)',
type: 'json',
description: 'JSON object with implementation-specific metadata for downstream services.',
defaultValue: {}
}
]
}
};

module.exports = envelopeForms;
Loading
Loading