feat(orchestrator): create_skill action + wire per-project watchers (§14.3)
- domain: OrchestratorCommand::CreateSkill with optional scope field (defaults to Project, case-insensitive, UnknownScope on bad value) - application: dispatch CreateSkill through the CreateSkill use case - app-tauri: build OrchestratorService and start/stop per-project request watchers on open/create/close_project (ensure/stop_orchestrator_watch) - tests: domain validation, service dispatch, infra watcher e2e, app-tauri wiring lifecycle (idempotent, isolated, stop) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -64,7 +64,7 @@ function describe(e: unknown): string {
|
||||
}
|
||||
|
||||
export function useAgents(projectId: string): AgentsViewModel {
|
||||
const { agent, profile } = useGateways();
|
||||
const { agent, profile, system } = useGateways();
|
||||
|
||||
const [agents, setAgents] = useState<Agent[]>([]);
|
||||
const [selectedAgentId, setSelectedAgentId] = useState<string | null>(null);
|
||||
@ -95,6 +95,32 @@ export function useAgents(projectId: string): AgentsViewModel {
|
||||
void refresh();
|
||||
}, [refresh]);
|
||||
|
||||
// Live refresh: the agents list is otherwise only reloaded on mount or after a
|
||||
// UI-driven CRUD. An agent created/launched/stopped *out of band* — most
|
||||
// notably by the orchestrator (`spawn_agent`, ARCHITECTURE §14.3) when an AI
|
||||
// delegates agent creation to IdeA — emits `agentLaunched` / `agentExited`.
|
||||
// Subscribing here makes the tab reflect those changes without a manual reload.
|
||||
// `system` may be absent in unit tests that inject a partial gateway set; guard.
|
||||
useEffect(() => {
|
||||
if (!system) return;
|
||||
let unsubscribe: (() => void) | undefined;
|
||||
let cancelled = false;
|
||||
void system
|
||||
.onDomainEvent((event) => {
|
||||
if (event.type === "agentLaunched" || event.type === "agentExited") {
|
||||
void refresh();
|
||||
}
|
||||
})
|
||||
.then((un) => {
|
||||
if (cancelled) un();
|
||||
else unsubscribe = un;
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
unsubscribe?.();
|
||||
};
|
||||
}, [system, refresh]);
|
||||
|
||||
const createAgent = useCallback(
|
||||
async (name: string, profileId: string, initialContent?: string) => {
|
||||
setBusy(true);
|
||||
|
||||
Reference in New Issue
Block a user