fix(webchat): route slash commands through agent command fast-path
This commit is contained in:
+12
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"updated_at": "2026-02-18",
|
||||
"updated_at": "2026-02-19",
|
||||
"description": "Tracks the status of all Flynn plans and implementation phases",
|
||||
"plans": {
|
||||
"makefile-skills-convenience-targets": {
|
||||
@@ -5548,6 +5548,17 @@
|
||||
"docs/plans/state.json"
|
||||
],
|
||||
"test_status": "pnpm test:run src/channels/telegram/adapter.test.ts src/config/schema.test.ts src/gateway/handlers/services.test.ts src/cli/doctor.test.ts + pnpm typecheck passing"
|
||||
},
|
||||
"webchat-slash-command-agent-fastpath-fix": {
|
||||
"status": "completed",
|
||||
"date": "2026-02-19",
|
||||
"updated": "2026-02-19",
|
||||
"summary": "Fixed WebChat slash command reliability by routing /reset, /compact, /usage, /status, and /model through agent.send command metadata fast-path instead of mixed local RPC shortcuts. This resolves /model returning unknown and keeps command behavior aligned with backend command registry.",
|
||||
"files_modified": [
|
||||
"src/gateway/ui/pages/chat.js",
|
||||
"docs/plans/state.json"
|
||||
],
|
||||
"test_status": "pnpm typecheck + pnpm test:run src/commands/registry.test.ts src/commands/builtin/index.test.ts passing"
|
||||
}
|
||||
},
|
||||
"overall_progress": {
|
||||
|
||||
@@ -368,6 +368,20 @@ function showSystemMessage(content) {
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
async function executeAgentSlashCommand(client, command, commandArgs = '') {
|
||||
const normalizedArgs = (commandArgs ?? '').trim();
|
||||
const message = normalizedArgs ? `/${command} ${normalizedArgs}` : `/${command}`;
|
||||
const metadata = {
|
||||
isCommand: true,
|
||||
command,
|
||||
...(normalizedArgs ? { commandArgs: normalizedArgs } : {}),
|
||||
};
|
||||
|
||||
const stream = client.stream('agent.send', { message, metadata });
|
||||
const done = await stream.result;
|
||||
return done?.content ?? done?.text ?? '';
|
||||
}
|
||||
|
||||
async function handleSlashCommand(cmd, client) {
|
||||
switch (cmd.type) {
|
||||
case 'help': {
|
||||
@@ -381,7 +395,7 @@ async function handleSlashCommand(cmd, client) {
|
||||
'| `/compact` | Ask the agent to compact context |',
|
||||
'| `/usage` | Show token usage stats |',
|
||||
'| `/status` | Show system health |',
|
||||
'| `/model` | Show current model info |',
|
||||
'| `/model [tier|provider]` | Show or set model tier/provider |',
|
||||
'',
|
||||
'Type `/` to see autocomplete suggestions.',
|
||||
];
|
||||
@@ -391,14 +405,9 @@ async function handleSlashCommand(cmd, client) {
|
||||
|
||||
case 'reset': {
|
||||
try {
|
||||
// Send reset command via metadata
|
||||
const stream = client.stream('agent.send', {
|
||||
message: '/reset',
|
||||
metadata: { isCommand: true, command: 'reset' },
|
||||
});
|
||||
await stream.result;
|
||||
const result = await executeAgentSlashCommand(client, 'reset');
|
||||
_elements.messages.innerHTML = '';
|
||||
showSystemMessage('Session reset.');
|
||||
showSystemMessage(result || 'Session reset.');
|
||||
} catch (err) {
|
||||
showSystemMessage(`Failed to reset: ${err.message}`);
|
||||
}
|
||||
@@ -406,33 +415,19 @@ async function handleSlashCommand(cmd, client) {
|
||||
}
|
||||
|
||||
case 'compact': {
|
||||
// Send as a regular message — the agent will interpret the request
|
||||
showSystemMessage('Requesting context compaction...');
|
||||
return false; // Let it pass through as a normal message
|
||||
try {
|
||||
const result = await executeAgentSlashCommand(client, 'compact');
|
||||
showSystemMessage(result || 'Compaction requested.');
|
||||
} catch (err) {
|
||||
showSystemMessage(`Failed to compact: ${err.message}`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case 'usage': {
|
||||
try {
|
||||
const result = await client.call('system.tokenUsage');
|
||||
const sessions = result.sessions ?? [];
|
||||
if (sessions.length === 0) {
|
||||
showSystemMessage('No usage data available.');
|
||||
} else {
|
||||
const lines = ['**Token Usage**', ''];
|
||||
let totalIn = 0, totalOut = 0, totalCalls = 0;
|
||||
for (const s of sessions) {
|
||||
totalIn += s.total?.inputTokens ?? 0;
|
||||
totalOut += s.total?.outputTokens ?? 0;
|
||||
totalCalls += s.total?.calls ?? 0;
|
||||
}
|
||||
lines.push(`**Input:** ${totalIn.toLocaleString()} tokens`);
|
||||
lines.push(`**Output:** ${totalOut.toLocaleString()} tokens`);
|
||||
lines.push(`**API Calls:** ${totalCalls}`);
|
||||
if (sessions.length > 1) {
|
||||
lines.push(`**Sessions:** ${sessions.length}`);
|
||||
}
|
||||
showSystemMessage(lines.join('\n'));
|
||||
}
|
||||
const result = await executeAgentSlashCommand(client, 'usage');
|
||||
showSystemMessage(result || 'No usage data available.');
|
||||
} catch (err) {
|
||||
showSystemMessage(`Failed to fetch usage: ${err.message}`);
|
||||
}
|
||||
@@ -441,24 +436,8 @@ async function handleSlashCommand(cmd, client) {
|
||||
|
||||
case 'status': {
|
||||
try {
|
||||
const result = await client.call('system.health');
|
||||
const lines = [
|
||||
'**System Status**',
|
||||
'',
|
||||
`**Uptime:** ${result.uptime ?? 'unknown'}`,
|
||||
`**Status:** ${result.status ?? 'unknown'}`,
|
||||
];
|
||||
if (result.channels) {
|
||||
lines.push('', '**Channels:**');
|
||||
for (const ch of result.channels) {
|
||||
const dot = ch.status === 'connected' ? '\\*' : '-';
|
||||
lines.push(` ${dot} ${ch.name}: ${ch.status}`);
|
||||
}
|
||||
}
|
||||
if (result.model) {
|
||||
lines.push('', `**Model:** ${result.model}`);
|
||||
}
|
||||
showSystemMessage(lines.join('\n'));
|
||||
const result = await executeAgentSlashCommand(client, 'status');
|
||||
showSystemMessage(result || 'Status unavailable.');
|
||||
} catch (err) {
|
||||
showSystemMessage(`Failed to fetch status: ${err.message}`);
|
||||
}
|
||||
@@ -467,9 +446,8 @@ async function handleSlashCommand(cmd, client) {
|
||||
|
||||
case 'model': {
|
||||
try {
|
||||
const result = await client.call('system.health');
|
||||
const model = result.model ?? result.config?.model ?? 'unknown';
|
||||
showSystemMessage(`**Current Model:** ${model}`);
|
||||
const result = await executeAgentSlashCommand(client, 'model', cmd.args ?? '');
|
||||
showSystemMessage(result || 'Model info unavailable.');
|
||||
} catch (err) {
|
||||
showSystemMessage(`Failed to fetch model info: ${err.message}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user