mirror of
https://github.com/JackChen-me/open-multi-agent.git
synced 2026-10-19 01:29:57 -05:00
chore: migrate package to org scope
Prepare the @open-multi-agent/core@1.4.0 release and update GitHub/npm references for the org migration.
This commit is contained in:
1 parent
ebde758c53
commit
8bf80f2b9a
21 files changed
+93
-79
No files matched your search
@@ -5,7 +5,7 @@ Thanks for your interest in contributing to Open Multi-Agent! This guide covers
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/JackChen-me/open-multi-agent.git
|
||||
git clone https://github.com/open-multi-agent/open-multi-agent.git
|
||||
cd open-multi-agent
|
||||
npm install
|
||||
```
|
||||
@@ -65,7 +65,7 @@ See the [README](../README.md#architecture) for an architecture diagram. Key ent
|
||||
|
||||
## Where to Contribute
|
||||
|
||||
Check the [issues](https://github.com/JackChen-me/open-multi-agent/issues) page. Issues labeled `good first issue` are scoped and approachable. Issues labeled `help wanted` are larger but well-defined.
|
||||
Check the [issues](https://github.com/open-multi-agent/open-multi-agent/issues) page. Issues labeled `good first issue` are scoped and approachable. Issues labeled `help wanted` are larger but well-defined.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 76 KiB |
@@ -3,4 +3,4 @@
|
||||
<ellipse cx="230" cy="148" rx="32" ry="46" fill="rgb(16, 185, 129)" transform="matrix(0.939693, 0.34202, -0.34202, 0.939693, 64.4897, -69.7391)" color="rgb(245, 242, 235)" stroke="none"/>
|
||||
<circle cx="295" cy="118" r="7" fill="rgb(16, 185, 129)" color="rgb(245, 242, 235)" stroke="none"/>
|
||||
<circle cx="330" cy="100" r="3" fill="rgb(16, 185, 129)" opacity="0.5" color="rgb(245, 242, 235)" stroke="none"/>
|
||||
</g></g><g data-tag="span" id="gh-handle1" class="gh-handle" data-z-index="auto" data-stacking-context="true" aria-owns="accent1"><text color="rgb(160, 154, 142)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(160, 154, 142)"><tspan xml:space="preserve" x="281.546875" y="260.796875" textLength="126.375" lengthAdjust="spacingAndGlyphs">JackChen-me </tspan></text><g data-tag="span" id="accent1" class="accent" data-z-index="auto" data-stacking-context="true"><text color="rgb(16, 185, 129)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(16, 185, 129)"><tspan xml:space="preserve" x="407.921875" y="260.796875" textLength="10.53125" lengthAdjust="spacingAndGlyphs">/</tspan></text></g><text color="rgb(160, 154, 142)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(160, 154, 142)"><tspan xml:space="preserve" x="418.453125" y="260.796875" textLength="179.015625" lengthAdjust="spacingAndGlyphs"> open-multi-agent</tspan></text></g></g><g data-tag="div" id="gh-mid1" class="gh-mid" data-z-index="1" data-stacking-context="true" aria-owns="h41 p1"><g data-tag="h4" id="h41" data-z-index="auto" data-stacking-context="true" role="heading" aria-level="4" aria-owns="br1 accent2"><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="209.171875" y="447.328125" textLength="680.953125" lengthAdjust="spacingAndGlyphs">Three runtime deps.</tspan></text><g data-tag="br" id="br1" data-z-index="auto" data-stacking-context="true"/><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="209.171875" y="508.125" textLength="179.203125" lengthAdjust="spacingAndGlyphs">Zero </tspan></text><g data-tag="span" id="accent2" class="accent" data-z-index="auto" data-stacking-context="true"><text color="rgb(16, 185, 129)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(16, 185, 129)"><tspan xml:space="preserve" x="388.375" y="508.125" textLength="215.046875" lengthAdjust="spacingAndGlyphs">config</tspan></text></g><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="603.421875" y="508.125" textLength="35.84375" lengthAdjust="spacingAndGlyphs">.</tspan></text><Line truncated
|
||||
</g></g><g data-tag="span" id="gh-handle1" class="gh-handle" data-z-index="auto" data-stacking-context="true" aria-owns="accent1"><text color="rgb(160, 154, 142)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(160, 154, 142)"><tspan xml:space="preserve" x="281.546875" y="260.796875" textLength="179.015625" lengthAdjust="spacingAndGlyphs">open-multi-agent </tspan></text><g data-tag="span" id="accent1" class="accent" data-z-index="auto" data-stacking-context="true"><text color="rgb(16, 185, 129)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(16, 185, 129)"><tspan xml:space="preserve" x="460.5625" y="260.796875" textLength="10.53125" lengthAdjust="spacingAndGlyphs">/</tspan></text></g><text color="rgb(160, 154, 142)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="18px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="400" direction="ltr" letter-spacing="-0.27px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(160, 154, 142)"><tspan xml:space="preserve" x="471.09375" y="260.796875" textLength="179.015625" lengthAdjust="spacingAndGlyphs"> open-multi-agent</tspan></text></g></g><g data-tag="div" id="gh-mid1" class="gh-mid" data-z-index="1" data-stacking-context="true" aria-owns="h41 p1"><g data-tag="h4" id="h41" data-z-index="auto" data-stacking-context="true" role="heading" aria-level="4" aria-owns="br1 accent2"><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="209.171875" y="447.328125" textLength="680.953125" lengthAdjust="spacingAndGlyphs">Three runtime deps.</tspan></text><g data-tag="br" id="br1" data-z-index="auto" data-stacking-context="true"/><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="209.171875" y="508.125" textLength="179.203125" lengthAdjust="spacingAndGlyphs">Zero </tspan></text><g data-tag="span" id="accent2" class="accent" data-z-index="auto" data-stacking-context="true"><text color="rgb(16, 185, 129)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="normal" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(16, 185, 129)"><tspan xml:space="preserve" x="388.375" y="508.125" textLength="215.046875" lengthAdjust="spacingAndGlyphs">config</tspan></text></g><text color="rgb(245, 242, 235)" dominant-baseline="text-after-edge" font-family=""JetBrains Mono", ui-monospace, Menlo, monospace" font-size="64px" font-size-adjust="none" font-stretch="100%" font-style="normal" font-variant="normal" font-weight="500" direction="ltr" letter-spacing="-2.56px" text-decoration="none" text-anchor="start" text-rendering="auto" unicode-bidi="isolate" word-spacing="0px" writing-mode="horizontal-tb" user-select="auto" fill="rgb(245, 242, 235)"><tspan xml:space="preserve" x="603.421875" y="508.125" textLength="35.84375" lengthAdjust="spacingAndGlyphs">.</tspan></tLine truncated
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -54,7 +54,7 @@ This is the framework's key feature. When `runTeam()` is called:
|
||||
| Utils | `utils/semaphore.ts`, `utils/tokens.ts`, `utils/keywords.ts`, `utils/trace.ts` | Concurrency primitive, token accounting, keyword helpers, trace plumbing |
|
||||
| Errors | `errors.ts` | Shared error types |
|
||||
| Types | `types.ts` | All interfaces in one file to avoid circular deps |
|
||||
| Exports | `index.ts` (root, `'open-multi-agent'`), `mcp.ts` (subpath, `'open-multi-agent/mcp'`) | Public API surface; MCP integration is a separate entry point so non-MCP users don't pay the import cost |
|
||||
| Exports | `index.ts` (root, `'@open-multi-agent/core'`), `mcp.ts` (subpath, `'@open-multi-agent/core/mcp'`) | Public API surface; MCP integration is a separate entry point so non-MCP users don't pay the import cost |
|
||||
|
||||
### Agent Conversation Loop (AgentRunner)
|
||||
|
||||
@@ -98,7 +98,7 @@ Optional `maxRetries`, `retryDelayMs`, `retryBackoff` on task config (used via `
|
||||
|
||||
### MCP Integration
|
||||
|
||||
`connectMCPTools()` (in `tool/mcp.ts`) bridges Model Context Protocol servers into the `ToolRegistry`. Imported lazily and exposed via the dedicated `open-multi-agent/mcp` package subpath (`src/mcp.ts`) so users who don't need MCP don't load `@modelcontextprotocol/sdk`.
|
||||
`connectMCPTools()` (in `tool/mcp.ts`) bridges Model Context Protocol servers into the `ToolRegistry`. Imported lazily and exposed via the dedicated `@open-multi-agent/core/mcp` package subpath (`src/mcp.ts`) so users who don't need MCP don't load `@modelcontextprotocol/sdk`.
|
||||
|
||||
### Loop Detection
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-light.svg">
|
||||
<img alt="Open Multi-Agent" src="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-light.svg" width="96">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-light.svg">
|
||||
<img alt="Open Multi-Agent" src="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-light.svg" width="96">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
@@ -18,18 +18,18 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/@jackchen_me/open-multi-agent"><img src="https://img.shields.io/npm/v/@jackchen_me/open-multi-agent" alt="npm version"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/actions/workflows/ci.yml"><img src="https://github.com/JackChen-me/open-multi-agent/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/github/license/JackChen-me/open-multi-agent" alt="license"></a>
|
||||
<a href="https://www.npmjs.com/package/@open-multi-agent/core"><img src="https://img.shields.io/npm/v/@open-multi-agent/core" alt="npm version"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/actions/workflows/ci.yml"><img src="https://github.com/open-multi-agent/open-multi-agent/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License"></a>
|
||||
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.6-blue" alt="TypeScript"></a>
|
||||
<a href="https://codecov.io/gh/JackChen-me/open-multi-agent"><img src="https://codecov.io/gh/JackChen-me/open-multi-agent/graph/badge.svg" alt="codecov"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/blob/main/package.json"><img src="https://img.shields.io/badge/runtime_deps-3-brightgreen" alt="runtime deps"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/stargazers"><img src="https://img.shields.io/github/stars/JackChen-me/open-multi-agent" alt="GitHub stars"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/network/members"><img src="https://img.shields.io/github/forks/JackChen-me/open-multi-agent" alt="GitHub forks"></a>
|
||||
<a href="https://codecov.io/gh/open-multi-agent/open-multi-agent"><img src="https://codecov.io/gh/open-multi-agent/open-multi-agent/graph/badge.svg" alt="codecov"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/blob/main/package.json"><img src="https://img.shields.io/badge/runtime_deps-3-brightgreen" alt="runtime deps"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/stargazers"><img src="https://img.shields.io/github/stars/open-multi-agent/open-multi-agent" alt="GitHub stars"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/network/members"><img src="https://img.shields.io/github/forks/open-multi-agent/open-multi-agent" alt="GitHub forks"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/demo-dashboard-hero.gif" alt="Animated task DAG dashboard: coordinator decomposes a goal into tasks, executes them in parallel, and synthesizes the result — with token breakdown and agent output log" width="960" height="456" loading="eager">
|
||||
<img src="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/demo-dashboard-hero.gif" alt="Animated task DAG dashboard: coordinator decomposes a goal into tasks, executes them in parallel, and synthesizes the result — with token breakdown and agent output log" width="960" height="456" loading="eager">
|
||||
</p>
|
||||
|
||||
<br />
|
||||
@@ -42,6 +42,9 @@
|
||||
|
||||
`open-multi-agent` is a multi-agent orchestration framework for TypeScript backends. Give it a goal; a coordinator agent decomposes it into a task DAG, parallelizes independents, and synthesizes the result. Three runtime dependencies, drops into any Node.js backend.
|
||||
|
||||
> **Package update:** the official npm package is now `@open-multi-agent/core`.
|
||||
> The previous package, `@jackchen_me/open-multi-agent`, remains supported during the migration window.
|
||||
|
||||
> **Your engineers describe the goal, not the graph.**
|
||||
|
||||
## Quick Start
|
||||
@@ -51,11 +54,11 @@ Requires Node.js >= 18.
|
||||
### Use it in your project
|
||||
|
||||
```bash
|
||||
npm install @jackchen_me/open-multi-agent
|
||||
npm install @open-multi-agent/core
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { OpenMultiAgent, type AgentConfig } from '@jackchen_me/open-multi-agent'
|
||||
import { OpenMultiAgent, type AgentConfig } from '@open-multi-agent/core'
|
||||
|
||||
const agents: AgentConfig[] = [
|
||||
{ name: 'architect', model: 'claude-sonnet-4-6', systemPrompt: 'Design clean API contracts.', tools: ['file_write'] },
|
||||
@@ -77,7 +80,7 @@ console.log(result.success, result.totalTokenUsage.output_tokens)
|
||||
### Run an example locally
|
||||
|
||||
```bash
|
||||
git clone https://github.com/JackChen-me/open-multi-agent && cd open-multi-agent
|
||||
git clone https://github.com/open-multi-agent/open-multi-agent && cd open-multi-agent
|
||||
npm install
|
||||
export ANTHROPIC_API_KEY=sk-...
|
||||
npx tsx examples/basics/team-collaboration.ts
|
||||
@@ -188,14 +191,14 @@ A quick router. Mechanism breakdown follows.
|
||||
- **[temodar-agent](https://github.com/xeloxa/temodar-agent)** (~60 stars). WordPress security analysis platform by [Ali Sünbül](https://github.com/xeloxa). Uses our built-in tools (`bash`, `file_*`, `grep`) directly inside a Docker runtime. Confirmed production use.
|
||||
- **Cybersecurity SOC (home lab).** A private setup running Qwen 2.5 + DeepSeek Coder entirely offline via Ollama, building an autonomous SOC pipeline on Wazuh + Proxmox. Early user, not yet public.
|
||||
|
||||
Using `open-multi-agent` in production or a side project? [Open a discussion](https://github.com/JackChen-me/open-multi-agent/discussions) and we will list it here.
|
||||
Using `open-multi-agent` in production or a side project? [Open a discussion](https://github.com/open-multi-agent/open-multi-agent/discussions) and we will list it here.
|
||||
|
||||
### Integrations
|
||||
|
||||
- **[Engram](https://www.engram-memory.com)** — "Git for AI memory." Syncs knowledge across agents instantly and flags conflicts. ([repo](https://github.com/Agentscreator/engram-memory))
|
||||
- **[@agentsonar/oma](https://github.com/agentsonar/agentsonar-oma)** — Sidecar detecting cross-run delegation cycles, repetition, and rate bursts.
|
||||
|
||||
Built an integration? [Open a discussion](https://github.com/JackChen-me/open-multi-agent/discussions) to get listed.
|
||||
Built an integration? [Open a discussion](https://github.com/open-multi-agent/open-multi-agent/discussions) to get listed.
|
||||
|
||||
### Featured partner
|
||||
|
||||
@@ -296,12 +299,12 @@ Issues, feature requests, and PRs are welcome. Some areas where contributions wo
|
||||
|
||||
- **Production examples.** Real-world end-to-end workflows. See [`examples/production/README.md`](./examples/production/README.md) for the acceptance criteria and submission format.
|
||||
- **Documentation.** Guides, tutorials, and API docs.
|
||||
- **Translations.** Help translate this README into other languages. [Open a PR](https://github.com/JackChen-me/open-multi-agent/pulls).
|
||||
- **Translations.** Help translate this README into other languages. [Open a PR](https://github.com/open-multi-agent/open-multi-agent/pulls).
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent&max=100&v=20260507" />
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=open-multi-agent/open-multi-agent&max=100&v=20260507" />
|
||||
</a>
|
||||
|
||||
<details>
|
||||
@@ -357,11 +360,11 @@ Issues, feature requests, and PRs are welcome. Some areas where contributions wo
|
||||
|
||||
## Star History
|
||||
|
||||
<a href="https://star-history.com/#JackChen-me/open-multi-agent&Date">
|
||||
<a href="https://star-history.com/#open-multi-agent/open-multi-agent&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260425" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260425" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260425" />
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&theme=dark&v=20260425" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&v=20260425" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&v=20260425" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
|
||||
+26
-23
@@ -2,9 +2,9 @@
|
||||
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-light.svg">
|
||||
<img alt="Open Multi-Agent" src="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/logo-mark-light.svg" width="96">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-light.svg">
|
||||
<img alt="Open Multi-Agent" src="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/logo-mark-light.svg" width="96">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
@@ -18,18 +18,18 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/@jackchen_me/open-multi-agent"><img src="https://img.shields.io/npm/v/@jackchen_me/open-multi-agent" alt="npm version"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/actions/workflows/ci.yml"><img src="https://github.com/JackChen-me/open-multi-agent/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/github/license/JackChen-me/open-multi-agent" alt="license"></a>
|
||||
<a href="https://www.npmjs.com/package/@open-multi-agent/core"><img src="https://img.shields.io/npm/v/@open-multi-agent/core" alt="npm version"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/actions/workflows/ci.yml"><img src="https://github.com/open-multi-agent/open-multi-agent/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License"></a>
|
||||
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.6-blue" alt="TypeScript"></a>
|
||||
<a href="https://codecov.io/gh/JackChen-me/open-multi-agent"><img src="https://codecov.io/gh/JackChen-me/open-multi-agent/graph/badge.svg" alt="codecov"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/blob/main/package.json"><img src="https://img.shields.io/badge/runtime_deps-3-brightgreen" alt="runtime deps"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/stargazers"><img src="https://img.shields.io/github/stars/JackChen-me/open-multi-agent" alt="GitHub stars"></a>
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/network/members"><img src="https://img.shields.io/github/forks/JackChen-me/open-multi-agent" alt="GitHub forks"></a>
|
||||
<a href="https://codecov.io/gh/open-multi-agent/open-multi-agent"><img src="https://codecov.io/gh/open-multi-agent/open-multi-agent/graph/badge.svg" alt="codecov"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/blob/main/package.json"><img src="https://img.shields.io/badge/runtime_deps-3-brightgreen" alt="runtime deps"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/stargazers"><img src="https://img.shields.io/github/stars/open-multi-agent/open-multi-agent" alt="GitHub stars"></a>
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/network/members"><img src="https://img.shields.io/github/forks/open-multi-agent/open-multi-agent" alt="GitHub forks"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/JackChen-me/open-multi-agent/main/.github/brand/demo-dashboard-hero.gif" alt="Animated task DAG dashboard: coordinator decomposes a goal into tasks, executes them in parallel, and synthesizes the result — with token breakdown and agent output log" width="960" height="456" loading="eager">
|
||||
<img src="https://raw.githubusercontent.com/open-multi-agent/open-multi-agent/main/.github/brand/demo-dashboard-hero.gif" alt="Animated task DAG dashboard: coordinator decomposes a goal into tasks, executes them in parallel, and synthesizes the result — with token breakdown and agent output log" width="960" height="456" loading="eager">
|
||||
</p>
|
||||
|
||||
<br />
|
||||
@@ -42,6 +42,9 @@
|
||||
|
||||
`open-multi-agent` 是面向 TypeScript 后端的多智能体编排框架。给定一个目标,协调者 agent 会将其拆解为任务 DAG,并行执行独立任务,合成最终结果。仅 3 个运行时依赖,可直接嵌入任意现有 Node.js 后端。
|
||||
|
||||
> **包名更新:** 官方 npm 包已迁移到 `@open-multi-agent/core`。
|
||||
> 旧包 `@jackchen_me/open-multi-agent` 在迁移窗口内继续支持。
|
||||
|
||||
> **工程师只描述目标,不画任务图。**
|
||||
|
||||
## 快速开始
|
||||
@@ -51,11 +54,11 @@
|
||||
### 在你的项目里使用
|
||||
|
||||
```bash
|
||||
npm install @jackchen_me/open-multi-agent
|
||||
npm install @open-multi-agent/core
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { OpenMultiAgent, type AgentConfig } from '@jackchen_me/open-multi-agent'
|
||||
import { OpenMultiAgent, type AgentConfig } from '@open-multi-agent/core'
|
||||
|
||||
const agents: AgentConfig[] = [
|
||||
{ name: 'architect', model: 'claude-sonnet-4-6', systemPrompt: 'Design clean API contracts.', tools: ['file_write'] },
|
||||
@@ -77,7 +80,7 @@ console.log(result.success, result.totalTokenUsage.output_tokens)
|
||||
### 本地试跑
|
||||
|
||||
```bash
|
||||
git clone https://github.com/JackChen-me/open-multi-agent && cd open-multi-agent
|
||||
git clone https://github.com/open-multi-agent/open-multi-agent && cd open-multi-agent
|
||||
npm install
|
||||
export ANTHROPIC_API_KEY=sk-...
|
||||
npx tsx examples/basics/team-collaboration.ts
|
||||
@@ -188,14 +191,14 @@ Shell 和 CI 场景使用 JSON-first 的 `oma` 命令行工具。详见 [docs/cl
|
||||
- **[temodar-agent](https://github.com/xeloxa/temodar-agent)**(约 60 stars)。WordPress 安全分析平台,作者 [Ali Sünbül](https://github.com/xeloxa)。在 Docker runtime 里直接用我们的内置工具(`bash`、`file_*`、`grep`)。已确认生产环境使用。
|
||||
- **家用服务器 Cybersecurity SOC。** 本地完全离线跑 Qwen 2.5 + DeepSeek Coder(通过 Ollama),在 Wazuh + Proxmox 上搭自主 SOC 流水线。早期用户,未公开。
|
||||
|
||||
如果在生产或 side project 中使用了 `open-multi-agent`,[请开个 Discussion](https://github.com/JackChen-me/open-multi-agent/discussions),我们会将其列在这里。
|
||||
如果在生产或 side project 中使用了 `open-multi-agent`,[请开个 Discussion](https://github.com/open-multi-agent/open-multi-agent/discussions),我们会将其列在这里。
|
||||
|
||||
### 集成
|
||||
|
||||
- **[Engram](https://www.engram-memory.com)** — "Git for AI memory." Syncs knowledge across agents instantly and flags conflicts. ([repo](https://github.com/Agentscreator/engram-memory))
|
||||
- **[@agentsonar/oma](https://github.com/agentsonar/agentsonar-oma)** — Sidecar detecting cross-run delegation cycles, repetition, and rate bursts.
|
||||
|
||||
做了 `open-multi-agent` 集成?[开个 Discussion](https://github.com/JackChen-me/open-multi-agent/discussions),我们会将其列在这里。
|
||||
做了 `open-multi-agent` 集成?[开个 Discussion](https://github.com/open-multi-agent/open-multi-agent/discussions),我们会将其列在这里。
|
||||
|
||||
### Featured partner
|
||||
|
||||
@@ -297,12 +300,12 @@ Issue、feature request、PR 都欢迎。特别欢迎以下方面的贡献:
|
||||
|
||||
- **生产级示例。** 端到端跑通的真实场景工作流。收录条件和提交格式见 [`examples/production/README.md`](./examples/production/README.md)。
|
||||
- **文档。** 指南、教程、API 文档。
|
||||
- **翻译。** 把这份 README 翻译成其他语言。[提个 PR](https://github.com/JackChen-me/open-multi-agent/pulls)。
|
||||
- **翻译。** 把这份 README 翻译成其他语言。[提个 PR](https://github.com/open-multi-agent/open-multi-agent/pulls)。
|
||||
|
||||
## 贡献者
|
||||
|
||||
<a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent&max=100&v=20260507" />
|
||||
<a href="https://github.com/open-multi-agent/open-multi-agent/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=open-multi-agent/open-multi-agent&max=100&v=20260507" />
|
||||
</a>
|
||||
|
||||
<details>
|
||||
@@ -358,11 +361,11 @@ Issue、feature request、PR 都欢迎。特别欢迎以下方面的贡献:
|
||||
|
||||
## Star 趋势
|
||||
|
||||
<a href="https://star-history.com/#JackChen-me/open-multi-agent&Date">
|
||||
<a href="https://star-history.com/#open-multi-agent/open-multi-agent&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260425" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260425" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260425" />
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&theme=dark&v=20260425" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&v=20260425" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=open-multi-agent/open-multi-agent&type=Date&v=20260425" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ It does **not** provide an interactive REPL, working-directory injection into to
|
||||
After installing the package, the binary is on `PATH` when using `npx` or a local `node_modules/.bin`:
|
||||
|
||||
```bash
|
||||
npm install @jackchen_me/open-multi-agent
|
||||
npm install @open-multi-agent/core
|
||||
npx oma help
|
||||
```
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ $3,000 USD per partner per 12-month placement. Single partner per slot at a time
|
||||
|
||||
## How to apply
|
||||
|
||||
[Open an inquiry issue](https://github.com/JackChen-me/open-multi-agent/issues/new?title=Featured+Partner+Inquiry&labels=featured-partner-inquiry) with:
|
||||
[Open an inquiry issue](https://github.com/open-multi-agent/open-multi-agent/issues/new?title=Featured+Partner+Inquiry&labels=featured-partner-inquiry) with:
|
||||
|
||||
- A short description of your product and how it integrates with `open-multi-agent`.
|
||||
- A link to the integration code or live deployment.
|
||||
|
||||
@@ -36,7 +36,7 @@ Forward trace spans to OpenTelemetry, Datadog, Honeycomb, Langfuse, or your own
|
||||
|
||||
```typescript
|
||||
import { writeFileSync } from 'node:fs'
|
||||
import { renderTeamRunDashboard } from '@jackchen_me/open-multi-agent'
|
||||
import { renderTeamRunDashboard } from '@open-multi-agent/core'
|
||||
|
||||
const result = await orchestrator.runTeam(team, goal)
|
||||
writeFileSync('run.html', renderTeamRunDashboard(result))
|
||||
|
||||
@@ -13,7 +13,7 @@ const team = orchestrator.createTeam('research-team', {
|
||||
For durable or cross-process backends (Redis, Postgres, Engram, etc.), implement the `MemoryStore` interface and pass it via `sharedMemoryStore`. Keys are still namespaced as `<agentName>/<key>` before reaching the store:
|
||||
|
||||
```typescript
|
||||
import type { MemoryStore } from '@jackchen_me/open-multi-agent'
|
||||
import type { MemoryStore } from '@open-multi-agent/core'
|
||||
|
||||
class RedisStore implements MemoryStore { /* get/set/list/delete/clear */ }
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ Two ways to give an agent a tool that is not in the built-in set.
|
||||
**Inject at config time** via `customTools` on `AgentConfig`. Good when the orchestrator wires up tools centrally. Tools defined here bypass preset/allowlist filtering but still respect `disallowedTools`.
|
||||
|
||||
```typescript
|
||||
import { defineTool } from '@jackchen_me/open-multi-agent'
|
||||
import { defineTool } from '@open-multi-agent/core'
|
||||
import { z } from 'zod'
|
||||
|
||||
const weatherTool = defineTool({
|
||||
@@ -130,7 +130,7 @@ const agent: AgentConfig = {
|
||||
`open-multi-agent` can connect to stdio MCP servers and expose their tools directly to agents.
|
||||
|
||||
```typescript
|
||||
import { connectMCPTools } from '@jackchen_me/open-multi-agent/mcp'
|
||||
import { connectMCPTools } from '@open-multi-agent/core/mcp'
|
||||
|
||||
const { tools, disconnect } = await connectMCPTools({
|
||||
command: 'npx',
|
||||
|
||||
@@ -50,7 +50,7 @@ const agent = new Agent(
|
||||
|
||||
try {
|
||||
const result = await agent.run(
|
||||
'List the last 3 open issues in JackChen-me/open-multi-agent with title and number.',
|
||||
'List the last 3 open issues in open-multi-agent/open-multi-agent with title and number.',
|
||||
)
|
||||
|
||||
console.log(result.output)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { streamText, convertToModelMessages, type UIMessage } from 'ai'
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible'
|
||||
import { OpenMultiAgent } from '@jackchen_me/open-multi-agent'
|
||||
import type { AgentConfig } from '@jackchen_me/open-multi-agent'
|
||||
import { OpenMultiAgent } from '@open-multi-agent/core'
|
||||
import type { AgentConfig } from '@open-multi-agent/core'
|
||||
|
||||
export const maxDuration = 120
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextConfig } from 'next'
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
serverExternalPackages: ['@jackchen_me/open-multi-agent'],
|
||||
serverExternalPackages: ['@open-multi-agent/core'],
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
+9
-4
@@ -8,7 +8,7 @@
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai-compatible": "^2.0.41",
|
||||
"@ai-sdk/react": "^3.0.0",
|
||||
"@jackchen_me/open-multi-agent": "file:../../",
|
||||
"@open-multi-agent/core": "file:../../",
|
||||
"ai": "^6.0.0",
|
||||
"next": "^16.0.0",
|
||||
"react": "^19.0.0",
|
||||
@@ -22,8 +22,8 @@
|
||||
}
|
||||
},
|
||||
"../..": {
|
||||
"name": "@jackchen_me/open-multi-agent",
|
||||
"version": "1.1.0",
|
||||
"name": "@open-multi-agent/core",
|
||||
"version": "1.4.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.52.0",
|
||||
@@ -34,6 +34,7 @@
|
||||
"oma": "dist/cli/oma.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.1040.0",
|
||||
"@google/genai": "^1.48.0",
|
||||
"@modelcontextprotocol/sdk": "^1.18.0",
|
||||
"@types/node": "^22.0.0",
|
||||
@@ -46,10 +47,14 @@
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.700.0",
|
||||
"@google/genai": "^1.48.0",
|
||||
"@modelcontextprotocol/sdk": "^1.18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@aws-sdk/client-bedrock-runtime": {
|
||||
"optional": true
|
||||
},
|
||||
"@google/genai": {
|
||||
"optional": true
|
||||
},
|
||||
@@ -614,7 +619,7 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@jackchen_me/open-multi-agent": {
|
||||
"node_modules/@open-multi-agent/core": {
|
||||
"resolved": "../..",
|
||||
"link": true
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai-compatible": "^2.0.41",
|
||||
"@ai-sdk/react": "^3.0.0",
|
||||
"@jackchen_me/open-multi-agent": "file:../../",
|
||||
"@open-multi-agent/core": "file:../../",
|
||||
"ai": "^6.0.0",
|
||||
"next": "^16.0.0",
|
||||
"react": "^19.0.0",
|
||||
|
||||
Generated
+4
-4
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@jackchen_me/open-multi-agent",
|
||||
"version": "1.3.1",
|
||||
"name": "@open-multi-agent/core",
|
||||
"version": "1.4.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@jackchen_me/open-multi-agent",
|
||||
"version": "1.3.1",
|
||||
"name": "@open-multi-agent/core",
|
||||
"version": "1.4.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.52.0",
|
||||
|
||||
+8
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@jackchen_me/open-multi-agent",
|
||||
"version": "1.3.1",
|
||||
"name": "@open-multi-agent/core",
|
||||
"version": "1.4.0",
|
||||
"description": "TypeScript multi-agent framework — one runTeam() call from goal to result. Auto task decomposition, parallel execution. 3 dependencies, deploys anywhere Node.js runs.",
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -8,6 +8,9 @@
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -50,11 +53,11 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/JackChen-me/open-multi-agent.git"
|
||||
"url": "git+https://github.com/open-multi-agent/open-multi-agent.git"
|
||||
},
|
||||
"homepage": "https://github.com/JackChen-me/open-multi-agent#readme",
|
||||
"homepage": "https://github.com/open-multi-agent/open-multi-agent#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/JackChen-me/open-multi-agent/issues"
|
||||
"url": "https://github.com/open-multi-agent/open-multi-agent/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Agent, ToolRegistry, ToolExecutor, registerBuiltInTools } from 'open-multi-agent'
|
||||
* import { Agent, ToolRegistry, ToolExecutor, registerBuiltInTools } from '@open-multi-agent/core'
|
||||
*
|
||||
* const registry = new ToolRegistry()
|
||||
* registerBuiltInTools(registry)
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* @fileoverview open-multi-agent — public API surface.
|
||||
*
|
||||
* Import from `'open-multi-agent'` to access everything you need:
|
||||
* Import from `'@open-multi-agent/core'` to access everything you need:
|
||||
*
|
||||
* ```ts
|
||||
* import { OpenMultiAgent, Agent, Team, defineTool } from 'open-multi-agent'
|
||||
* import { OpenMultiAgent, Agent, Team, defineTool } from '@open-multi-agent/core'
|
||||
* ```
|
||||
*
|
||||
* ## Quickstart
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Requires: ANTHROPIC_API_KEY environment variable
|
||||
*
|
||||
* Reproducer: https://github.com/CodingBangboo/open-multi-agent/blob/planOnly_with_examples/examples/basics/plan-only-dag_stress_test.ts
|
||||
* Issue: https://github.com/JackChen-me/open-multi-agent/issues/208
|
||||
* Issue: https://github.com/open-multi-agent/open-multi-agent/issues/208
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { OpenMultiAgent } from '../../src/orchestrator/orchestrator.js'
|
||||
|
||||
Reference in new issue
Block a user