Skip to content

Commit 3ad615b

Browse files
committed
Updates
1 parent f09f117 commit 3ad615b

File tree

6 files changed

+174
-641
lines changed

6 files changed

+174
-641
lines changed

spec/scratch/MESSAGE-FORMATTERS.md

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,30 @@ This document inventories which MEW protocol messages have dedicated formatters
99
### ✅ Implemented Formatters
1010

1111
#### `chat`
12-
- **Location**: `src/cli/utils/interactive-ui.ts` (line ~770), `src/cli/utils/advanced-interactive-ui.ts` (line ~1900)
13-
- **Formatting**:
12+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~1900)
13+
- **Formatting**:
1414
- Shows text content directly
15-
- In advanced UI: Full-width separators (top/bottom borders) for visual distinction
15+
- Full-width separators (top/bottom borders) for visual distinction
1616
- Filled diamond (◆) prefix
1717
- Theme-aware colors
1818

19+
#### `chat/acknowledge`
20+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2544)
21+
- **Formatting**:
22+
- Checkmark (✓) prefix
23+
- Shows status field from payload (e.g., "processing", "received", "seen")
24+
- Example: `✓ processing` or `✓ received`
25+
- Note: Per spec, payload only contains `status` field; correlation_id (in envelope) references acknowledged message
26+
1927
#### `mcp/request` and `mcp/proposal`
20-
- **Location**: `src/cli/utils/interactive-ui.ts` (line ~775), `src/cli/utils/advanced-interactive-ui.ts` (line ~1920)
28+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~1920)
2129
- **Formatting**:
2230
- Shows method and tool name
2331
- Arguments preview
2432
- Special handling for `tools/call` with tool-specific formatters
2533

2634
#### `mcp/response`
27-
- **Location**: `src/cli/utils/interactive-ui.ts` (line ~780), `src/cli/utils/advanced-interactive-ui.ts` (line ~1940)
35+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~1940)
2836
- **Formatting**:
2937
- Handles result content arrays (shows first text item)
3038
- Object results with key summary
@@ -44,13 +52,46 @@ This document inventories which MEW protocol messages have dedicated formatters
4452
- Prefixes: ◇ for start, ◆ for conclusion
4553
- Message preview (truncated to 120 chars)
4654

55+
#### `stream/request`
56+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2642)
57+
- **Formatting**:
58+
- Shows direction (upload/download)
59+
- Shows description if present
60+
- Shows expected size in MB if present
61+
- Example: `upload stream "reasoning:reason-123"` or `download stream (5.2MB)`
62+
63+
#### `stream/open`
64+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2649)
65+
- **Formatting**:
66+
- Shows stream ID and encoding
67+
- Example: `opened stream-4 [text]` or `opened stream-42 [binary]`
68+
69+
#### `stream/close`
70+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2655)
71+
- **Formatting**:
72+
- Shows stream ID (if present) and reason
73+
- Example: `stream-4 complete` or `cancelled`
74+
4775
#### `system/help`
4876
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~1970)
4977
- **Formatting**:
5078
- Multi-line display with proper indentation
5179
- Section titles highlighted
5280
- Line-by-line rendering
5381

82+
#### `system/info`
83+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2565)
84+
- **Formatting**:
85+
- Shows text content directly
86+
- Example: `Stream closed (complete)`
87+
88+
#### `system/welcome`
89+
- **Location**: `src/cli/utils/advanced-interactive-ui.ts` (line ~2569)
90+
- **Formatting**:
91+
- Shows your participant ID, capability count, and other participants
92+
- Example: `connected as participant-123 (2 capabilities) • 2 other participants: mew, mcp-fs-bridge`
93+
- Concise format to avoid bloat (per spec recommendation)
94+
5495
### 🛠️ Tool-Specific Formatters
5596

5697
The advanced UI includes a pluggable tool formatter system for `mcp/proposal` messages:
@@ -77,11 +118,10 @@ The advanced UI includes a pluggable tool formatter system for `mcp/proposal` me
77118

78119
These message types fall back to generic JSON preview in `getPayloadPreview()`:
79120

80-
#### `system/*` (except `help`)
81-
- `system/welcome`
121+
#### `system/*` (except `help`, `info`, `welcome`)
82122
- `system/heartbeat`
83123
- `system/error`
84-
- `system/info`
124+
- `system/presence`
85125
- **Current behavior**: Generic object preview showing first 2-3 keys
86126

87127
#### `participant/*`
@@ -97,19 +137,15 @@ These message types fall back to generic JSON preview in `getPayloadPreview()`:
97137
- `participant/compact-done`
98138
- **Current behavior**: Generic object preview
99139

100-
#### `stream/*`
101-
- `stream/open`
102-
- `stream/close`
103-
- `stream/request`
104-
- `stream/data`
105-
- **Current behavior**: Generic object preview (though `stream/data` is filtered from display)
140+
#### `stream/data`
141+
- **Current behavior**: Filtered from display (binary/chunked data, not shown in envelope view)
106142

107143
#### `capability/*`
108144
- `capability/grant`
109145
- `capability/grant-ack`
110146
- **Current behavior**: Generic object preview
111147

112-
#### `chat/acknowledge` & `chat/cancel`
148+
#### `chat/cancel`
113149
- **Current behavior**: Generic object preview
114150

115151
#### Other Protocol Messages
@@ -118,29 +154,25 @@ These message types fall back to generic JSON preview in `getPayloadPreview()`:
118154

119155
## Formatter Architecture
120156

121-
### Interactive UI (Simple)
122-
- **File**: `src/cli/utils/interactive-ui.ts`
123-
- **Function**: `getPayloadPreview()` (line ~700)
124-
- **Approach**: Switch statement with kind-specific logic
125-
126-
### Advanced UI (Rich)
157+
### Advanced UI (Only)
127158
- **File**: `src/cli/utils/advanced-interactive-ui.ts`
159+
- **Function**: `getPayloadPreview()` (line ~2540)
128160
- **Component**: `ReasoningDisplay` (line ~1880)
129161
- **Approach**: React component with pluggable tool formatters
130162
- **Tool Formatters**: Object registry at line ~1300
163+
- **Note**: The simple readline UI has been removed as of v0.5
131164

132165
## Recommendations
133166

134167
### High Priority Formatters
135168
1. **`system/error`** - Errors should have distinct formatting (red, prominent)
136169
2. **`participant/status`** - Status telemetry could be tabular
137-
3. **`stream/open`** - Stream info could show direction/encoding
138-
4. **`capability/grant`** - Security-critical, needs clear display
170+
3. **`capability/grant`** - Security-critical, needs clear display
139171

140172
### Medium Priority Formatters
141-
1. **`system/welcome`** - Connection info could be structured
142-
2. **`participant/pause`** - Show timeout and reason clearly
143-
3. **`chat/acknowledge`** - Show ack status visually
173+
1. **`participant/pause`** - Show timeout and reason clearly
174+
2. **`chat/cancel`** - Show cancellation status visually
175+
3. **`system/presence`** - Show join/leave events clearly
144176

145177
### Tool Formatters to Add
146178
1. **`read_file`** - Show file path and size

src/cli/commands/space.ts

Lines changed: 40 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
getInteractiveOverrides,
1818
} from '../utils/participant-resolver.js';
1919
import { printBanner } from '../utils/banner.js';
20-
import * as interactiveUI from '../utils/interactive-ui.js';
2120
import * as advancedInteractiveUI from '../utils/advanced-interactive-ui.js';
2221
import { getTheme } from '../themes.js';
2322

@@ -894,15 +893,6 @@ async function spaceUpAction(options) {
894893
if (options.interactive) {
895894
console.log('\nConnecting interactively...\n');
896895

897-
// Determine UI mode
898-
const useDebugUI = options.debug || options.simple || options.noUi;
899-
900-
// Select appropriate UI module
901-
const InteractiveUI = useDebugUI ? interactiveUI : null;
902-
const startAdvancedInteractiveUI = useDebugUI
903-
? null
904-
: advancedInteractiveUI.startAdvancedInteractiveUI;
905-
906896
try {
907897
// Resolve participant
908898
const participant = await resolveParticipant({
@@ -944,41 +934,27 @@ async function spaceUpAction(options) {
944934
const theme = getTheme(themeName);
945935

946936
// Display banner before starting UI
947-
if (!useDebugUI) {
948-
printBanner({
949-
spaceName: spaceName,
950-
spaceId: spaceId,
951-
participantId: participant.id,
952-
gateway: `ws://localhost:${selectedPort}`,
953-
color: process.env.NO_COLOR !== '1',
954-
theme: theme
955-
});
956-
}
937+
printBanner({
938+
spaceName: spaceName,
939+
spaceId: spaceId,
940+
participantId: participant.id,
941+
gateway: `ws://localhost:${selectedPort}`,
942+
color: process.env.NO_COLOR !== '1',
943+
theme: theme
944+
});
957945

958-
// Start interactive UI
959-
if (useDebugUI) {
960-
const defaultChatTargets = {
961-
participant: Array.isArray(config?.participants?.[participant.id]?.default_to?.chat)
962-
? config.participants[participant.id].default_to.chat.slice()
963-
: null,
964-
global: Array.isArray(config?.defaults?.routing?.default_to?.chat)
965-
? config.defaults.routing.default_to.chat.slice()
966-
: null
967-
};
968-
const ui = new InteractiveUI(ws, participant.id, spaceId, defaultChatTargets);
969-
ui.start();
970-
} else {
971-
// Compute default chat targets from config
972-
const defaultChatTargets = {
973-
participant: Array.isArray(config?.participants?.[participant.id]?.default_to?.chat)
974-
? config.participants[participant.id].default_to.chat.slice()
975-
: null,
976-
global: Array.isArray(config?.defaults?.routing?.default_to?.chat)
977-
? config.defaults.routing.default_to.chat.slice()
978-
: null
979-
};
980-
startAdvancedInteractiveUI(ws, participant.id, spaceId, themeName, defaultChatTargets);
981-
}
946+
// Compute default chat targets from config
947+
const defaultChatTargets = {
948+
participant: Array.isArray(config?.participants?.[participant.id]?.default_to?.chat)
949+
? config.participants[participant.id].default_to.chat.slice()
950+
: null,
951+
global: Array.isArray(config?.defaults?.routing?.default_to?.chat)
952+
? config.defaults.routing.default_to.chat.slice()
953+
: null
954+
};
955+
956+
// Start advanced interactive UI
957+
advancedInteractiveUI.startAdvancedInteractiveUI(ws, participant.id, spaceId, themeName, defaultChatTargets);
982958
});
983959

984960
ws.on('error', (err) => {
@@ -1003,9 +979,6 @@ space
1003979
.option('-i, --interactive', 'Connect interactively after starting space')
1004980
.option('--detach', 'Run in background (default if not interactive)')
1005981
.option('--participant <id>', 'Connect as this participant (with --interactive)')
1006-
.option('--debug', 'Use simple debug interface instead of advanced UI')
1007-
.option('--simple', 'Alias for --debug')
1008-
.option('--no-ui', 'Disable UI enhancements, use plain interface')
1009982
.action(spaceUpAction);
1010983

1011984
// Action handler for space down
@@ -1539,9 +1512,6 @@ space
15391512
.option('-d, --space-dir <path>', 'Directory of space to connect to', '.')
15401513
.option('--participant <id>', 'Connect as this participant')
15411514
.option('--gateway <url>', 'Override gateway URL (default: from running space)')
1542-
.option('--debug', 'Use simple debug interface instead of advanced UI')
1543-
.option('--simple', 'Alias for --debug')
1544-
.option('--no-ui', 'Disable UI enhancements, use plain interface')
15451515
.action(async (options) => {
15461516
const spaceDir = path.resolve(options.spaceDir);
15471517
const configPath = path.join(spaceDir, path.basename(options.config));
@@ -1563,15 +1533,6 @@ space
15631533
console.log(`Space: ${pids.spaceName} (${spaceId})`);
15641534
console.log(`Gateway: ${gatewayUrl}`);
15651535

1566-
// Determine UI mode
1567-
const useDebugUI = options.debug || options.simple || options.noUi;
1568-
1569-
// Select appropriate UI module
1570-
const InteractiveUI = useDebugUI ? interactiveUI : null;
1571-
const startAdvancedInteractiveUI = useDebugUI
1572-
? null
1573-
: advancedInteractiveUI.startAdvancedInteractiveUI;
1574-
15751536
try {
15761537
// Resolve participant
15771538
const participant = await resolveParticipant({
@@ -1613,33 +1574,27 @@ space
16131574
const theme = getTheme(themeName);
16141575

16151576
// Display banner before starting UI
1616-
if (!useDebugUI) {
1617-
printBanner({
1618-
spaceName: pids.spaceName,
1619-
spaceId: spaceId,
1620-
participantId: participant.id,
1621-
gateway: gatewayUrl,
1622-
color: process.env.NO_COLOR !== '1',
1623-
theme: theme
1624-
});
1625-
}
1577+
printBanner({
1578+
spaceName: pids.spaceName,
1579+
spaceId: spaceId,
1580+
participantId: participant.id,
1581+
gateway: gatewayUrl,
1582+
color: process.env.NO_COLOR !== '1',
1583+
theme: theme
1584+
});
16261585

1627-
// Start interactive UI
1628-
if (useDebugUI) {
1629-
const ui = new InteractiveUI(ws, participant.id, spaceId);
1630-
ui.start();
1631-
} else {
1632-
// Compute default chat targets from config
1633-
const defaultChatTargets = {
1634-
participant: Array.isArray(config?.participants?.[participant.id]?.default_to?.chat)
1635-
? config.participants[participant.id].default_to.chat.slice()
1636-
: null,
1637-
global: Array.isArray(config?.defaults?.routing?.default_to?.chat)
1638-
? config.defaults.routing.default_to.chat.slice()
1639-
: null
1640-
};
1641-
startAdvancedInteractiveUI(ws, participant.id, spaceId, themeName, defaultChatTargets);
1642-
}
1586+
// Compute default chat targets from config
1587+
const defaultChatTargets = {
1588+
participant: Array.isArray(config?.participants?.[participant.id]?.default_to?.chat)
1589+
? config.participants[participant.id].default_to.chat.slice()
1590+
: null,
1591+
global: Array.isArray(config?.defaults?.routing?.default_to?.chat)
1592+
? config.defaults.routing.default_to.chat.slice()
1593+
: null
1594+
};
1595+
1596+
// Start advanced interactive UI
1597+
advancedInteractiveUI.startAdvancedInteractiveUI(ws, participant.id, spaceId, themeName, defaultChatTargets);
16431598
});
16441599

16451600
ws.on('error', (err) => {

src/cli/ui/components/EnhancedInput.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,7 @@ import { useKeypress } from '../hooks/useKeypress.js';
1717
import { getCommand } from '../keyMatchers.js';
1818
import { defaultKeyBindings } from '../../config/keyBindings.js';
1919
import { getSlashCommandSuggestions } from '../utils/slashCommands.js';
20-
import fs from 'fs';
21-
import path from 'path';
22-
// Helper function for debug logging
23-
const debugLog = (message) => {
24-
const logFile = path.join(process.cwd(), '.mew', 'debug.log');
25-
const mewDir = path.join(process.cwd(), '.mew');
26-
if (!fs.existsSync(mewDir)) {
27-
fs.mkdirSync(mewDir, { recursive: true });
28-
}
29-
fs.appendFileSync(logFile, message);
30-
};
20+
import { debugLog } from '../../utils/debug.js';
3121

3222
/**
3323
* Enhanced Input Component
@@ -44,12 +34,12 @@ const debugLog = (message) => {
4434
* @returns {React.Element}
4535
*/
4636
function EnhancedInput({
47-
onSubmit = () => {},
37+
onSubmit = () => { },
4838
placeholder = '',
4939
multiline = false,
5040
disabled = false,
5141
history = [],
52-
onHistoryChange = () => {},
42+
onHistoryChange = () => { },
5343
keyBindings = defaultKeyBindings,
5444
showCursor = true,
5545
prompt = '> ',
@@ -326,7 +316,7 @@ function EnhancedInput({
326316

327317
// Submission
328318
case 'SUBMIT':
329-
debugLog(`\n>>> SUBMIT CASE REACHED <<<\n`);
319+
debugLog(`\n>>> SUBMIT CASE REACHED 2 <<<\n`);
330320
debugLog(`>>> Buffer text: "${buffer.getText()}"\n`);
331321
if (!multiline || !buffer.getText().includes('\n')) {
332322
debugLog(`>>> CALLING handleSubmit() <<<\n`);

0 commit comments

Comments
 (0)