mirror of
https://github.com/JackChen-me/open-multi-agent.git
synced 2026-10-21 10:40:12 -05:00
* fix: redact secrets in traces, bash env, and dashboard payloads Adds src/utils/redaction.ts and applies best-effort redaction at three sinks where sensitive data could leak: - tool_call trace events (input, output) - the bash tool's output buffer - the post-run dashboard's embedded JSON payload The bash tool no longer inherits the parent process.env. Child processes receive a fixed allowlist (HOME, LANG, LC_ALL, LOGNAME, PATH, SHELL, TEMP, TERM, TMP, TMPDIR, USER), so provider API keys and similar secrets are no longer visible to spawned shells. The post-run dashboard no longer loads Tailwind CDN, Google Fonts, or Material Symbols at view time. The page is self-contained and renders without network access. llmMessagesToAiSdkModelMessages no longer concatenates the opaque redactedData payload into the reasoning text emitted to the AI SDK; it emits only the [redacted_thinking] marker. The MCP GitHub example uses --no-install instead of -y and passes an explicit env allowlist instead of spreading process.env. * fix(redaction): consume full value for quoted and unquoted assignments The single ASSIGNMENT_PATTERN stopped at the first whitespace inside a value, so values with spaces were only partially redacted and the remainder leaked into trace events, dashboard payloads, and the bash output buffer. Three reviewer-reported cases on PR #263: password=secret value -> password=[redacted] value password="secret value" -> password="[redacted]" value" apiKey: "abc def" -> apiKey: "[redacted]" def" Splits the single pattern into two passes. The quoted pass consumes to the back-referenced closing quote so password="my pass" is fully matched. The unquoted pass consumes to the next structural delimiter (comma, semicolon, brace, bracket, newline) so password=my pass is fully matched. Adds tests/redaction.test.ts covering the three reviewer cases, the existing Authorization orphan-bracket regression, common token literal patterns, and idempotence.
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
/**
|
|
* MCP GitHub Tools
|
|
*
|
|
* Connect an MCP server over stdio and register all exposed MCP tools as
|
|
* standard open-multi-agent tools.
|
|
*
|
|
* Run:
|
|
* npx tsx examples/integrations/mcp-github.ts
|
|
*
|
|
* Prerequisites:
|
|
* - GEMINI_API_KEY
|
|
* - GITHUB_TOKEN
|
|
* - @modelcontextprotocol/sdk installed
|
|
* - @modelcontextprotocol/server-github installed locally
|
|
*/
|
|
|
|
import { Agent, ToolExecutor, ToolRegistry, registerBuiltInTools } from '../../src/index.js'
|
|
import { connectMCPTools } from '../../src/mcp.js'
|
|
|
|
if (!process.env.GITHUB_TOKEN?.trim()) {
|
|
console.error('Missing GITHUB_TOKEN: set a GitHub personal access token in the environment.')
|
|
process.exit(1)
|
|
}
|
|
|
|
const { tools, disconnect } = await connectMCPTools({
|
|
command: 'npx',
|
|
args: ['--no-install', '@modelcontextprotocol/server-github'],
|
|
env: {
|
|
GITHUB_TOKEN: process.env.GITHUB_TOKEN,
|
|
HOME: process.env.HOME,
|
|
PATH: process.env.PATH,
|
|
TMPDIR: process.env.TMPDIR,
|
|
},
|
|
namePrefix: 'github',
|
|
})
|
|
|
|
const registry = new ToolRegistry()
|
|
registerBuiltInTools(registry)
|
|
for (const tool of tools) registry.register(tool)
|
|
const executor = new ToolExecutor(registry)
|
|
|
|
const agent = new Agent(
|
|
{
|
|
name: 'github-agent',
|
|
model: 'gemini-2.5-flash',
|
|
provider: 'gemini',
|
|
tools: tools.map((tool) => tool.name),
|
|
systemPrompt: 'Use GitHub MCP tools to answer repository questions.',
|
|
},
|
|
registry,
|
|
executor,
|
|
)
|
|
|
|
try {
|
|
const result = await agent.run(
|
|
'List the last 3 open issues in open-multi-agent/open-multi-agent with title and number.',
|
|
)
|
|
|
|
console.log(result.output)
|
|
} finally {
|
|
await disconnect()
|
|
}
|