Skip to content

feat: add shared messaging utils and surface real Claude CLI errors#58

Open
sean808080 wants to merge 1 commit intomoazbuilds:masterfrom
sean808080:feat/shared-messaging-utils
Open

feat: add shared messaging utils and surface real Claude CLI errors#58
sean808080 wants to merge 1 commit intomoazbuilds:masterfrom
sean808080:feat/shared-messaging-utils

Conversation

@sean808080
Copy link
Copy Markdown

Problem

Claude CLI exits non-zero on auth and quota failures, but the human-readable error message (e.g. Not logged in · Please run /login) lives in the JSON stdout result field — not in stderr. All three chat bridges were showing Unknown error instead of the actual failure reason.

Before:

Error (exit 1): Unknown error

After:

Error (exit 1): Not logged in · Please run /login

Solution

Introduces src/messaging.ts — a shared utilities module used by start.ts, telegram.ts, and discord.ts.

Key function: extractErrorDetail(result)

export function extractErrorDetail(result: { stdout: string; stderr: string }): string {
  const stderr = result.stderr?.trim() || "";
  if (stderr) return stderr;

  // Claude CLI emits human-readable errors in JSON stdout when stderr is empty
  try {
    const parsed = JSON.parse(stdout);
    if (parsed?.is_error && parsed?.result) return String(parsed.result).trim();
    if (parsed?.error?.message) return String(parsed.error.message).trim();
    if (typeof parsed?.error === "string") return parsed.error.trim();
  } catch {}

  return stdout;
}

Additional utilities (no behaviour change, available for future use)

  • describeProvider() — human-readable provider/model label
  • isProviderStatusQuery() / isModelChangeRequest() — intent detection for model-switch queries
  • authoritativeProviderReply() — canonical provider status response
  • extractReactionDirective() — strips [react:emoji] directives from response text

Files changed

File Change
src/messaging.ts New shared utilities module
src/commands/start.ts Use extractErrorDetail in forwardToTelegram and forwardToDiscord
src/commands/telegram.ts Use extractErrorDetail in the main message handler error path
src/commands/discord.ts Use extractErrorDetail in the main message handler error path

Testing

Auth failures now surface the real Claude CLI message across all three chat interfaces. The fix handles:

  • stderr present → returns stderr (existing behaviour, unchanged)
  • stderr empty, JSON stdout with is_error: true → returns result field
  • stderr empty, JSON stdout with error.message → returns error.message
  • Fallback to raw stdout if JSON parse fails

Claude CLI exits non-zero on auth and quota failures, but the
human-readable message (e.g. "Not logged in · Please run /login")
lives in the JSON stdout `result` field, not stderr. All three
chat bridges (start.ts, telegram.ts, discord.ts) were showing
"Unknown error" instead of the actual message.

This PR introduces src/messaging.ts with shared utility functions:
- extractErrorDetail(): prefers stderr, falls back to parsing JSON
  stdout for Claude CLI's is_error/result error pattern
- describeProvider(): human-readable provider/model label
- isProviderStatusQuery() / isModelChangeRequest(): intent detection
- authoritativeProviderReply(): canonical provider status response
- extractReactionDirective(): strips [react:emoji] directives from text

Updates start.ts, telegram.ts, and discord.ts to use extractErrorDetail
so auth failures, quota errors, and other CLI failures show the real
error message across all chat interfaces.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant