fix(plugins): make the 10 focused plugins installable, finish the AgentHub rename
The ten `agenthub-*` plugins were listed by the marketplace but could never be
installed — two schema mistakes present since the entries were first authored
(57dc915), both invisible until you actually run `claude plugin install`:
- marketplace entries used `"path": "plugins/<name>"`; the CLI only accepts
`"source"`, so every one failed with
`This plugin's marketplace entry is invalid: source: Invalid input`
- each `plugin.json` carried npm's `"repository": { "type", "url" }` object;
the schema wants a plain string, so the next attempt failed with
`Validation errors: repository: Invalid input`
Verified by installing all 11 entries into a throwaway CLAUDE_CONFIG_DIR:
1/11 before, 11/11 after. `plugins-marketplace.test.js` was asserting the
broken shape, which is why CI stayed green — it now asserts `source` and
rejects `path`.
Marketplace renamed `claude-code-agent-monitor-plugins` -> `agenthub`, so the
install line is `agenthub@agenthub`. ARCHITECTURE.md documented a marketplace
name (`smartgift-claude-code-monitor`) that never existed in any revision.
The documented `/plugin marketplace add Smartgift-AI/Claude-Code-Monitor` also
never worked: the `owner/repo` shorthand resolves to github.com only, and this
repo is self-hosted on Gitea. Confirmed the CLI rejects `host/owner/repo` and
ignores GH_HOST / GITHUB_HOST / CLAUDE_CODE_MARKETPLACE_URL, so the full
https:// clone URL is the only supported form. Same GitHub-habit class fixed
elsewhere: raw.githubusercontent.com icon URLs (404, and the repo ships
favicon.svg not favicon.ico — the client had the same dead /favicon.ico),
a smartgift.github.io docs link (404), and Gitea `/blob/<ref>/` paths that
must be `/src/branch/<ref>/`.
Repository renamed to Smartgift-AI/AgentHub throughout. Gitea 301-redirects
the old name, so these were stale rather than broken; `docs/superpowers/`
keeps the old name because those are dated decision records.
Adds `repo-links.test.js` to guard both classes (it runs under the existing
pre-commit gate) plus an openapi.yaml drift check — the committed spec had
silently fallen a minor version behind package.json. `generate-openapi-yaml.js`
now exports `render()` so the test compares against one definition of the dump
options instead of a second copy.
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "claude-code-agent-monitor-plugins",
|
||||
"name": "agenthub",
|
||||
"description": "Official plugin marketplace for AgentHub — the `agenthub` plugin installs the dashboard itself (hooks, server, CLI), plus 10 focused plugins for analytics, cost guardrails, productivity, developer tools, AI insights, session forensics, workflow/fleet intelligence, reliability/SLOs, config & memory governance, and dashboard connectivity. Every plugin is powered by the local Agent Monitor API.",
|
||||
"owner": {
|
||||
"name": "smartgift",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "agenthub",
|
||||
@@ -16,61 +16,61 @@
|
||||
},
|
||||
{
|
||||
"name": "agenthub-analytics",
|
||||
"path": "plugins/agenthub-analytics",
|
||||
"source": "./plugins/agenthub-analytics",
|
||||
"description": "Deep analytics on Claude Code sessions — token usage (total_input/total_output/total_cache_read/total_cache_write with compaction baselines pre-summed), cost breakdowns via the pricing engine, usage trends over 365 days, cache efficiency, model mix, and productivity scoring.",
|
||||
"tags": ["analytics", "tokens", "cost", "productivity"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-cost-guard",
|
||||
"path": "plugins/agenthub-cost-guard",
|
||||
"source": "./plugins/agenthub-cost-guard",
|
||||
"description": "Budget guardrails — set spend limits, forecast week/month-end cost from daily trends, surface cost-threshold alerts via the alert-rule API, and quantify model-routing savings.",
|
||||
"tags": ["budget", "cost", "forecast", "alerts"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-productivity",
|
||||
"path": "plugins/agenthub-productivity",
|
||||
"source": "./plugins/agenthub-productivity",
|
||||
"description": "Productivity automation — daily standups, weekly/monthly reviews, sprint summaries, time-of-day focus analysis, and workflow optimization using the workflow intelligence API's 11 datasets.",
|
||||
"tags": ["productivity", "reports", "workflows", "standup"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-devtools",
|
||||
"path": "plugins/agenthub-devtools",
|
||||
"source": "./plugins/agenthub-devtools",
|
||||
"description": "Developer tools for the Agent Monitor — session debugging with full event-chain inspection, data-integrity inspection, event tracing, transcript search, hook diagnostics, data export (JSON/CSV/Markdown), and system health checks.",
|
||||
"tags": ["devtools", "debug", "diagnostics", "export"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-insights",
|
||||
"path": "plugins/agenthub-insights",
|
||||
"source": "./plugins/agenthub-insights",
|
||||
"description": "AI-powered insights — pattern detection via workflow intelligence (tool flow transitions, agent co-occurrence), anomaly alerting, trend forecasting, regression watch, benchmarking, optimization recommendations, and session comparison.",
|
||||
"tags": ["insights", "patterns", "anomaly", "optimization"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-sessions",
|
||||
"path": "plugins/agenthub-sessions",
|
||||
"source": "./plugins/agenthub-sessions",
|
||||
"description": "Session forensics — search by project/model/status, reconstruct event timelines, replay transcripts turn-by-turn, roll up activity per working directory, and review stale sessions before cleanup.",
|
||||
"tags": ["sessions", "search", "transcript", "replay"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-workflows",
|
||||
"path": "plugins/agenthub-workflows",
|
||||
"source": "./plugins/agenthub-workflows",
|
||||
"description": "Multi-agent orchestration & fleet intelligence — map the subagent DAG, audit model delegation and effectiveness, report concurrency lanes, trace error propagation by depth, and review Workflow-tool fleet runs.",
|
||||
"tags": ["workflows", "orchestration", "subagents", "fleet"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-quality",
|
||||
"path": "plugins/agenthub-quality",
|
||||
"source": "./plugins/agenthub-quality",
|
||||
"description": "Reliability & SLOs — scan for API errors and tool failures, audit hook delivery health (PreToolUse/PostToolUse balance), track completion/error-rate SLOs with error budgets, and alert on reliability regressions.",
|
||||
"tags": ["reliability", "errors", "slo", "quality"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-config",
|
||||
"path": "plugins/agenthub-config",
|
||||
"source": "./plugins/agenthub-config",
|
||||
"description": "Claude Code config & memory governance — audit skills/subagents/commands/MCP servers/hooks/settings via the Config Explorer API and curate the file-based memory store (CLAUDE.md + per-project auto-memory files).",
|
||||
"tags": ["config", "memory", "governance", "mcp"]
|
||||
},
|
||||
{
|
||||
"name": "agenthub-dashboard",
|
||||
"path": "plugins/agenthub-dashboard",
|
||||
"source": "./plugins/agenthub-dashboard",
|
||||
"description": "Dashboard connector — quick status checks, one-line metrics, live activity watch, and endpoint probing against the Agent Monitor API.",
|
||||
"tags": ["dashboard", "status", "connector"]
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git",
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["dashboard", "monitoring", "sessions", "cost", "lanes", "claude-code"],
|
||||
"commands": [
|
||||
|
||||
+3
-3
@@ -1779,7 +1779,7 @@ Skills are namespaced: `/agenthub-analytics:session-report`, `/agenthub-producti
|
||||
| **agenthub-config** | `config-audit`, `memory-review`, `skill-inventory`, `mcp-audit`, `hook-inventory` | `config-auditor` | — | — |
|
||||
| **agenthub-dashboard** | `dashboard-status`, `quick-stats` | — | — | — |
|
||||
|
||||
**Totals**: 10 plugins, 53 skills, 14 agents, 30 slash commands, 3 CLI tools, 3 hook configurations. Each plugin is installable via `claude plugin install <name>@smartgift-claude-code-monitor`, and a server test (`server/__tests__/plugins-marketplace.test.js`) validates the marketplace↔directory bijection plus every `plugin.json`, agent, skill, and command.
|
||||
**Totals**: 10 plugins, 53 skills, 14 agents, 30 slash commands, 3 CLI tools, 3 hook configurations. Each plugin is installable via `claude plugin install <name>@agenthub`, and a server test (`server/__tests__/plugins-marketplace.test.js`) validates the marketplace↔directory bijection plus every `plugin.json`, agent, skill, and command.
|
||||
|
||||
### Data Model Grounding
|
||||
|
||||
@@ -1808,8 +1808,8 @@ Plugins compute these from raw API data:
|
||||
|
||||
```bash
|
||||
# Marketplace install
|
||||
claude plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
claude plugin install agenthub-analytics@smartgift-claude-code-monitor
|
||||
claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
claude plugin install agenthub-analytics@agenthub
|
||||
|
||||
# Local development testing
|
||||
claude --plugin-dir plugins/agenthub-analytics
|
||||
|
||||
+4
-4
@@ -7,8 +7,8 @@ A step-by-step guide to get AgentHub — the local control surface for Claude Co
|
||||
If all you want is a working dashboard, skip every step below. From Claude Code:
|
||||
|
||||
```
|
||||
/plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
/plugin install agenthub@claude-code-agent-monitor-plugins
|
||||
/plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
/plugin install agenthub@agenthub
|
||||
```
|
||||
|
||||
The next session start installs the hooks, boots the server, puts the `agenthub` CLI
|
||||
@@ -39,8 +39,8 @@ dashboard, run it from source, or stay on Node 20.
|
||||
## Step 1 — Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git
|
||||
cd Claude-Code-Monitor
|
||||
git clone https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
cd AgentHub
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -68,8 +68,8 @@ Two commands on a machine that has nothing but Claude Code, no clone and no
|
||||
`npm run setup`:
|
||||
|
||||
```
|
||||
/plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
/plugin install agenthub@claude-code-agent-monitor-plugins
|
||||
/plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
/plugin install agenthub@agenthub
|
||||
```
|
||||
|
||||
The first session start installs the hooks, boots the server, puts `agenthub` on
|
||||
|
||||
+2
-2
@@ -41,8 +41,8 @@ Hai lệnh, trên máy chỉ có Claude Code, không cần clone repo, không c
|
||||
`npm run setup`:
|
||||
|
||||
```
|
||||
/plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
/plugin install agenthub@claude-code-agent-monitor-plugins
|
||||
/plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
/plugin install agenthub@agenthub
|
||||
```
|
||||
|
||||
Lần session-start đầu tiên sẽ cài hooks, boot server, đưa `agenthub` vào PATH và
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@
|
||||
"name": "SmartGift",
|
||||
"url": "https://smartgift.vn"
|
||||
},
|
||||
"codeRepository": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"codeRepository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"featureList": "Real-time dashboard, Kanban board, Session tracking, Activity feed, Token usage analytics, Cost tracking, Browser notifications, WebSocket live updates, CLI statusline"
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -123,9 +123,9 @@ async function notify(title: string, body: string) {
|
||||
try {
|
||||
if ("serviceWorker" in navigator) {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
await registration.showNotification(title, { body, icon: "/favicon.ico", silent: false });
|
||||
await registration.showNotification(title, { body, icon: "/favicon.svg", silent: false });
|
||||
} else {
|
||||
new Notification(title, { body, icon: "/favicon.ico" });
|
||||
new Notification(title, { body, icon: "/favicon.svg" });
|
||||
}
|
||||
} catch {
|
||||
// Silently ignore
|
||||
|
||||
@@ -127,9 +127,7 @@ describe("agentOriginLabel - parent chain walk", () => {
|
||||
|
||||
describe("projectFromCwd - session-cwd fallback for the dir prefix", () => {
|
||||
it("returns the last path segment of a POSIX cwd", () => {
|
||||
expect(projectFromCwd("/Users/dev/WebstormProjects/Claude-Code-Agent-Monitor")).toBe(
|
||||
"Claude-Code-Agent-Monitor"
|
||||
);
|
||||
expect(projectFromCwd("/Users/dev/WebstormProjects/AgentHub")).toBe("AgentHub");
|
||||
});
|
||||
|
||||
it("ignores a trailing slash", () => {
|
||||
|
||||
@@ -1235,7 +1235,7 @@ export interface UpdateStatusPayload {
|
||||
* Drives whether the "Update available" call-to-action is shown. */
|
||||
update_available: boolean;
|
||||
/** Absolute path to the detected git repository root. Example:
|
||||
* `"/Users/dev/Claude-Code-Agent-Monitor"`. */
|
||||
* `"/Users/dev/AgentHub"`. */
|
||||
repo_root?: string;
|
||||
/** Resolved ref compared against, e.g. "upstream/master" or "origin/main";
|
||||
* null when no remote could be resolved (e.g. no remotes configured). */
|
||||
|
||||
+2
-2
@@ -53,8 +53,8 @@ flowchart LR
|
||||
`npm run setup` ends with a fail-soft `npm link` (the `link-cli` script), so after a normal local setup `agenthub` is on your PATH from any directory:
|
||||
|
||||
```bash
|
||||
git clone https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git
|
||||
cd Claude-Code-Agent-Monitor
|
||||
git clone https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
cd AgentHub
|
||||
npm run setup # installs deps AND links agenthub globally
|
||||
agenthub help
|
||||
```
|
||||
|
||||
+23
-16
@@ -9,13 +9,13 @@ Every plugin is powered by the local Agent Monitor REST API at `http://localhost
|
||||
### Add the marketplace
|
||||
|
||||
```bash
|
||||
claude plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
```
|
||||
|
||||
### Install the dashboard itself
|
||||
|
||||
```bash
|
||||
claude plugin install agenthub@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub@agenthub
|
||||
```
|
||||
|
||||
That is the whole install: no clone, no `npm run setup`, no `npm run install-hooks`, no manual `npm start`. See [The `agenthub` plugin](#the-agenthub-plugin) below for what it does on first session start.
|
||||
@@ -39,16 +39,16 @@ marketplace name, not per source).
|
||||
### Install a focused plugin
|
||||
|
||||
```bash
|
||||
claude plugin install agenthub-analytics@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-cost-guard@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-productivity@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-devtools@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-insights@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-sessions@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-workflows@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-quality@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-config@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-dashboard@claude-code-agent-monitor-plugins
|
||||
claude plugin install agenthub-analytics@agenthub
|
||||
claude plugin install agenthub-cost-guard@agenthub
|
||||
claude plugin install agenthub-productivity@agenthub
|
||||
claude plugin install agenthub-devtools@agenthub
|
||||
claude plugin install agenthub-insights@agenthub
|
||||
claude plugin install agenthub-sessions@agenthub
|
||||
claude plugin install agenthub-workflows@agenthub
|
||||
claude plugin install agenthub-quality@agenthub
|
||||
claude plugin install agenthub-config@agenthub
|
||||
claude plugin install agenthub-dashboard@agenthub
|
||||
```
|
||||
|
||||
### Or install locally during development
|
||||
@@ -250,7 +250,7 @@ single port.
|
||||
|
||||
### Uninstalling
|
||||
|
||||
`claude plugin uninstall agenthub@claude-code-agent-monitor-plugins` only removes
|
||||
`claude plugin uninstall agenthub@agenthub` only removes
|
||||
the plugin from the enabled list — verified against a real install/uninstall,
|
||||
not assumed. It does **not**:
|
||||
|
||||
@@ -545,6 +545,13 @@ my-plugin/
|
||||
|
||||
Structure is validated by `server/__tests__/plugins-marketplace.test.js`, which enforces the marketplace↔directory bijection, `plugin.json` shape, name/dir agreement, and required frontmatter on every agent / skill / command.
|
||||
|
||||
Two of those shape rules exist because getting them wrong makes a plugin **listed but uninstallable**, with no other symptom — the marketplace loads fine and only `claude plugin install` fails:
|
||||
|
||||
- A subdirectory entry declares **`"source": "./plugins/<name>"`**, never `"path"`. `path` is not a source key the CLI accepts (`This plugin's marketplace entry is invalid: source: Invalid input`).
|
||||
- A `plugin.json`'s **`repository` is a string**, not npm's `{ "type", "url" }` object (`Validation errors: repository: Invalid input`).
|
||||
|
||||
`server/__tests__/repo-links.test.js` guards the link side: no GitHub `owner/repo` marketplace shorthand (it resolves to github.com only — this repo is on Gitea, so the shorthand cannot work and no `GH_HOST`-style env var redirects it), no `raw.githubusercontent.com` / `*.github.io` / GitHub `/blob/<branch>/` URLs, no retired repository name, and no stale committed `openapi.yaml`.
|
||||
|
||||
### Testing locally
|
||||
|
||||
```bash
|
||||
@@ -555,20 +562,20 @@ claude --plugin-dir /path/to/my-plugin # then use /my-plugin:my-skill some arg
|
||||
|
||||
### Dashboard not reachable
|
||||
```bash
|
||||
cd /path/to/Claude-Code-Agent-Monitor
|
||||
cd /path/to/AgentHub
|
||||
npm start # or: npm run dev
|
||||
```
|
||||
|
||||
### Hooks not installed
|
||||
```bash
|
||||
cd /path/to/Claude-Code-Agent-Monitor
|
||||
cd /path/to/AgentHub
|
||||
npm run setup
|
||||
```
|
||||
|
||||
### Plugin not found
|
||||
```bash
|
||||
claude plugin marketplace list
|
||||
claude plugin marketplace add Smartgift-AI/Claude-Code-Monitor
|
||||
claude plugin marketplace add https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "claude-code-agent-monitor-landing",
|
||||
"name": "AgentHub",
|
||||
"short_name": "CC Monitor",
|
||||
"short_name": "AgentHub",
|
||||
"description": "Local-first monitoring dashboard for Claude Code sessions.",
|
||||
"author": "Nguyễn Ngọc Trí Vĩ",
|
||||
"start_url": ".",
|
||||
|
||||
+20
-20
@@ -3,15 +3,15 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Agent Dashboard for Claude Code API
|
||||
version: 1.4.6
|
||||
version: 1.5.0
|
||||
description: HTTP API for real-time Claude Code session monitoring, agent lifecycle tracking, analytics, pricing, hooks ingestion, and workflow intelligence.
|
||||
contact:
|
||||
name: Nguyễn Ngọc Trí Vĩ
|
||||
email: vinnt@smartgift.vn
|
||||
url: https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor
|
||||
url: https://git.smartgift.io.vn/Smartgift-AI/AgentHub
|
||||
externalDocs:
|
||||
description: Project documentation
|
||||
url: https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor#readme
|
||||
url: https://git.smartgift.io.vn/Smartgift-AI/AgentHub#readme
|
||||
servers:
|
||||
- url: http://localhost:4820
|
||||
description: Local dashboard server (default)
|
||||
@@ -363,7 +363,7 @@ components:
|
||||
version:
|
||||
type: string
|
||||
description: Dashboard release version from package.json
|
||||
example: 1.4.6
|
||||
example: 1.5.0
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -4051,7 +4051,7 @@ components:
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
- /Users/dev/AgentHub
|
||||
- /Users/son/code/another-project
|
||||
sources:
|
||||
type: array
|
||||
@@ -4540,7 +4540,7 @@ paths:
|
||||
- id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
status: active
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
started_at: '2026-06-25T14:02:11.004Z'
|
||||
ended_at: null
|
||||
@@ -4554,7 +4554,7 @@ paths:
|
||||
- id: 1a2b3c4d-5e6f-4071-8293-a4b5c6d7e8f9
|
||||
name: Fix flaky transcript pagination test
|
||||
status: completed
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-sonnet-4-20250514
|
||||
started_at: '2026-06-24T09:12:00.000Z'
|
||||
ended_at: '2026-06-24T09:48:32.501Z'
|
||||
@@ -4583,7 +4583,7 @@ paths:
|
||||
example:
|
||||
id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
metadata:
|
||||
source: hook
|
||||
@@ -4600,7 +4600,7 @@ paths:
|
||||
id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
status: active
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
started_at: '2026-06-25T14:02:11.004Z'
|
||||
ended_at: null
|
||||
@@ -4623,7 +4623,7 @@ paths:
|
||||
id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
status: active
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
started_at: '2026-06-25T14:02:11.004Z'
|
||||
ended_at: null
|
||||
@@ -4667,7 +4667,7 @@ paths:
|
||||
id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
status: active
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
started_at: '2026-06-25T14:02:11.004Z'
|
||||
ended_at: null
|
||||
@@ -4762,7 +4762,7 @@ paths:
|
||||
id: b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d
|
||||
name: Refactor pricing route + add cost endpoint
|
||||
status: completed
|
||||
cwd: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
cwd: /Users/dev/AgentHub
|
||||
model: claude-opus-4-20250514
|
||||
started_at: '2026-06-25T14:02:11.004Z'
|
||||
ended_at: '2026-06-25T15:07:44.220Z'
|
||||
@@ -6119,7 +6119,7 @@ paths:
|
||||
$ref: '#/components/schemas/SettingsInfoResponse'
|
||||
example:
|
||||
db:
|
||||
path: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor/server/data/agent-monitor.db
|
||||
path: /Users/dev/AgentHub/server/data/agent-monitor.db
|
||||
size: 48922624
|
||||
counts:
|
||||
sessions: 412
|
||||
@@ -6697,7 +6697,7 @@ paths:
|
||||
summary: Behind origin — update available
|
||||
value:
|
||||
git_repo: true
|
||||
repo_root: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
repo_root: /Users/dev/AgentHub
|
||||
update_available: true
|
||||
commits_behind: 4
|
||||
remote_ref: origin/master
|
||||
@@ -6709,7 +6709,7 @@ paths:
|
||||
summary: Up to date with origin
|
||||
value:
|
||||
git_repo: true
|
||||
repo_root: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
repo_root: /Users/dev/AgentHub
|
||||
update_available: false
|
||||
commits_behind: 0
|
||||
remote_ref: origin/master
|
||||
@@ -6754,7 +6754,7 @@ paths:
|
||||
summary: Behind origin — update available
|
||||
value:
|
||||
git_repo: true
|
||||
repo_root: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
repo_root: /Users/dev/AgentHub
|
||||
update_available: true
|
||||
commits_behind: 4
|
||||
remote_ref: origin/master
|
||||
@@ -6766,7 +6766,7 @@ paths:
|
||||
summary: Up to date with origin
|
||||
value:
|
||||
git_repo: true
|
||||
repo_root: /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
repo_root: /Users/dev/AgentHub
|
||||
update_available: false
|
||||
commits_behind: 0
|
||||
remote_ref: origin/master
|
||||
@@ -10114,7 +10114,7 @@ paths:
|
||||
example:
|
||||
items:
|
||||
- kind: dashboard
|
||||
path: /Users/dev/Claude-Code-Agent-Monitor
|
||||
path: /Users/dev/AgentHub
|
||||
label: Dashboard server
|
||||
- kind: home
|
||||
path: /Users/dev
|
||||
@@ -10965,7 +10965,7 @@ paths:
|
||||
$ref: '#/components/schemas/SessionsFacetsResponse'
|
||||
example:
|
||||
cwds:
|
||||
- /Users/son/WebstormProjects/Claude-Code-Agent-Monitor
|
||||
- /Users/dev/AgentHub
|
||||
- /Users/son/code/another-project
|
||||
sources:
|
||||
- local
|
||||
@@ -11633,4 +11633,4 @@ paths:
|
||||
errors: 0
|
||||
'400':
|
||||
description: Missing file, invalid JSON, or unrecognized export format
|
||||
x-issues-url: https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor/issues
|
||||
x-issues-url: https://git.smartgift.io.vn/Smartgift-AI/AgentHub/issues
|
||||
|
||||
+3
-3
@@ -18,13 +18,13 @@
|
||||
"author": "Nguyễn Ngọc Trí Vĩ",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
"url": "git+https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor/issues"
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub/issues"
|
||||
},
|
||||
"license": "UNLICENSED",
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor#readme",
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub#readme",
|
||||
"keywords": [
|
||||
"claude",
|
||||
"claude-code",
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"analytics",
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["config", "memory", "governance", "audit", "mcp", "hooks", "claude-code"],
|
||||
"categories": ["config", "governance", "monitoring"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["budget", "cost", "forecast", "alerts", "spend", "pricing", "claude-code"],
|
||||
"categories": ["cost", "monitoring", "alerts"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["dashboard", "connector", "real-time", "monitoring", "claude-code"],
|
||||
"categories": ["integration", "monitoring"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["devtools", "debugging", "diagnostics", "export", "health-check", "claude-code"],
|
||||
"categories": ["devtools", "debugging", "diagnostics"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"insights",
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["productivity", "standup", "reports", "sprint", "workflow", "claude-code"],
|
||||
"categories": ["productivity", "workflow", "reporting"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"reliability",
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": ["sessions", "search", "transcript", "replay", "timeline", "cleanup", "claude-code"],
|
||||
"categories": ["sessions", "monitoring", "devtools"]
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
"name": "Nguyễn Ngọc Trí Vĩ",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
"repository": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"workflows",
|
||||
|
||||
@@ -15,7 +15,11 @@ const { createOpenApiSpec } = require("../server/openapi");
|
||||
|
||||
const OUT = path.join(__dirname, "..", "openapi.yaml");
|
||||
|
||||
function main() {
|
||||
/** The exact bytes `openapi.yaml` must contain for the current spec. Exported so
|
||||
* the drift test can compare against the committed file without duplicating the
|
||||
* dump options — a second copy of them would let the two definitions diverge,
|
||||
* which is the very staleness this file exists to prevent. */
|
||||
function render() {
|
||||
const spec = createOpenApiSpec();
|
||||
const body = yaml.dump(spec, {
|
||||
lineWidth: -1, // don't wrap long strings (keeps descriptions/examples intact)
|
||||
@@ -25,10 +29,15 @@ function main() {
|
||||
const header =
|
||||
"# DO NOT EDIT BY HAND. Generated from server/openapi.js via `npm run openapi:yaml`.\n" +
|
||||
"# This YAML mirrors the live spec served at GET /api/openapi.json.\n";
|
||||
fs.writeFileSync(OUT, header + body, "utf8");
|
||||
const stat = fs.statSync(OUT);
|
||||
const pathCount = Object.keys(spec.paths || {}).length;
|
||||
console.log(`Wrote ${OUT} (${pathCount} paths, ${stat.size} bytes).`);
|
||||
return { text: header + body, pathCount: Object.keys(spec.paths || {}).length };
|
||||
}
|
||||
|
||||
main();
|
||||
function main() {
|
||||
const { text, pathCount } = render();
|
||||
fs.writeFileSync(OUT, text, "utf8");
|
||||
console.log(`Wrote ${OUT} (${pathCount} paths, ${fs.statSync(OUT).size} bytes).`);
|
||||
}
|
||||
|
||||
if (require.main === module) main();
|
||||
|
||||
module.exports = { render, OUT };
|
||||
|
||||
@@ -89,7 +89,7 @@ function containerRefusalMessage() {
|
||||
"",
|
||||
" → Install hooks ON THE HOST instead:",
|
||||
" npm run install-hooks",
|
||||
" # or: node /path/to/Claude-Code-Agent-Monitor/scripts/install-hooks.js",
|
||||
" # or: node /path/to/AgentHub/scripts/install-hooks.js",
|
||||
"",
|
||||
" The host handler POSTs to http://localhost:4820, which the container already",
|
||||
" publishes — so a host-installed hook reaches the containerized dashboard.",
|
||||
|
||||
@@ -185,10 +185,7 @@ describe("OpenAPI / Swagger", () => {
|
||||
// so the spec must not advertise one (a LICENSE url would 404).
|
||||
assert.equal(res.body.info.license, undefined);
|
||||
assert.equal(res.body["x-issues-url"], pkg.bugs.url);
|
||||
assert.match(
|
||||
res.body.info.contact.url,
|
||||
/git\.smartgift\.io\.vn\/Smartgift-AI\/Claude-Code-Monitor/
|
||||
);
|
||||
assert.match(res.body.info.contact.url, /git\.smartgift\.io\.vn\/Smartgift-AI\/AgentHub/);
|
||||
|
||||
for (const pathName of EXPECTED_API_PATHS) {
|
||||
assert.ok(res.body.paths[pathName], `Expected path ${pathName} to be documented`);
|
||||
|
||||
@@ -248,7 +248,7 @@ describe("legacy hook cleanup", () => {
|
||||
TMP_HOME,
|
||||
"plugins",
|
||||
"cache",
|
||||
"claude-code-agent-monitor-plugins",
|
||||
"agenthub",
|
||||
"agenthub",
|
||||
"abc123",
|
||||
"scripts",
|
||||
|
||||
@@ -79,16 +79,21 @@ describe("plugin marketplace", () => {
|
||||
|
||||
for (const entry of subdirEntries) {
|
||||
describe(`entry: ${entry.name}`, () => {
|
||||
it("has name, path, description, tags", () => {
|
||||
it("has name, source, description, tags", () => {
|
||||
assert.equal(typeof entry.name, "string");
|
||||
assert.equal(entry.path, `plugins/${entry.name}`);
|
||||
// `source`, not `path`: the `claude plugin install` CLI validates the
|
||||
// entry against a schema that only knows `source`, so a `path` entry
|
||||
// fails with "This plugin's marketplace entry is invalid: source:
|
||||
// Invalid input" — the plugin is listed but uninstallable.
|
||||
assert.equal(entry.source, `./plugins/${entry.name}`);
|
||||
assert.equal(entry.path, undefined, "`path` is not a source key the CLI accepts");
|
||||
assert.equal(typeof entry.description, "string");
|
||||
assert.ok(entry.description.length > 20);
|
||||
assert.ok(Array.isArray(entry.tags) && entry.tags.length > 0);
|
||||
});
|
||||
|
||||
it("path exists on disk", () => {
|
||||
assert.ok(fs.existsSync(path.join(REPO_ROOT, entry.path)));
|
||||
it("source exists on disk", () => {
|
||||
assert.ok(fs.existsSync(path.join(REPO_ROOT, entry.source)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file repo-links.test.js
|
||||
* @description Guards the two staleness classes that shipped broken commands to
|
||||
* users for weeks: (1) GitHub-shaped references in a repo that is self-hosted on
|
||||
* Gitea — the `owner/repo` marketplace shorthand resolves to github.com ONLY
|
||||
* (verified against the CLI: it rejects `host/owner/repo` outright and ignores
|
||||
* GH_HOST / GITHUB_HOST / CLAUDE_CODE_MARKETPLACE_URL), plus raw.githubusercontent
|
||||
* / *.github.io / `/blob/<branch>` URLs that 404 against Gitea; and (2) a stale
|
||||
* committed `openapi.yaml`, which had silently drifted a whole minor version
|
||||
* behind package.json. Pure file reads plus one in-process spec render.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
const { describe, it } = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { execFileSync } = require("node:child_process");
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, "..", "..");
|
||||
|
||||
// Only git-tracked text files: keeps node_modules, client/dist and every
|
||||
// build artifact out without hand-maintaining an ignore list.
|
||||
const TRACKED_EXT = /\.(md|json|js|cjs|mjs|ts|tsx|sh|ya?ml|html|css)$/;
|
||||
|
||||
// This file states every banned pattern verbatim — in the rules below and in
|
||||
// the comments explaining them — so it must exclude itself or it fails on its
|
||||
// own source. Derived from __filename rather than hardcoded so a rename can't
|
||||
// silently re-arm the self-report.
|
||||
const SELF = path.relative(REPO_ROOT, __filename);
|
||||
|
||||
function trackedFiles() {
|
||||
// No GIT_* scrub here, deliberately: under this repo's pre-commit hook
|
||||
// GIT_INDEX_FILE points at the index being committed, so `ls-files` lints
|
||||
// exactly what is about to land. Scrubbing it would lint the previous commit
|
||||
// instead and let a newly staged violation through.
|
||||
const out = execFileSync("git", ["ls-files", "-z"], {
|
||||
cwd: REPO_ROOT,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 20_000_000,
|
||||
});
|
||||
return (
|
||||
out
|
||||
.split("\0")
|
||||
.filter((f) => f && TRACKED_EXT.test(f))
|
||||
.filter((f) => f !== SELF)
|
||||
// Dated design docs and plans record what was true when written; rewriting
|
||||
// history to satisfy a lint would be a lie about the decision record.
|
||||
.filter((f) => !f.startsWith("docs/superpowers/"))
|
||||
// Generated from server/openapi-extra/* (which IS linted): the drift test
|
||||
// below covers it, so linting both would only double-report one fix.
|
||||
.filter((f) => f !== "openapi.yaml" && !f.endsWith("package-lock.json"))
|
||||
);
|
||||
}
|
||||
|
||||
// Each rule: what to look for, and what to do instead. A `skip` pattern is
|
||||
// tested against the MATCHED TEXT ONLY, never the surrounding line — a skip
|
||||
// written against nearby prose silently never fires. Add one only when the
|
||||
// exception is visible inside the match itself.
|
||||
const RULES = [
|
||||
{
|
||||
name: "GitHub owner/repo marketplace shorthand",
|
||||
// `claude plugin marketplace add Smartgift-AI/AgentHub` — resolves to
|
||||
// github.com and fails, because this repo lives on Gitea.
|
||||
re: /plugin marketplace add\s+(?!https?:\/\/)(?!\.{0,2}\/)(?!["'$])[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*/g,
|
||||
fix: "use the full https:// clone URL — the shorthand is GitHub-only",
|
||||
// Anthropic's own marketplace really does live on GitHub.
|
||||
skip: [/anthropics\/claude-plugins-official/],
|
||||
},
|
||||
{
|
||||
name: "GitHub URL for a Smartgift repo",
|
||||
re: /(?:https?:\/\/)?(?:www\.)?github\.com\/[Ss]martgift[\w-]*\/[\w.-]+/g,
|
||||
fix: "point at git.smartgift.io.vn",
|
||||
skip: [],
|
||||
},
|
||||
{
|
||||
name: "raw.githubusercontent.com",
|
||||
// Our repos are not on GitHub, so every raw URL 404s. Same-origin paths or
|
||||
// a Gitea /raw/branch/<ref>/ URL instead.
|
||||
re: /raw\.githubusercontent\.com\/[\w-]+\/[\w.-]+/g,
|
||||
fix: "use a same-origin path, or a Gitea /raw/branch/<ref>/ URL",
|
||||
skip: [],
|
||||
},
|
||||
{
|
||||
name: "GitHub Pages host for a Smartgift site",
|
||||
re: /[\w-]*smartgift[\w-]*\.github\.io/gi,
|
||||
fix: "there is no GitHub Pages site — link the Gitea docs directory",
|
||||
skip: [],
|
||||
},
|
||||
{
|
||||
name: "GitHub /blob/<branch>/ path syntax on a Gitea URL",
|
||||
// Gitea serves files at /src/branch/<ref>/, never /blob/<ref>/.
|
||||
re: /git\.smartgift\.io\.vn\/[^\s"')\]]*\/blob\/[\w.-]+\//g,
|
||||
fix: "Gitea serves files at /src/branch/<ref>/",
|
||||
skip: [],
|
||||
},
|
||||
{
|
||||
name: "retired repository name",
|
||||
// Gitea 301-redirects the old name, so these never fail loudly — they just
|
||||
// rot until someone turns the redirect off.
|
||||
re: /Claude-Code-Monitor|Claude-Code-Agent-Monitor/g,
|
||||
fix: "the repository is Smartgift-AI/AgentHub",
|
||||
skip: [],
|
||||
},
|
||||
];
|
||||
|
||||
describe("repo links and generated files", () => {
|
||||
const files = trackedFiles();
|
||||
|
||||
it("finds tracked text files to lint", () => {
|
||||
assert.ok(files.length > 50, `expected a populated file list, got ${files.length}`);
|
||||
});
|
||||
|
||||
for (const rule of RULES) {
|
||||
it(`no ${rule.name}`, () => {
|
||||
const hits = [];
|
||||
for (const rel of files) {
|
||||
const text = fs.readFileSync(path.join(REPO_ROOT, rel), "utf8");
|
||||
// A fresh regex per file: the /g rules carry lastIndex between calls.
|
||||
for (const m of text.matchAll(new RegExp(rule.re.source, rule.re.flags))) {
|
||||
if (rule.skip.some((s) => s.test(m[0]))) continue;
|
||||
const line = text.slice(0, m.index).split("\n").length;
|
||||
hits.push(`${rel}:${line}: ${m[0].trim()}`);
|
||||
}
|
||||
}
|
||||
assert.deepEqual(hits, [], `${rule.fix}\n ${hits.join("\n ")}`);
|
||||
});
|
||||
}
|
||||
|
||||
it("committed openapi.yaml matches the generator output", () => {
|
||||
const { render, OUT } = require("../../scripts/generate-openapi-yaml");
|
||||
assert.equal(
|
||||
fs.readFileSync(OUT, "utf8"),
|
||||
render().text,
|
||||
"openapi.yaml is stale — run `npm run openapi:yaml` and commit the result"
|
||||
);
|
||||
});
|
||||
});
|
||||
+7
-4
@@ -25,7 +25,7 @@ function loadOrCreateVapidKeys() {
|
||||
const vapidKeys = loadOrCreateVapidKeys();
|
||||
|
||||
webpush.setVapidDetails(
|
||||
"https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor",
|
||||
"https://git.smartgift.io.vn/Smartgift-AI/AgentHub",
|
||||
vapidKeys.publicKey,
|
||||
vapidKeys.privateKey
|
||||
);
|
||||
@@ -94,9 +94,12 @@ async function sendPushToAll(db, title, body) {
|
||||
const payload = JSON.stringify({
|
||||
title,
|
||||
body,
|
||||
icon: "https://raw.githubusercontent.com/Smartgift-AI/Claude-Code-Monitor/main/client/public/favicon.ico",
|
||||
badge:
|
||||
"https://raw.githubusercontent.com/Smartgift-AI/Claude-Code-Monitor/main/client/public/favicon.ico",
|
||||
// Same-origin path, resolved by the service worker against its own scope
|
||||
// (client/public/sw.js spreads these straight into showNotification). An
|
||||
// absolute forge/raw URL would 404 — this repo is self-hosted on Gitea and
|
||||
// ships favicon.svg, not favicon.ico.
|
||||
icon: "/favicon.svg",
|
||||
badge: "/favicon.svg",
|
||||
silent: false,
|
||||
sound: "default",
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ const { execFile } = require("child_process");
|
||||
const DEFAULT_ROOT = path.join(__dirname, "..", "..");
|
||||
|
||||
// This build tracks its OWN repository only: origin points at
|
||||
// git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor. "upstream" is
|
||||
// git.smartgift.io.vn/Smartgift-AI/AgentHub. "upstream" is
|
||||
// deliberately absent from the priority list — a stray upstream remote must
|
||||
// never make the update checker report commits from somebody else's repo.
|
||||
const REMOTE_PRIORITY = ["origin"];
|
||||
|
||||
@@ -40,10 +40,7 @@ const schemas = {
|
||||
description:
|
||||
"Distinct, non-empty session working directories (the `cwd` column), sorted ascending. Powers the cwd filter dropdown.",
|
||||
items: { type: "string" },
|
||||
example: [
|
||||
"/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
"/Users/son/code/another-project",
|
||||
],
|
||||
example: ["/Users/dev/AgentHub", "/Users/son/code/another-project"],
|
||||
},
|
||||
sources: {
|
||||
type: "array",
|
||||
@@ -527,10 +524,7 @@ const paths = {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/SessionsFacetsResponse" },
|
||||
example: {
|
||||
cwds: [
|
||||
"/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
"/Users/son/code/another-project",
|
||||
],
|
||||
cwds: ["/Users/dev/AgentHub", "/Users/son/code/another-project"],
|
||||
sources: ["local", "4d1f0e2a-7b9c-4c33-8a21-9e0f7b6d4c11"],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -97,7 +97,7 @@ const GENERIC_WEBHOOK_TARGET_EXAMPLE = {
|
||||
|
||||
const SETTINGS_INFO_EXAMPLE = {
|
||||
db: {
|
||||
path: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor/server/data/agent-monitor.db",
|
||||
path: "/Users/dev/AgentHub/server/data/agent-monitor.db",
|
||||
size: 48922624,
|
||||
counts: {
|
||||
sessions: 412,
|
||||
@@ -351,7 +351,7 @@ const IMPORT_UPLOAD_EXAMPLE = {
|
||||
|
||||
const UPDATE_STATUS_AVAILABLE_EXAMPLE = {
|
||||
git_repo: true,
|
||||
repo_root: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
repo_root: "/Users/dev/AgentHub",
|
||||
update_available: true,
|
||||
commits_behind: 4,
|
||||
remote_ref: "origin/master",
|
||||
@@ -363,7 +363,7 @@ const UPDATE_STATUS_AVAILABLE_EXAMPLE = {
|
||||
|
||||
const UPDATE_STATUS_UP_TO_DATE_EXAMPLE = {
|
||||
git_repo: true,
|
||||
repo_root: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
repo_root: "/Users/dev/AgentHub",
|
||||
update_available: false,
|
||||
commits_behind: 0,
|
||||
remote_ref: "origin/master",
|
||||
|
||||
@@ -43,7 +43,7 @@ const exampleSession = {
|
||||
id: "b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d",
|
||||
name: "Refactor pricing route + add cost endpoint",
|
||||
status: "active",
|
||||
cwd: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
cwd: "/Users/dev/AgentHub",
|
||||
model: "claude-opus-4-20250514",
|
||||
started_at: "2026-06-25T14:02:11.004Z",
|
||||
ended_at: null,
|
||||
@@ -60,7 +60,7 @@ const exampleCompletedSession = {
|
||||
id: "1a2b3c4d-5e6f-4071-8293-a4b5c6d7e8f9",
|
||||
name: "Fix flaky transcript pagination test",
|
||||
status: "completed",
|
||||
cwd: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
cwd: "/Users/dev/AgentHub",
|
||||
model: "claude-sonnet-4-20250514",
|
||||
started_at: "2026-06-24T09:12:00.000Z",
|
||||
ended_at: "2026-06-24T09:48:32.501Z",
|
||||
@@ -176,7 +176,7 @@ const paths = {
|
||||
example: {
|
||||
id: "b7f3a2c1-4e5d-4a8b-9c2f-1d6e8a0b3c4d",
|
||||
name: "Refactor pricing route + add cost endpoint",
|
||||
cwd: "/Users/son/WebstormProjects/Claude-Code-Agent-Monitor",
|
||||
cwd: "/Users/dev/AgentHub",
|
||||
model: "claude-opus-4-20250514",
|
||||
metadata: { source: "hook", git_branch: "feat/spend-budgets" },
|
||||
},
|
||||
|
||||
@@ -875,7 +875,7 @@ const paths = {
|
||||
items: [
|
||||
{
|
||||
kind: "dashboard",
|
||||
path: "/Users/dev/Claude-Code-Agent-Monitor",
|
||||
path: "/Users/dev/AgentHub",
|
||||
label: "Dashboard server",
|
||||
},
|
||||
{ kind: "home", path: "/Users/dev", label: "Home" },
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**AgentHub** brings a high-fidelity, real-time dashboard for your Claude Code AI sessions directly into your VS Code workspace. Monitor token usage, track agent health, and view deep analytics without switching windows.
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -288,8 +288,8 @@ function getErrorHtml() {
|
||||
<div class="timeline">
|
||||
<div class="t-step">
|
||||
<div class="t-label">Initialize Repository</div>
|
||||
<div class="t-code">git clone https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor.git
|
||||
cd Claude-Code-Agent-Monitor
|
||||
<div class="t-code">git clone https://git.smartgift.io.vn/Smartgift-AI/AgentHub.git
|
||||
cd AgentHub
|
||||
npm run setup</div>
|
||||
</div>
|
||||
<div class="t-step" style="margin-bottom: 0;">
|
||||
@@ -317,16 +317,15 @@ npm run setup</div>
|
||||
Retry Connection
|
||||
</button>
|
||||
|
||||
<a href="https://smartgift.github.io/Claude-Code-Agent-Monitor/" class="btn btn-secondary">
|
||||
<a href="https://git.smartgift.io.vn/Smartgift-AI/AgentHub/src/branch/main/docs" class="btn btn-secondary">
|
||||
View Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<a href="https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor">GitHub</a>
|
||||
<a href="https://smartgift.github.io/Claude-Code-Agent-Monitor/">Wiki</a>
|
||||
<a href="https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor/issues">Support</a>
|
||||
<a href="https://git.smartgift.io.vn/Smartgift-AI/AgentHub">Repository</a>
|
||||
<a href="https://git.smartgift.io.vn/Smartgift-AI/AgentHub/issues">Support</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor"
|
||||
"url": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub"
|
||||
},
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/Claude-Code-Monitor/blob/master/vscode-extension/README.md",
|
||||
"homepage": "https://git.smartgift.io.vn/Smartgift-AI/AgentHub/src/branch/main/vscode-extension/README.md",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user