Skip to content

feat: add minimax and zai agent plugins#166

Open
txhno wants to merge 2 commits intosubsy:mainfrom
txhno:feat/minimax-zai-agents
Open

feat: add minimax and zai agent plugins#166
txhno wants to merge 2 commits intosubsy:mainfrom
txhno:feat/minimax-zai-agents

Conversation

@txhno
Copy link

@txhno txhno commented Jan 20, 2026

Add support for minimax and zai CLI agents from cc-mirror
(https://github.com/numman-ali/cc-mirror). Both are wrappers
for Claude Code (v2.1.1) and use --output-format stream-json
--verbose for structured JSONL output parsing.

Changes

  • Add zai.ts agent plugin with stream-json parsing
  • Add minimax.ts agent plugin with stream-json parsing
  • Register both plugins in builtin/index.ts

Features

Both agents support:

  • Streaming output with proper event type parsing (assistant, result, tool_use, tool_result, system)
  • Tool use and tool result event tracking
  • Subagent tracing via onJsonlMessage forwarding
  • File context via --add-dir flag
  • Configurable model and skip-permissions options

Summary by CodeRabbit

  • New Features
    • Added MiniMax as a built-in agent with CLI detection, version checks, model selection, streaming output handling and tool integration.
    • Added Zai as a built-in agent for Claude Code support with sandbox guidance, model options, streaming JSONL output handling and setup flows.
    • Expanded built-in agent exports to make the new agents available via the public API.

✏️ Tip: You can customize this high-level summary in your review settings.

  Add support for minimax and zai CLI agents from cc-mirror
  (https://github.com/numman-ali/cc-mirror). Both are wrappers
  for Claude Code (v2.1.1) and use --output-format stream-json
  --verbose for structured JSONL output parsing.

  Changes:
  - Add zai.ts agent plugin with stream-json parsing
  - Add minimax.ts agent plugin with stream-json parsing
  - Register both plugins in builtin/index.ts

  Both agents support:
  - Streaming output with proper event type parsing
  - Tool use and tool result event tracking
  - Subagent tracing via onJsonlMessage forwarding
  - File context via --add-dir flag
  - Configurable model and skip-permissions options
@vercel
Copy link

vercel bot commented Jan 20, 2026

Someone is attempting to deploy a commit to the plgeek Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Walkthrough

Adds two built‑in agent plugins (MiniMax and Zai) with CLI detection/version checks, JSONL stream parsing to AgentDisplayEvents, sandbox and setup metadata, streaming execution that forwards JSONL and UI events, and factory exports; also re-exports ClaudeAgentPlugin and exposes new factory functions.

Changes

Cohort / File(s) Summary
Public API exports
src/plugins/agents/builtin/index.ts
Extended exports to include createMiniMaxAgent and createZaiAgent; re‑exported ClaudeAgentPlugin from ./claude.js.
MiniMax agent implementation
src/plugins/agents/builtin/minimax.ts
New MiniMaxAgentPlugin and factory: PATH detection + --version, CLI arg building, stdin prompt delivery, JSONL/stream‑json parsing to AgentDisplayEvent[], streaming callbacks (onJsonlMessage, onStdoutSegments, onStdout), sandbox requirements, setup/questions, VALID_MODELS.
Zai agent implementation
src/plugins/agents/builtin/zai.ts
New ZaiAgentPlugin and factory: binary detection/version, buildArgs/getStdinInput, execute with CLI spawn, JSONL parsing pipeline to display events, dual callback paths for traces and UI segments, sandbox metadata, setup questions and preflight suggestion.

Sequence Diagram(s)

sequenceDiagram
    participant Host as Host
    participant Plugin as Agent Plugin
    participant CLI as CLI Process
    participant Parser as JSONL Parser
    participant Callbacks as Callbacks

    Host->>Plugin: execute(prompt, files, options)
    Plugin->>Plugin: buildArgs & getStdinInput
    Plugin->>CLI: spawn process (stdin)
    CLI->>CLI: consume stdin, run model, emit JSONL
    CLI-->>Plugin: stdout/stderr (line‑delimited JSON)
    loop Stream processing
        Plugin->>Parser: feed JSONL line
        Parser-->>Plugin: AgentDisplayEvent[]
        Plugin->>Callbacks: onJsonlMessage(raw)
        Plugin->>Callbacks: onStdoutSegments / onStdout(events)
    end
    CLI-->>Plugin: exit
    Plugin-->>Host: return AgentExecutionHandle
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I found two CLIs in the glade,
MiniMax and Zai in streaming parade,
I nibbled JSON lines and spun them bright,
Emitting events through day and night,
Hooray — carrots for every byte! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarises the main change: adding two new agent plugins (minimax and zai) to the built-in agents module.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/plugins/agents/builtin/minimax.ts`:
- Around line 54-65: In the case 'result' block inside
src/plugins/agents/builtin/minimax.ts, avoid emitting duplicate events when an
error result is represented as a string: if event.subtype === 'error' (or
event.is_error) has been detected and you pushed an error entry to allEvents, do
not also push a 'text' entry for the same event.result; update the logic in that
case 'result' branch to either use an else (skip adding the text when
subtype/error was handled) or add a conditional check before pushing the 'text'
event to ensure the previous error path didn't already consume event.result.
- Around line 401-407: In validateSetup replace the inline array check with the
shared VALID_MODELS constant (the same constant used by validateModel) so model
validation uses VALID_MODELS for allowed values; locate the conditional in
validateSetup that currently compares model against ['MiniMax-M2.1',
'MiniMax-M2', 'MiniMax-M1'] and update it to reference VALID_MODELS (convert
model to string as currently done) so both validateSetup and validateModel stay
consistent.

In `@src/plugins/agents/builtin/zai.ts`:
- Around line 53-64: The result-case handler in case 'result' (inside zai.ts)
can push both an error event and a text event for the same error result; update
the logic around event.subtype/event.is_error and event.result so that when you
detect an error (using event.subtype === 'error' || event.is_error ||
event.error), you push only the error into allEvents and skip adding the text
branch—e.g., make the text push conditional only when not an error (use else or
a negated check) so allEvents does not get duplicate error/text entries.
- Around line 186-193: getSandboxRequirements currently includes a hardcoded
user-specific path "/Users/roshan/.local/bin"; remove that entry and replace it
with a generic, cross-user alternative (e.g., expand "~/.local/bin" or rely on
PATH resolution) in the binaryPaths array inside the getSandboxRequirements
method so the function no longer references a developer-specific filesystem
location.
🧹 Nitpick comments (5)
src/plugins/agents/builtin/minimax.ts (2)

312-325: Consider cross-platform path handling.

The directory extraction uses forward slash (/) only. On Windows, paths may use backslashes. Consider using path.dirname() from node:path for robust cross-platform support.

Also, root-level files (where lastSlash <= 0) are silently skipped. This may be intentional but worth documenting.

♻️ Suggested improvement
+import { dirname } from 'node:path';
 // ... in buildArgs:
     if (files && files.length > 0) {
       const directories = new Set<string>();
 
       for (const file of files) {
-        const lastSlash = file.path.lastIndexOf('/');
-        if (lastSlash > 0) {
-          directories.add(file.path.substring(0, lastSlash));
+        const dir = dirname(file.path);
+        if (dir && dir !== '.' && dir !== '/') {
+          directories.add(dir);
         }
       }

253-258: Potential double resolution after timeout.

When the timeout fires, proc.kill() is called and the promise resolves with a timeout error. However, the close event will still fire afterwards, potentially causing the promise to resolve twice. While Node.js Promises ignore subsequent resolutions, this can be confusing and may mask issues.

♻️ Suggested fix
   private runVersion(
     command: string
   ): Promise<{ success: boolean; version?: string; error?: string }> {
     return new Promise((resolve) => {
+      let resolved = false;
+      const safeResolve = (result: { success: boolean; version?: string; error?: string }) => {
+        if (!resolved) {
+          resolved = true;
+          resolve(result);
+        }
+      };
       const proc = spawn(command, ['--version'], {
         // ... rest of spawn options
       });
       
       // ... event handlers using safeResolve instead of resolve
       
       setTimeout(() => {
         proc.kill();
-        resolve({ success: false, error: 'Timeout waiting for --version' });
+        safeResolve({ success: false, error: 'Timeout waiting for --version' });
       }, 5000);
     });
   }
src/plugins/agents/builtin/zai.ts (3)

30-104: Significant code duplication with parseMiniMaxOutputToEvents.

This function is nearly identical to parseMiniMaxOutputToEvents in minimax.ts. Since both agents wrap Claude Code with the same stream-json output format, consider extracting a shared parser function.

♻️ Suggested approach

Create a shared parser in a common location (e.g., output-formatting.ts or a new claude-code-parser.ts):

// In a shared module, e.g., ../claude-code-parser.ts
export function parseClaudeCodeJsonlOutput(data: string): AgentDisplayEvent[] {
  // ... shared implementation
}

Then both agents can import and use the shared parser:

import { parseClaudeCodeJsonlOutput } from '../claude-code-parser.js';
// ...
const events = parseClaudeCodeJsonlOutput(data);

240-244: Same timeout double-resolution issue as minimax.ts.

This has the same potential for double promise resolution after timeout. Consider the same fix or extracting to a shared utility.


289-300: Same cross-platform path handling consideration as minimax.ts.

The directory extraction logic has the same platform-specific path separator issue. Consider using path.dirname() for consistency.

  - Use else-if in result case to avoid duplicate error/text events
  - Reference VALID_MODELS constant in minimax validateSetup
  - Remove hardcoded user path from zai getSandboxRequirements
@subsy
Copy link
Owner

subsy commented Jan 22, 2026

@txhno did you try using the builtin command option to run cc mirror using the claude agent?

https://ralph-tui.com/docs/configuration/options#custom-command

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.

2 participants

Comments