Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/workflows/downloads-badge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Downloads Badge

# Computes all-time npm download totals for every published package and
# commits the result as shields.io "endpoint badge" JSON to a dedicated
# `badges` branch (not `main` — this keeps generated data out of main's
# history and off to the side of any branch protection rule on `main`).
# The README points a shields.io endpoint badge at the raw file on that
# branch.

on:
schedule:
- cron: "0 6 * * *" # daily, 06:00 UTC
workflow_dispatch: {}

permissions:
contents: write

env:
BADGES_DIR: .github/badges

jobs:
update-badge:
name: Update downloads badge data
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 24.x

- name: Compute total downloads
run: |
mkdir -p "$BADGES_DIR"
node -e '
const fs = require("fs");
const pkgs = ["@a2a-wrapper/core","a2a-claude","a2a-codex","a2a-copilot","a2a-opencode","a2a-antigravity"];
const fmt = d => d.toISOString().slice(0, 10);

// npm caps any single date range at ~18 months, so chunk from
// when npm download-stats data begins (2015-01-10) to today.
async function totalDownloads(pkg) {
const end = new Date();
let cursor = new Date("2015-01-10");
let total = 0;
while (cursor < end) {
const chunkEnd = new Date(Math.min(cursor.getTime() + 540 * 86400000, end.getTime()));
const url = `https://api.npmjs.org/downloads/point/${fmt(cursor)}:${fmt(chunkEnd)}/${encodeURIComponent(pkg)}`;
const res = await fetch(url);
const data = await res.json();
total += data.downloads ?? 0;
cursor = new Date(chunkEnd.getTime() + 86400000);
}
return total;
}

(async () => {
const perPackage = {};
let grand = 0;
for (const pkg of pkgs) {
const total = await totalDownloads(pkg);
perPackage[pkg] = total;
grand += total;
console.log(`${pkg}: ${total}`);
}
console.log(`TOTAL: ${grand}`);

const badge = {
schemaVersion: 1,
label: "downloads",
message: `${grand.toLocaleString()} total`,
color: "blue",
};
fs.writeFileSync(`${process.env.BADGES_DIR}/downloads.json`, JSON.stringify(badge, null, 2) + "\n");
fs.writeFileSync(
`${process.env.BADGES_DIR}/downloads-detail.json`,
JSON.stringify({ perPackage, grand, updatedAt: new Date().toISOString() }, null, 2) + "\n",
);
})();
'

- name: Commit and push to badges branch
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "$BADGES_DIR"
if git diff --cached --quiet; then
echo "Download counts unchanged; nothing to commit."
exit 0
fi
git commit -m "chore: update downloads badge data [skip ci]"
git push --force origin HEAD:badges
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# a2a-wrapper

[![CI](https://github.com/shashikanth-gs/a2a-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/shashikanth-gs/a2a-wrapper/actions/workflows/ci.yml)
[![Publish](https://github.com/shashikanth-gs/a2a-wrapper/actions/workflows/publish.yml/badge.svg)](https://github.com/shashikanth-gs/a2a-wrapper/actions/workflows/publish.yml)
[![Total Downloads](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/shashikanth-gs/a2a-wrapper/badges/.github/badges/downloads.json)](https://github.com/shashikanth-gs/a2a-wrapper/blob/badges/.github/badges/downloads-detail.json)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node.js >=20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)

Expand All @@ -14,16 +16,16 @@ A monorepo of [A2A protocol](https://a2a-protocol.org) wrappers that turn produc

## Packages

| Package | npm | Description |
|---|---|---|
| [`@a2a-wrapper/core`](packages/core/) | [![npm](https://img.shields.io/npm/v/@a2a-wrapper/core.svg)](https://www.npmjs.com/package/@a2a-wrapper/core) | Shared infrastructure — logging, config loading, event publishing, server factory, session management, CLI scaffold |
| [`a2a-copilot`](a2a-copilot/) | [![npm](https://img.shields.io/npm/v/a2a-copilot.svg)](https://www.npmjs.com/package/a2a-copilot) | A2A wrapper for GitHub Copilot SDK. Supports **Bring Your Own Model (BYOK)** — Ollama, OpenAI, Anthropic, Azure, vLLM, or any OpenAI-compatible endpoint |
| [`a2a-opencode`](a2a-opencode/) | [![npm](https://img.shields.io/npm/v/a2a-opencode.svg)](https://www.npmjs.com/package/a2a-opencode) | A2A wrapper for OpenCode — multi-provider out of the box (Anthropic, OpenAI, GitHub Copilot, and more) |
| [`a2a-claude`](a2a-claude/) | [![npm](https://img.shields.io/npm/v/a2a-claude.svg)](https://www.npmjs.com/package/a2a-claude) | A2A wrapper for Claude Code — fully spec-compliant agent powered by the official `@anthropic-ai/claude-agent-sdk` |
| [`a2a-codex`](a2a-codex/) | [![npm](https://img.shields.io/npm/v/a2a-codex.svg)](https://www.npmjs.com/package/a2a-codex) | A2A wrapper for OpenAI Codex SDK — repository-scoped software engineering agent with sandboxing, MCP, and multi-agent delegation |
| [`a2a-antigravity`](a2a-antigravity/) | [![npm](https://img.shields.io/npm/v/a2a-antigravity.svg)](https://www.npmjs.com/package/a2a-antigravity) | A2A wrapper for Google Antigravity SDK — Node/TypeScript public server with a managed Python SDK subprocess, Gemini auth, policies, MCP, and sideband traces |

`npm install <package>` always installs the latest stable release. Every package also publishes a `canary` build automatically after each merge to `main` that passes CI — install one with `npm install <package>@canary` to try an unreleased fix ahead of the next stable version. See each package's README for details, or [Release Process](CONTRIBUTING.md#release-process) for how the pipeline works.
| Package | Stable | Canary | Description |
|---|---|---|---|
| [`@a2a-wrapper/core`](packages/core/) | [![npm](https://img.shields.io/npm/v/@a2a-wrapper/core.svg)](https://www.npmjs.com/package/@a2a-wrapper/core) | [![canary](https://img.shields.io/npm/v/@a2a-wrapper/core/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/@a2a-wrapper/core/v/canary) | Shared infrastructure — logging, config loading, event publishing, server factory, session management, CLI scaffold |
| [`a2a-copilot`](a2a-copilot/) | [![npm](https://img.shields.io/npm/v/a2a-copilot.svg)](https://www.npmjs.com/package/a2a-copilot) | [![canary](https://img.shields.io/npm/v/a2a-copilot/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/a2a-copilot/v/canary) | A2A wrapper for GitHub Copilot SDK. Supports **Bring Your Own Model (BYOK)** — Ollama, OpenAI, Anthropic, Azure, vLLM, or any OpenAI-compatible endpoint |
| [`a2a-opencode`](a2a-opencode/) | [![npm](https://img.shields.io/npm/v/a2a-opencode.svg)](https://www.npmjs.com/package/a2a-opencode) | [![canary](https://img.shields.io/npm/v/a2a-opencode/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/a2a-opencode/v/canary) | A2A wrapper for OpenCode — multi-provider out of the box (Anthropic, OpenAI, GitHub Copilot, and more) |
| [`a2a-claude`](a2a-claude/) | [![npm](https://img.shields.io/npm/v/a2a-claude.svg)](https://www.npmjs.com/package/a2a-claude) | [![canary](https://img.shields.io/npm/v/a2a-claude/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/a2a-claude/v/canary) | A2A wrapper for Claude Code — fully spec-compliant agent powered by the official `@anthropic-ai/claude-agent-sdk` |
| [`a2a-codex`](a2a-codex/) | [![npm](https://img.shields.io/npm/v/a2a-codex.svg)](https://www.npmjs.com/package/a2a-codex) | [![canary](https://img.shields.io/npm/v/a2a-codex/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/a2a-codex/v/canary) | A2A wrapper for OpenAI Codex SDK — repository-scoped software engineering agent with sandboxing, MCP, and multi-agent delegation |
| [`a2a-antigravity`](a2a-antigravity/) | [![npm](https://img.shields.io/npm/v/a2a-antigravity.svg)](https://www.npmjs.com/package/a2a-antigravity) | [![canary](https://img.shields.io/npm/v/a2a-antigravity/canary.svg?label=canary&color=orange)](https://www.npmjs.com/package/a2a-antigravity/v/canary) | A2A wrapper for Google Antigravity SDK — Node/TypeScript public server with a managed Python SDK subprocess, Gemini auth, policies, MCP, and sideband traces |

Both badges are live — **Stable** reflects the latest approved release (`npm install <package>`), **Canary** reflects the most recent successful merge to `main` (`npm install <package>@canary`). See [Release Process](CONTRIBUTING.md#release-process) for how the pipeline works.

### Feature Comparison

Expand Down
Loading