Files
Jack Chen 98dbc2025e docs(examples): prefix example run commands with packages/core/ (#330)
* docs(examples): prefix example run commands with packages/core/

Examples live under packages/core/, and both READMEs document running them from the repo root (npx tsx packages/core/examples/<path>.ts), but the in-file Run: headers and a few READMEs still used the bare examples/ path. The repo root has no top-level examples/, so copy-pasting those commands from root failed with file-not-found.

Prefixes 67 run/cd commands across 56 files (53 example scripts + examples/README.md + two integration READMEs). Markdown links that use the bare examples/ path are correct relative links and are left unchanged.

* docs: prefix two stale examples/ path references in docs/

context-management.md and tool-configuration.md referenced bare examples/ paths that do not resolve from the repo root. Make the first a relative link (matching the convention in model-routing.md) and prefix the second with packages/core/. Follow-up to the run-command fixes in this PR.
2026-06-24 17:14:23 +08:00

168 lines
6.0 KiB
TypeScript

/**
* Multi-Agent Team Collaboration with MiMo
*
* Three specialized agents (architect, developer, reviewer) collaborate via `runTeam()`
* to build a minimal Express.js REST API. Every agent uses MiMo's OpenAI-compatible API.
*
* Run:
* npx tsx packages/core/examples/providers/mimo.ts
*
* Prerequisites:
* MIMO_API_KEY environment variable must be set.
* Token Plan keys (tp-...) also need MIMO_BASE_URL set to the cluster URL
* shown on your subscription page, for example https://token-plan-cn.xiaomimimo.com/v1.
*
* Available models:
* mimo-v2.5-pro
* mimo-v2.5
* mimo-v2-pro
* mimo-v2-omni
*/
import { join } from 'node:path'
import { OpenMultiAgent } from '../../src/index.js'
import type { AgentConfig, OrchestratorEvent } from '../../src/types.js'
// Built-in filesystem tools are sandboxed to `<cwd>/.agent-workspace` by
// default; route generated output there so the demo runs without
// disabling the sandbox.
const OUTPUT_DIR = join(process.cwd(), '.agent-workspace', 'mimo-api')
// ---------------------------------------------------------------------------
// Agent definitions (all using MiMo)
// ---------------------------------------------------------------------------
const architect: AgentConfig = {
name: 'architect',
model: 'mimo-v2.5-pro',
provider: 'mimo',
systemPrompt: `You are a software architect with deep experience in Node.js and REST API design.
Your job is to design clear, production-quality API contracts and file/directory structures.
Output concise plans in markdown - no unnecessary prose.`,
tools: ['bash', 'file_write'],
maxTurns: 5,
temperature: 0.2,
}
const developer: AgentConfig = {
name: 'developer',
model: 'mimo-v2.5-pro',
provider: 'mimo',
systemPrompt: `You are a TypeScript/Node.js developer. You implement what the architect specifies.
Write clean, runnable code with proper error handling. Use the tools to write files and run tests.`,
tools: ['bash', 'file_read', 'file_write', 'file_edit'],
maxTurns: 12,
temperature: 0.1,
}
const reviewer: AgentConfig = {
name: 'reviewer',
model: 'mimo-v2.5-pro',
provider: 'mimo',
systemPrompt: `You are a senior code reviewer. Review code for correctness, security, and clarity.
Provide a structured review with: LGTM items, suggestions, and any blocking issues.
Read files using the tools before reviewing.`,
tools: ['bash', 'file_read', 'grep'],
maxTurns: 5,
temperature: 0.3,
}
// ---------------------------------------------------------------------------
// Progress tracking
// ---------------------------------------------------------------------------
const startTimes = new Map<string, number>()
function handleProgress(event: OrchestratorEvent): void {
const ts = new Date().toISOString().slice(11, 23) // HH:MM:SS.mmm
switch (event.type) {
case 'agent_start':
startTimes.set(event.agent ?? '', Date.now())
console.log(`[${ts}] AGENT START -> ${event.agent}`)
break
case 'agent_complete': {
const elapsed = Date.now() - (startTimes.get(event.agent ?? '') ?? Date.now())
console.log(`[${ts}] AGENT DONE -> ${event.agent} (${elapsed}ms)`)
break
}
case 'task_start':
console.log(`[${ts}] TASK START -> ${event.task}`)
break
case 'task_complete':
console.log(`[${ts}] TASK DONE -> ${event.task}`)
break
case 'message':
console.log(`[${ts}] MESSAGE - ${event.agent} -> (team)`)
break
case 'error':
console.error(`[${ts}] ERROR agent=${event.agent} task=${event.task}`)
if (event.data instanceof Error) console.error(` ${event.data.message}`)
break
}
}
// ---------------------------------------------------------------------------
// Orchestrate
// ---------------------------------------------------------------------------
const orchestrator = new OpenMultiAgent({
defaultModel: 'mimo-v2.5-pro',
defaultProvider: 'mimo',
maxConcurrency: 1, // sequential for readable output
onProgress: handleProgress,
})
const team = orchestrator.createTeam('api-team', {
name: 'api-team',
agents: [architect, developer, reviewer],
sharedMemory: true,
maxConcurrency: 1,
})
console.log(`Team "${team.name}" created with agents: ${team.getAgents().map(a => a.name).join(', ')}`)
console.log('\nStarting team run...\n')
console.log('='.repeat(60))
const goal = `Create a minimal Express.js REST API in ${OUTPUT_DIR}/ with:
- GET /health returns { status: "ok" }
- GET /users returns a hardcoded array of 2 user objects
- POST /users accepts { name, email } body, logs it, returns 201
- Proper error handling middleware
- The server should listen on port 3001
- Include a package.json with the required dependencies`
const result = await orchestrator.runTeam(team, goal)
console.log('\n' + '='.repeat(60))
// ---------------------------------------------------------------------------
// Results
// ---------------------------------------------------------------------------
console.log('\nTeam run complete.')
console.log(`Success: ${result.success}`)
console.log(`Total tokens - input: ${result.totalTokenUsage.input_tokens}, output: ${result.totalTokenUsage.output_tokens}`)
console.log('\nPer-agent results:')
for (const [agentName, agentResult] of result.agentResults) {
const status = agentResult.success ? 'OK' : 'FAILED'
const tools = agentResult.toolCalls.length
console.log(` ${agentName.padEnd(12)} [${status}] tool_calls=${tools}`)
if (!agentResult.success) {
console.log(` Error: ${agentResult.output.slice(0, 120)}`)
}
}
const developerResult = result.agentResults.get('developer')
if (developerResult?.success) {
console.log('\nDeveloper output (last 600 chars):')
console.log('-'.repeat(60))
const out = developerResult.output
console.log(out.length > 600 ? '...' + out.slice(-600) : out)
console.log('-'.repeat(60))
}
const reviewerResult = result.agentResults.get('reviewer')
if (reviewerResult?.success) {
console.log('\nReviewer output:')
console.log('-'.repeat(60))
console.log(reviewerResult.output)
console.log('-'.repeat(60))
}