Compare commits

..

No commits in common. "eec2050a326228d6e21fac6e500cdc7ed570bb6f" and "c0ac093f466147a2efb0827068d9d4ca63b329c7" have entirely different histories.

4 changed files with 15 additions and 95 deletions

View File

@ -1,6 +1,6 @@
{
"name": "agenthub",
"version": "0.7.3",
"version": "0.7.2",
"description": "Local coordination layer for AI coding agents",
"type": "module",
"main": "./dist/index.js",

View File

@ -12,7 +12,6 @@ import { watchEvents } from './commands/watch.js';
import { startAgent } from './commands/start.js';
import { workAgent } from './commands/work.js';
import { startMcpServer } from '../mcp/server.js';
import { printMcpConfig } from '../mcp/install.js';
import { loadConfig, saveConfig } from '../core/config.js';
import { findProjectRoot } from '../core/paths.js';
import { discoverServer } from '../discovery.js';
@ -116,7 +115,7 @@ async function runRemote(serverUrl: string, fn: () => Promise<void>): Promise<vo
export function createProgram(cwd: string): Command {
const program = new Command('agenthub')
.description('Local coordination layer for AI coding agents')
.version('0.7.3')
.version('0.7.2')
.option('--server <url>', 'AgentHub server URL (env: AGENTHUB_SERVER)');
program
@ -485,13 +484,9 @@ export function createProgram(cwd: string): Command {
// ─── mcp ───────────────────────────────────────────────────────────────────
program
.command('mcp [action]')
.description('Start the MCP server (stdio). `agenthub mcp install` prints per-CLI registration config.')
.action(async (action?: string) => {
if (action === 'install') {
printMcpConfig(cwd);
return;
}
.command('mcp')
.description('Start the MCP server (stdio) — exposes hub tools to MCP-capable agents (Claude/Codex/Kimi)')
.action(async () => {
await startMcpServer(cwd);
});

View File

@ -1,59 +0,0 @@
import { findProjectRoot } from '../core/paths.js';
import { loadConfig } from '../core/config.js';
/**
* Print ready-to-paste MCP registration config for each agent CLI, with the
* hub URL filled in. The MCP server itself is `agenthub mcp` (stdio) every
* client just needs to know to spawn it + which hub to talk to.
*/
export function printMcpConfig(cwd: string): void {
const root = findProjectRoot(cwd) ?? cwd;
let serverUrl = process.env.AGENTHUB_SERVER || undefined;
if (!serverUrl) {
try {
serverUrl = loadConfig(root).serverUrl;
} catch {
/* no project config */
}
}
const url = serverUrl ?? 'http://127.0.0.1:3377';
const out = (s: string) => process.stdout.write(s + '\n');
out('');
out('AgentHub MCP — registration');
out('═══════════════════════════');
out(`Hub URL: ${url}`);
out('(On the Windows machine use the Mac\'s LAN IP, e.g. http://192.168.178.30:3377)');
out('');
out('The MCP server is `agenthub mcp` (stdio). Register it once per agent CLI:');
out('');
out('── Claude Code ──────────────────────────────────────────────');
out(` claude mcp add agenthub --env AGENTHUB_SERVER=${url} -- agenthub mcp`);
out(' (or add the .mcp.json block below to the project)');
out('');
out('── .mcp.json (project root — Claude Code / generic) ─────────');
out(JSON.stringify(
{ mcpServers: { agenthub: { command: 'agenthub', args: ['mcp'], env: { AGENTHUB_SERVER: url } } } },
null,
2,
));
out('');
out('── Codex CLI (~/.codex/config.toml) ─────────────────────────');
out(' [mcp_servers.agenthub]');
out(' command = "agenthub"');
out(' args = ["mcp"]');
out(` env = { AGENTHUB_SERVER = "${url}" }`);
out('');
out('── Kimi CLI ─────────────────────────────────────────────────');
out(' Add a stdio MCP server via Kimi\'s MCP config with the same shape:');
out(' command: agenthub args: ["mcp"] env: { AGENTHUB_SERVER: ' + url + ' }');
out('');
out('After registering, the agent calls the tools (agenthub_work, agenthub_task_review, …)');
out('instead of CLI strings. Requires agenthub >= 0.7.0 on each machine.');
out('');
}

View File

@ -183,12 +183,11 @@ export function renderBoardHtml(projectName = 'AgentHub Project'): string {
.board {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
grid-template-columns: repeat(5, minmax(180px, 1fr));
gap: 12px;
align-items: start;
}
.column {
min-width: 0;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
@ -223,11 +222,8 @@ export function renderBoardHtml(projectName = 'AgentHub Project'): string {
.column[data-column="done"] .col-label { color: var(--done); }
.column[data-column="cancelled"] .col-label { color: var(--cancelled); }
.cards { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cards { display: flex; flex-direction: column; gap: 8px; }
.card {
min-width: 0;
max-width: 100%;
overflow: hidden;
background: var(--raised);
border: 1px solid var(--border);
border-left: 3px solid var(--accent);
@ -324,23 +320,19 @@ export function renderBoardHtml(projectName = 'AgentHub Project'): string {
.timeline {
display: none;
min-width: 0;
max-width: 100%;
overflow: hidden;
margin-top: 9px;
padding-top: 8px;
border-top: 1px solid var(--border);
}
.card.expanded .timeline { display: block; }
.tl-row {
display: grid;
grid-template-columns: auto auto minmax(0, 1fr);
align-items: start;
display: flex;
align-items: baseline;
gap: 6px;
flex-wrap: wrap;
padding: 4px 0;
border-top: 1px solid rgba(48, 54, 61, .5);
font-size: 12px;
min-width: 0;
}
.tl-row:first-child { border-top: 0; }
.tl-when { color: var(--muted); font: 11px/1.4 var(--mono); white-space: nowrap; min-width: 52px; }
@ -355,9 +347,9 @@ export function renderBoardHtml(projectName = 'AgentHub Project'): string {
.tl-kind-handoff { background: rgba(88, 166, 255, .12); color: var(--accent); border-color: rgba(88, 166, 255, .25); }
.tl-kind-result { background: rgba(34, 197, 94, .12); color: var(--done); border-color: rgba(34, 197, 94, .25); }
.tl-kind-status { background: rgba(210, 153, 34, .12); color: var(--review); border-color: rgba(210, 153, 34, .25); }
.tl-actor { color: var(--muted); font: 11px/1.4 var(--mono); min-width: 0; overflow-wrap: anywhere; }
.tl-summary { grid-column: 1 / -1; min-width: 0; max-width: 100%; overflow-wrap: anywhere; word-break: break-word; white-space: normal; }
.tl-meta { grid-column: 1 / -1; display: flex; gap: 4px; flex-wrap: wrap; min-width: 0; }
.tl-actor { color: var(--muted); font: 11px/1.4 var(--mono); white-space: nowrap; }
.tl-summary { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.tl-meta { display: flex; gap: 4px; flex-wrap: wrap; }
.badge.tl-tokens { color: #A371F7; border-color: rgba(163, 113, 247, .25); background: rgba(163, 113, 247, .12); }
.badge.tl-dur { color: #FFA657; border-color: rgba(255, 166, 87, .25); background: rgba(255, 166, 87, .12); }
.tl-loading, .tl-empty { color: var(--muted); font-size: 12px; padding: 2px 0; }
@ -633,20 +625,12 @@ ${columnSkeleton()}
if (!cardsEl) return;
var expanded = {};
cardsEl.querySelectorAll('.card.expanded[data-id]').forEach(function(c) {
var timeline = c.querySelector('.timeline');
expanded[c.dataset.id] = timeline ? timeline.innerHTML : '';
expanded[c.dataset.id] = true;
});
cardsEl.innerHTML = list.length ? list.map(taskCard).join('') : '<div class="empty">none</div>';
Object.keys(expanded).forEach(function(id) {
var card = cardsEl.querySelector('.card[data-id="' + id + '"]');
if (!card) return;
card.classList.add('expanded');
var timeline = card.querySelector('.timeline');
if (timeline && expanded[id]) {
timeline.innerHTML = expanded[id];
} else {
loadTimeline(card, id);
}
if (card) card.classList.add('expanded');
});
});
updateTimers();