From 5fb2b6d6c608348c1f15dc6c79aec93df4dcb6c4 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Wed, 29 Jul 2026 19:21:08 +0200 Subject: [PATCH] fix(hub): SessionStart-Hook und `agenthub start` liefern denselben Text + Verzeichnis-Guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) hookContext druckte einen eigenen, aelteren Text. Fuer Codex/Kimi ist der Hook aber oft der EINZIGE Einstieg (sie starten automatisch) — dadurch kannten auto-gestartete Agenten weder den Check-in-Kanal noch DEC-0035. Aufgefallen, als codex ohne `agenthub start` losgelaufen ist. Beide Wege nutzen jetzt agentBriefing(). 2) `server start` prueft jetzt VOR dem Binden, ob hier ueberhaupt ein Projekt liegt. Vorher band der Server erst den Port und starb dann beim Laden der Config — der alte Hub war da schon gekillt, die Agenten liefen ins Leere. Klassiker: aus dem Quellrepo statt aus dem Projekt gestartet (an einem Tag dreimal passiert). Jetzt sofortiger, verstaendlicher Fehler. Co-Authored-By: Claude Opus 5 (1M context) --- src/cli/commands/agentSetup.ts | 17 +++++++---------- src/cli/commands/server.ts | 20 +++++++++++++++++++- src/cli/commands/startAgent.ts | 7 +++++-- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/cli/commands/agentSetup.ts b/src/cli/commands/agentSetup.ts index ce25ef0..51da8e3 100644 --- a/src/cli/commands/agentSetup.ts +++ b/src/cli/commands/agentSetup.ts @@ -2,6 +2,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs'; import { join, dirname } from 'node:path'; import { homedir } from 'node:os'; import { findProjectRoot } from '../../core/paths.js'; +import { agentBriefing } from './startAgent.js'; /** * Auto-start: make an agent enter the agenthub work-loop the moment its CLI @@ -37,16 +38,12 @@ export function inferCli(agent: string, explicit?: string): AgentCli { /** Printed by the SessionStart hook → injected as session context. */ export function hookContext(opts: { agent: string; role: string }): void { const { agent, role } = opts; - process.stdout.write( - `AgentHub auto-start — you are "${agent}" (${role}). Before anything else, enter the work loop:\n` + - ` agenthub work --agent ${agent} --role ${role}\n` + - `(or call the agenthub_work tool with { agent: "${agent}", role: "${role}" }). It BLOCKS until a ` + - `task or message addressed to you arrives, then returns it. Handle it, then IMMEDIATELY call ` + - `agenthub_work AGAIN — run it in the BACKGROUND so you're woken on the next event without ` + - `tying up your turn. The loop is: work -> handle -> agenthub_task_review -> work, forever. ` + - `agenthub_work claims your tasks AND delivers your messages. Never run agenthub_task_done. ` + - `Staying in this loop is what keeps you reachable — do not end a turn without relaunching agenthub_work.\n`, - ); + // Denselben Text wie `agenthub start` ausgeben. Der Hook ist fuer viele + // Sessions der EINZIGE Einstieg (Codex/Kimi starten automatisch) — ein + // eigener, aelterer Text hier fuehrt dazu, dass auto-gestartete Agenten den + // Check-in-Kanal und DEC-0035 gar nicht kennen. Genau das war der Fall, bis + // der CEO bemerkte, dass codex ohne `agenthub start` losgelaufen ist. + process.stdout.write(`${agentBriefing(agent, role)}\n`); } // ─── Marker-delimited upsert (for line-based TOML configs) ─────────────────── diff --git a/src/cli/commands/server.ts b/src/cli/commands/server.ts index d8aef64..6e372d5 100644 --- a/src/cli/commands/server.ts +++ b/src/cli/commands/server.ts @@ -1,4 +1,5 @@ import { startServer } from '../../server/index.js'; +import { findProjectRoot } from '../../core/paths.js'; /** * Probe a URL to check whether an AgentHub server is already answering there. @@ -30,5 +31,22 @@ export async function serverStart(cwd: string, options: { port: number; host: st return; } - await startServer(cwd, options); + // Verzeichnis-Guard: NICHT den Port binden, wenn hier gar kein Projekt liegt. + // Ohne diese Prüfung bindet der Server erst den Port, stolpert dann beim + // Laden der Config und stirbt — der Port ist kurz belegt, der alte Hub ist + // schon gekillt, und die Agenten laufen ins Leere. Klassischer Fall: aus dem + // agenthub-Quellrepo statt aus dem Projekt gestartet (mir an einem Tag + // dreimal passiert). Lieber sofort und verständlich scheitern. + const projectRoot = findProjectRoot(cwd); + if (!projectRoot) { + console.error( + `Kein AgentHub-Projekt in ${cwd} (und keinem übergeordneten Verzeichnis).\n` + + `Starte den Server aus dem Projekt-Root — dort liegt .agenthub/ mit den Daten.\n` + + `Falls das hier ein neues Projekt werden soll: agenthub init`, + ); + process.exitCode = 1; + return; + } + + await startServer(projectRoot, options); } diff --git a/src/cli/commands/startAgent.ts b/src/cli/commands/startAgent.ts index 72635d2..fd1ad9c 100644 --- a/src/cli/commands/startAgent.ts +++ b/src/cli/commands/startAgent.ts @@ -24,7 +24,10 @@ export interface StartAgentOptions { role?: string; } -function briefing(agent: string, role: string): string { +/** Das verbindliche Briefing. Wird von `agenthub start` UND vom SessionStart-Hook + * benutzt — beide MÜSSEN denselben Text liefern, sonst arbeitet ein + * auto-gestarteter Agent nach veralteten Regeln. */ +export function agentBriefing(agent: string, role: string): string { return [ `Du bist "${agent}" im AgentHub (Rolle: ${role}).`, '', @@ -174,7 +177,7 @@ export async function startAgentSession(options: StartAgentOptions): Promise