multiagents 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/dashboard.ts +15 -2
- package/orchestrator/orchestrator-server.ts +31 -15
- package/package.json +1 -1
package/cli/dashboard.ts
CHANGED
|
@@ -168,14 +168,27 @@ interface DashboardState {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
export async function dashboard(sessionId?: string): Promise<void> {
|
|
171
|
-
const sid = sessionId ?? readLocalSession()?.session_id ?? null;
|
|
172
171
|
const client = new BrokerClient(BROKER_URL);
|
|
173
172
|
|
|
174
173
|
if (!(await client.isAlive())) {
|
|
175
|
-
console.error("Broker is not running. Start it with:
|
|
174
|
+
console.error("Broker is not running. Start it with: multiagents broker start");
|
|
176
175
|
process.exit(1);
|
|
177
176
|
}
|
|
178
177
|
|
|
178
|
+
// Resolve session ID: explicit arg > local file > most recent active session from broker > null
|
|
179
|
+
let sid = sessionId ?? readLocalSession()?.session_id ?? null;
|
|
180
|
+
if (!sid) {
|
|
181
|
+
try {
|
|
182
|
+
const sessions = await client.listSessions();
|
|
183
|
+
const active = sessions.filter((s: any) => s.status === "active" || s.status === "paused");
|
|
184
|
+
if (active.length > 0) {
|
|
185
|
+
// Pick the most recently active session
|
|
186
|
+
active.sort((a: any, b: any) => (b.last_active_at ?? 0) - (a.last_active_at ?? 0));
|
|
187
|
+
sid = active[0].id;
|
|
188
|
+
}
|
|
189
|
+
} catch { /* broker doesn't support listSessions or no sessions */ }
|
|
190
|
+
}
|
|
191
|
+
|
|
179
192
|
const state: DashboardState = {
|
|
180
193
|
session: null,
|
|
181
194
|
slots: [],
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
15
|
import type { Subprocess } from "bun";
|
|
16
16
|
|
|
17
|
+
import * as fs from "node:fs";
|
|
17
18
|
import { BrokerClient } from "../shared/broker-client.ts";
|
|
18
19
|
import type { AgentLaunchConfig } from "../shared/types.ts";
|
|
19
20
|
import { log, getGitRoot, slugify } from "../shared/utils.ts";
|
|
@@ -205,12 +206,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
205
206
|
tools: [
|
|
206
207
|
{
|
|
207
208
|
name: "create_team",
|
|
208
|
-
description: "Create a new multi-agent team session. Launches headless agents with assigned roles and file ownership.",
|
|
209
|
+
description: "Create a new multi-agent team session. Launches headless agents (separate Claude/Codex/Gemini CLI processes) with assigned roles and file ownership. The project_dir will be created if it does not exist, and git will be initialized if needed. Returns a session_id to use with all other orchestrator tools.",
|
|
209
210
|
inputSchema: {
|
|
210
211
|
type: "object" as const,
|
|
211
212
|
properties: {
|
|
212
|
-
project_dir: { type: "string", description: "Absolute path
|
|
213
|
-
session_name: { type: "string", description: "
|
|
213
|
+
project_dir: { type: "string", description: "Absolute path where agents will work. Will be created if it does not exist. Example: /Users/me/my-project" },
|
|
214
|
+
session_name: { type: "string", description: "Short name for this session. Used to generate session_id. Example: 'calculator-app'" },
|
|
214
215
|
agents: {
|
|
215
216
|
type: "array",
|
|
216
217
|
items: {
|
|
@@ -244,7 +245,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
244
245
|
},
|
|
245
246
|
{
|
|
246
247
|
name: "get_team_status",
|
|
247
|
-
description: "Get current status of all agents in a session,
|
|
248
|
+
description: "Get current status of all agents in a multiagents session — their roles, connection state, task state (idle/working/done/addressing_feedback), and what they are working on. Use the session_id returned by create_team.",
|
|
248
249
|
inputSchema: {
|
|
249
250
|
type: "object" as const,
|
|
250
251
|
properties: {
|
|
@@ -255,7 +256,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
255
256
|
},
|
|
256
257
|
{
|
|
257
258
|
name: "broadcast_to_team",
|
|
258
|
-
description: "Send a message to
|
|
259
|
+
description: "Send a message to ALL connected agents in a multiagents session. Use for requirement changes, priority shifts, or announcements that every team member must see.",
|
|
259
260
|
inputSchema: {
|
|
260
261
|
type: "object" as const,
|
|
261
262
|
properties: {
|
|
@@ -268,7 +269,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
268
269
|
},
|
|
269
270
|
{
|
|
270
271
|
name: "direct_agent",
|
|
271
|
-
description: "Send a direct message to a specific agent by name, role, or slot ID.",
|
|
272
|
+
description: "Send a direct message to a specific agent by name, role, or slot ID. The agent receives this as a peer message and must respond.",
|
|
272
273
|
inputSchema: {
|
|
273
274
|
type: "object" as const,
|
|
274
275
|
properties: {
|
|
@@ -281,7 +282,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
281
282
|
},
|
|
282
283
|
{
|
|
283
284
|
name: "add_agent",
|
|
284
|
-
description: "
|
|
285
|
+
description: "Spawn and add a new agent (Claude/Codex/Gemini CLI process) to an existing multiagents session. The agent auto-connects to the broker and receives team context.",
|
|
285
286
|
inputSchema: {
|
|
286
287
|
type: "object" as const,
|
|
287
288
|
properties: {
|
|
@@ -298,7 +299,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
298
299
|
},
|
|
299
300
|
{
|
|
300
301
|
name: "remove_agent",
|
|
301
|
-
description: "Gracefully stop and remove an agent from the session.",
|
|
302
|
+
description: "Gracefully stop and remove an agent from the session. Kills the CLI process and marks the slot as disconnected.",
|
|
302
303
|
inputSchema: {
|
|
303
304
|
type: "object" as const,
|
|
304
305
|
properties: {
|
|
@@ -310,7 +311,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
310
311
|
},
|
|
311
312
|
{
|
|
312
313
|
name: "control_session",
|
|
313
|
-
description: "Control
|
|
314
|
+
description: "Control a multiagents session. Actions: pause_all (pause every agent), resume_all (resume every agent), pause_agent (pause one by name/role), resume_agent (resume one), extend_budget (add minutes to time limit), set_budget (set exact time limit), status (get control state).",
|
|
314
315
|
inputSchema: {
|
|
315
316
|
type: "object" as const,
|
|
316
317
|
properties: {
|
|
@@ -324,7 +325,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
324
325
|
},
|
|
325
326
|
{
|
|
326
327
|
name: "adjust_guardrail",
|
|
327
|
-
description: "View or update guardrail limits
|
|
328
|
+
description: "View or update multiagents session guardrail limits (e.g. max restarts per agent). Use action='view' to see all guardrails, action='update' to change one.",
|
|
328
329
|
inputSchema: {
|
|
329
330
|
type: "object" as const,
|
|
330
331
|
properties: {
|
|
@@ -338,7 +339,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
338
339
|
},
|
|
339
340
|
{
|
|
340
341
|
name: "get_session_log",
|
|
341
|
-
description: "Get the message history for a session.",
|
|
342
|
+
description: "Get the inter-agent message history for a multiagents session. Returns timestamped messages between agents with sender/recipient info.",
|
|
342
343
|
inputSchema: {
|
|
343
344
|
type: "object" as const,
|
|
344
345
|
properties: {
|
|
@@ -351,7 +352,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
351
352
|
},
|
|
352
353
|
{
|
|
353
354
|
name: "release_agent",
|
|
354
|
-
description: "Release a specific agent, allowing it to disconnect.
|
|
355
|
+
description: "Release a specific agent from the multiagents session, allowing it to disconnect. Only use after their work is approved and complete. Agents cannot self-disconnect — only the orchestrator can release them.",
|
|
355
356
|
inputSchema: {
|
|
356
357
|
type: "object" as const,
|
|
357
358
|
properties: {
|
|
@@ -364,7 +365,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
364
365
|
},
|
|
365
366
|
{
|
|
366
367
|
name: "release_all",
|
|
367
|
-
description: "Release
|
|
368
|
+
description: "Release ALL agents in a multiagents session, allowing them to disconnect. Use when the entire team's work is complete and production-grade.",
|
|
368
369
|
inputSchema: {
|
|
369
370
|
type: "object" as const,
|
|
370
371
|
properties: {
|
|
@@ -376,7 +377,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
376
377
|
},
|
|
377
378
|
{
|
|
378
379
|
name: "end_session",
|
|
379
|
-
description: "End a session:
|
|
380
|
+
description: "End a multiagents session: releases and stops all agents, archives the session. Use when the project is complete.",
|
|
380
381
|
inputSchema: {
|
|
381
382
|
type: "object" as const,
|
|
382
383
|
properties: {
|
|
@@ -426,7 +427,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
426
427
|
}
|
|
427
428
|
|
|
428
429
|
const sessionId = slugify(session_name);
|
|
429
|
-
|
|
430
|
+
|
|
431
|
+
// Auto-create project directory if it doesn't exist
|
|
432
|
+
if (!fs.existsSync(project_dir)) {
|
|
433
|
+
fs.mkdirSync(project_dir, { recursive: true });
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Init git if not already a repo (needed for file coordination, but session works without it)
|
|
437
|
+
let gitRoot = await getGitRoot(project_dir);
|
|
438
|
+
if (!gitRoot) {
|
|
439
|
+
try {
|
|
440
|
+
const initProc = Bun.spawnSync(["git", "init"], { cwd: project_dir });
|
|
441
|
+
if (initProc.exitCode === 0) {
|
|
442
|
+
gitRoot = project_dir;
|
|
443
|
+
}
|
|
444
|
+
} catch { /* git not installed — session still works without it */ }
|
|
445
|
+
}
|
|
430
446
|
|
|
431
447
|
// Create session in broker
|
|
432
448
|
await brokerClient.createSession({
|