multiagents 0.1.0
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/.mcp.json +12 -0
- package/README.md +184 -0
- package/adapters/base-adapter.ts +1493 -0
- package/adapters/claude-adapter.ts +66 -0
- package/adapters/codex-adapter.ts +135 -0
- package/adapters/gemini-adapter.ts +129 -0
- package/broker.ts +1263 -0
- package/cli/commands.ts +194 -0
- package/cli/dashboard.ts +988 -0
- package/cli/session.ts +278 -0
- package/cli/setup.ts +257 -0
- package/cli.ts +17 -0
- package/index.ts +41 -0
- package/noop-mcp.ts +63 -0
- package/orchestrator/guardrails.ts +243 -0
- package/orchestrator/launcher.ts +433 -0
- package/orchestrator/monitor.ts +285 -0
- package/orchestrator/orchestrator-server.ts +1000 -0
- package/orchestrator/progress.ts +214 -0
- package/orchestrator/recovery.ts +176 -0
- package/orchestrator/session-control.ts +343 -0
- package/package.json +70 -0
- package/scripts/postinstall.ts +84 -0
- package/scripts/version.ts +62 -0
- package/server.ts +52 -0
- package/shared/broker-client.ts +243 -0
- package/shared/constants.ts +148 -0
- package/shared/summarize.ts +97 -0
- package/shared/types.ts +419 -0
- package/shared/utils.ts +121 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* ClaudeAdapter — MCP adapter for Claude Code instances.
|
|
4
|
+
*
|
|
5
|
+
* Uses the experimental claude/channel capability to push inbound
|
|
6
|
+
* messages directly into the Claude session as channel notifications.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseAdapter } from "./base-adapter.ts";
|
|
10
|
+
import type { BufferedMessage } from "../shared/types.ts";
|
|
11
|
+
|
|
12
|
+
export class ClaudeAdapter extends BaseAdapter {
|
|
13
|
+
constructor() {
|
|
14
|
+
super("claude");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getCapabilities(): Record<string, unknown> {
|
|
18
|
+
return {
|
|
19
|
+
experimental: { "claude/channel": {} },
|
|
20
|
+
tools: {},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getSystemPrompt(): string {
|
|
25
|
+
const base = `You are a team member on the multiagents network. Other agents can see you and message you in real-time.
|
|
26
|
+
|
|
27
|
+
CHANNEL MESSAGES: When you receive a <channel source="multiagents" ...> message, RESPOND IMMEDIATELY. Pause your current work, reply via send_message, then resume. Treat peer messages like a senior teammate tapping your shoulder — answer right away.
|
|
28
|
+
|
|
29
|
+
Read from_id, from_summary, from_cwd, from_role to understand the sender. Reply using send_message with their from_id.
|
|
30
|
+
|
|
31
|
+
TOOLS:
|
|
32
|
+
- list_peers / check_team_status: See who's on the team, their roles, and status
|
|
33
|
+
- send_message / check_messages: Communicate with teammates
|
|
34
|
+
- set_summary: Broadcast what you're working on (keep updated as you progress)
|
|
35
|
+
- signal_done: Signal your work is complete and ready for review
|
|
36
|
+
- submit_feedback / approve: Review teammates' work
|
|
37
|
+
- acquire_file / release_file / view_file_locks: Coordinate file edits
|
|
38
|
+
- get_plan / update_plan: Track team progress against the plan
|
|
39
|
+
- get_history: Review past messages
|
|
40
|
+
|
|
41
|
+
ON START: Call set_summary immediately to describe your current task. Call check_team_status to understand who else is working and on what. Call get_plan to see the team's plan and your assigned items.
|
|
42
|
+
|
|
43
|
+
QUALITY STANDARD: You produce production-grade code. Plan before coding. Verify before signaling done. Fix root causes, not symptoms. Keep solutions simple and clean.`;
|
|
44
|
+
|
|
45
|
+
if (this.roleContext) {
|
|
46
|
+
return `${base}\n\n--- ROLE CONTEXT ---\n${this.roleContext}`;
|
|
47
|
+
}
|
|
48
|
+
return base;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async deliverMessage(msg: BufferedMessage): Promise<void> {
|
|
52
|
+
await this.mcp.notification({
|
|
53
|
+
method: "notifications/claude/channel",
|
|
54
|
+
params: {
|
|
55
|
+
content: msg.text,
|
|
56
|
+
meta: {
|
|
57
|
+
from_id: msg.from_id,
|
|
58
|
+
from_summary: msg.from_summary ?? "",
|
|
59
|
+
from_cwd: msg.from_cwd ?? "",
|
|
60
|
+
from_role: msg.from_role ?? "",
|
|
61
|
+
sent_at: msg.sent_at,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* CodexAdapter — MCP adapter for Codex CLI instances.
|
|
4
|
+
*
|
|
5
|
+
* Codex has no channel/push capability. Messages are buffered in memory
|
|
6
|
+
* and delivered piggybacked on the next tool response.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseAdapter } from "./base-adapter.ts";
|
|
10
|
+
import type { BufferedMessage } from "../shared/types.ts";
|
|
11
|
+
|
|
12
|
+
export class CodexAdapter extends BaseAdapter {
|
|
13
|
+
private messageBuffer: BufferedMessage[] = [];
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
super("codex");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getCapabilities(): Record<string, unknown> {
|
|
20
|
+
return {
|
|
21
|
+
tools: {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getSystemPrompt(): string {
|
|
26
|
+
const base = `You are a team member on the multiagents network via Codex CLI. Other agents can see you and message you.
|
|
27
|
+
|
|
28
|
+
MESSAGE DELIVERY: You do not have push notifications. Messages arrive in two ways:
|
|
29
|
+
1. Piggybacked on tool responses — "[PENDING MESSAGES]" at the top of any tool result. Read these FIRST.
|
|
30
|
+
2. Via check_messages — call this after EVERY shell command and every 3-5 tool calls.
|
|
31
|
+
|
|
32
|
+
TOOLS:
|
|
33
|
+
- list_peers / check_team_status: See who's on the team, their roles, and status
|
|
34
|
+
- send_message / check_messages: Communicate with teammates (check_messages is your lifeline — call it constantly)
|
|
35
|
+
- set_summary: Broadcast what you're working on (keep updated as you progress)
|
|
36
|
+
- signal_done: Signal your work is complete and ready for review
|
|
37
|
+
- submit_feedback / approve: Review teammates' work
|
|
38
|
+
- acquire_file / release_file / view_file_locks: Coordinate file edits
|
|
39
|
+
- get_plan / update_plan: Track team progress against the plan
|
|
40
|
+
- get_history: Review past messages
|
|
41
|
+
|
|
42
|
+
ON START: Call set_summary, check_messages, and check_team_status immediately. Call get_plan to see your assigned items.
|
|
43
|
+
|
|
44
|
+
CRITICAL: Call check_messages after EVERY shell command. Teammate messages are only delivered when you use multiagents tools. Missing a message means blocking your team.
|
|
45
|
+
|
|
46
|
+
QUALITY STANDARD: You produce production-grade code. Plan before coding. Verify before signaling done. Fix root causes, not symptoms. Keep solutions simple and clean.`;
|
|
47
|
+
|
|
48
|
+
if (this.roleContext) {
|
|
49
|
+
return `${base}\n\n--- ROLE CONTEXT ---\n${this.roleContext}`;
|
|
50
|
+
}
|
|
51
|
+
return base;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async deliverMessage(msg: BufferedMessage): Promise<void> {
|
|
55
|
+
this.messageBuffer.push(msg);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// --- Piggyback delivery ---
|
|
59
|
+
|
|
60
|
+
protected wrapToolResult(result: string): string {
|
|
61
|
+
if (this.messageBuffer.length === 0) {
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const pending = this.messageBuffer
|
|
66
|
+
.map((m) => this.formatMessage(m))
|
|
67
|
+
.join("\n");
|
|
68
|
+
this.messageBuffer = [];
|
|
69
|
+
|
|
70
|
+
return `[PENDING MESSAGES]\n${pending}\n[END PENDING MESSAGES]\n\n${result}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// --- Override all tool handlers to wrap results ---
|
|
74
|
+
|
|
75
|
+
protected override async handleListPeers(args: any) {
|
|
76
|
+
const result = await super.handleListPeers(args);
|
|
77
|
+
return this.wrapResult(result);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
protected override async handleSendMessage(args: any) {
|
|
81
|
+
const result = await super.handleSendMessage(args);
|
|
82
|
+
return this.wrapResult(result);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
protected override async handleSetSummary(args: any) {
|
|
86
|
+
const result = await super.handleSetSummary(args);
|
|
87
|
+
return this.wrapResult(result);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
protected override async handleCheckMessages() {
|
|
91
|
+
const result = await super.handleCheckMessages();
|
|
92
|
+
return this.wrapResult(result);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected override async handleAssignRole(args: any) {
|
|
96
|
+
const result = await super.handleAssignRole(args);
|
|
97
|
+
return this.wrapResult(result);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
protected override async handleRenamePeer(args: any) {
|
|
101
|
+
const result = await super.handleRenamePeer(args);
|
|
102
|
+
return this.wrapResult(result);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
protected override async handleAcquireFile(args: any) {
|
|
106
|
+
const result = await super.handleAcquireFile(args);
|
|
107
|
+
return this.wrapResult(result);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected override async handleReleaseFile(args: any) {
|
|
111
|
+
const result = await super.handleReleaseFile(args);
|
|
112
|
+
return this.wrapResult(result);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected override async handleViewFileLocks() {
|
|
116
|
+
const result = await super.handleViewFileLocks();
|
|
117
|
+
return this.wrapResult(result);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected override async handleGetHistory(args: any) {
|
|
121
|
+
const result = await super.handleGetHistory(args);
|
|
122
|
+
return this.wrapResult(result);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// --- Helper to wrap a tool result object ---
|
|
126
|
+
|
|
127
|
+
private wrapResult(result: { content: { type: "text"; text: string }[]; isError?: boolean }) {
|
|
128
|
+
const text = result.content[0]?.text ?? "";
|
|
129
|
+
const wrapped = this.wrapToolResult(text);
|
|
130
|
+
return {
|
|
131
|
+
...result,
|
|
132
|
+
content: [{ type: "text" as const, text: wrapped }],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* GeminiAdapter — MCP adapter for Gemini CLI instances.
|
|
4
|
+
*
|
|
5
|
+
* Nearly identical to CodexAdapter: no push capability, messages are
|
|
6
|
+
* buffered and piggybacked on tool responses.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { BaseAdapter } from "./base-adapter.ts";
|
|
10
|
+
import type { BufferedMessage } from "../shared/types.ts";
|
|
11
|
+
|
|
12
|
+
export class GeminiAdapter extends BaseAdapter {
|
|
13
|
+
private messageBuffer: BufferedMessage[] = [];
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
super("gemini");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getCapabilities(): Record<string, unknown> {
|
|
20
|
+
return {
|
|
21
|
+
tools: {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getSystemPrompt(): string {
|
|
26
|
+
const base = `You are a team member on the multiagents network via Gemini CLI. Other agents can see you and message you.
|
|
27
|
+
|
|
28
|
+
MESSAGE DELIVERY: You do not have push notifications. Messages arrive in two ways:
|
|
29
|
+
1. Piggybacked on tool responses — "[PENDING MESSAGES]" at the top of any tool result. Read these FIRST.
|
|
30
|
+
2. Via check_messages — call this after EVERY shell command and every 3-5 tool calls.
|
|
31
|
+
|
|
32
|
+
TOOLS:
|
|
33
|
+
- list_peers / check_team_status: See who's on the team, their roles, and status
|
|
34
|
+
- send_message / check_messages: Communicate with teammates (check_messages is your lifeline — call it constantly)
|
|
35
|
+
- set_summary: Broadcast what you're working on (keep updated as you progress)
|
|
36
|
+
- signal_done: Signal your work is complete and ready for review
|
|
37
|
+
- submit_feedback / approve: Review teammates' work
|
|
38
|
+
- acquire_file / release_file / view_file_locks: Coordinate file edits
|
|
39
|
+
- get_plan / update_plan: Track team progress against the plan
|
|
40
|
+
- get_history: Review past messages
|
|
41
|
+
|
|
42
|
+
ON START: Call set_summary, check_messages, and check_team_status immediately. Call get_plan to see your assigned items.
|
|
43
|
+
|
|
44
|
+
CRITICAL: Call check_messages after EVERY shell command. Teammate messages are only delivered when you use multiagents tools. Missing a message means blocking your team.
|
|
45
|
+
|
|
46
|
+
QUALITY STANDARD: You produce production-grade code. Plan before coding. Verify before signaling done. Fix root causes, not symptoms. Keep solutions simple and clean.`;
|
|
47
|
+
|
|
48
|
+
if (this.roleContext) {
|
|
49
|
+
return `${base}\n\n--- ROLE CONTEXT ---\n${this.roleContext}`;
|
|
50
|
+
}
|
|
51
|
+
return base;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async deliverMessage(msg: BufferedMessage): Promise<void> {
|
|
55
|
+
this.messageBuffer.push(msg);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected wrapToolResult(result: string): string {
|
|
59
|
+
if (this.messageBuffer.length === 0) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const pending = this.messageBuffer
|
|
64
|
+
.map((m) => this.formatMessage(m))
|
|
65
|
+
.join("\n");
|
|
66
|
+
this.messageBuffer = [];
|
|
67
|
+
|
|
68
|
+
return `[PENDING MESSAGES]\n${pending}\n[END PENDING MESSAGES]\n\n${result}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected override async handleListPeers(args: any) {
|
|
72
|
+
const r = await super.handleListPeers(args);
|
|
73
|
+
return this.wrapResult(r);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected override async handleSendMessage(args: any) {
|
|
77
|
+
const r = await super.handleSendMessage(args);
|
|
78
|
+
return this.wrapResult(r);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected override async handleSetSummary(args: any) {
|
|
82
|
+
const r = await super.handleSetSummary(args);
|
|
83
|
+
return this.wrapResult(r);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
protected override async handleCheckMessages() {
|
|
87
|
+
const r = await super.handleCheckMessages();
|
|
88
|
+
return this.wrapResult(r);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
protected override async handleAssignRole(args: any) {
|
|
92
|
+
const r = await super.handleAssignRole(args);
|
|
93
|
+
return this.wrapResult(r);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected override async handleRenamePeer(args: any) {
|
|
97
|
+
const r = await super.handleRenamePeer(args);
|
|
98
|
+
return this.wrapResult(r);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
protected override async handleAcquireFile(args: any) {
|
|
102
|
+
const r = await super.handleAcquireFile(args);
|
|
103
|
+
return this.wrapResult(r);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected override async handleReleaseFile(args: any) {
|
|
107
|
+
const r = await super.handleReleaseFile(args);
|
|
108
|
+
return this.wrapResult(r);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
protected override async handleViewFileLocks() {
|
|
112
|
+
const r = await super.handleViewFileLocks();
|
|
113
|
+
return this.wrapResult(r);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected override async handleGetHistory(args: any) {
|
|
117
|
+
const r = await super.handleGetHistory(args);
|
|
118
|
+
return this.wrapResult(r);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private wrapResult(result: { content: { type: "text"; text: string }[]; isError?: boolean }) {
|
|
122
|
+
const text = result.content[0]?.text ?? "";
|
|
123
|
+
const wrapped = this.wrapToolResult(text);
|
|
124
|
+
return {
|
|
125
|
+
...result,
|
|
126
|
+
content: [{ type: "text" as const, text: wrapped }],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|