@spoons-and-mirrors/iam 0.1.0 → 0.1.2
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/README.md +11 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -30
- package/dist/prompt.d.ts +18 -8
- package/dist/prompt.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,40 +1,21 @@
|
|
|
1
1
|
# IAM Plugin for OpenCode
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lets parallel subagents talk to each other. No configuration needed — just install and it works.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What It Does
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Examples
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
iam sessions
|
|
17
|
-
iam read
|
|
18
|
-
iam write --to ses_abc123 --message "What approach are you using?"
|
|
19
|
-
```
|
|
7
|
+
When you spawn multiple agents with the `task` tool, they can:
|
|
8
|
+
- **Announce** what they're working on
|
|
9
|
+
- **Discover** other agents and see what they're doing
|
|
10
|
+
- **Message** each other to coordinate work
|
|
11
|
+
- Get **notified** when new messages arrive
|
|
20
12
|
|
|
21
13
|
## How It Works
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
- **Auto-discovery** - agents register on first iam use, see each other immediately
|
|
25
|
-
- **Urgent alerts** - recipients get `<system-reminder>` when they have unread mail
|
|
26
|
-
|
|
27
|
-
## Files
|
|
15
|
+
Agents get friendly names (agentA, agentB, ...) and automatically discover each other. When an agent has unread messages, they get an urgent notification.
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
iam/
|
|
31
|
-
├── index.ts # Plugin + tool + hooks
|
|
32
|
-
├── prompt.ts # LLM-facing prompts
|
|
33
|
-
├── logger.ts # Logs to .logs/iam.log
|
|
34
|
-
├── PROGRESS.md # Development history
|
|
35
|
-
└── README.md
|
|
36
|
-
```
|
|
17
|
+
The system lives in memory — fast, no file clutter, resets on restart.
|
|
37
18
|
|
|
38
|
-
## Logs
|
|
19
|
+
## Debug Logs
|
|
39
20
|
|
|
40
|
-
|
|
21
|
+
For troubleshooting, check `.logs/iam.log` (clears on restart). Shows all tool calls, messages, and notifications.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAkJjD,QAAA,MAAM,MAAM,EAAE,MAyKb,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import { tool } from "@opencode-ai/plugin";
|
|
|
5
5
|
var TOOL_DESCRIPTION = `Inter-agent messaging. Use this to communicate with other parallel agents (task tools).
|
|
6
6
|
|
|
7
7
|
Actions:
|
|
8
|
-
- "sessions": Show
|
|
8
|
+
- "sessions": Show agents you can message (e.g., agentA, agentB)
|
|
9
9
|
- "read": Read all your messages (marks them as read)
|
|
10
|
-
- "write": Send a message to
|
|
10
|
+
- "write": Send a message (requires 'to' and 'message' parameters)
|
|
11
|
+
- "announce": Announce what you're working on (requires 'message' parameter)`;
|
|
11
12
|
var ARG_DESCRIPTIONS = {
|
|
12
13
|
action: "Action to perform",
|
|
13
|
-
to: "Recipient
|
|
14
|
-
message: "Message content (required for 'write')"
|
|
14
|
+
to: "Recipient agent name, e.g. 'agentA' (required for 'write')",
|
|
15
|
+
message: "Message content (required for 'write'), or self-description (required for 'announce')"
|
|
15
16
|
};
|
|
16
17
|
var SESSIONS_EMPTY = `No other agents available yet.
|
|
17
18
|
|
|
@@ -19,18 +20,23 @@ Agents will appear here when:
|
|
|
19
20
|
- Parallel tasks are spawned by the same parent
|
|
20
21
|
- Another agent sends you a message`;
|
|
21
22
|
function sessionsResult(agents) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const lines = [`Agents you can message:
|
|
24
|
+
`];
|
|
25
|
+
for (const agent of agents) {
|
|
26
|
+
if (agent.description) {
|
|
27
|
+
lines.push(`- ${agent.alias}: ${agent.description}`);
|
|
28
|
+
} else {
|
|
29
|
+
lines.push(`- ${agent.alias}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
lines.push(``);
|
|
33
|
+
lines.push(`To send: use action="write" with to="<agent>" and message="..."`);
|
|
34
|
+
return lines.join(`
|
|
29
35
|
`);
|
|
30
36
|
}
|
|
31
|
-
var READ_EMPTY = `No messages in your
|
|
37
|
+
var READ_EMPTY = `No messages in your IAM inbox.`;
|
|
32
38
|
function readResult(messages, unreadCount) {
|
|
33
|
-
const lines = [`Your
|
|
39
|
+
const lines = [`Your IAM inbox (${unreadCount} were unread):
|
|
34
40
|
`, `---`];
|
|
35
41
|
for (const msg of messages) {
|
|
36
42
|
const time = new Date(msg.timestamp).toISOString();
|
|
@@ -40,12 +46,35 @@ function readResult(messages, unreadCount) {
|
|
|
40
46
|
lines.push(`---`);
|
|
41
47
|
}
|
|
42
48
|
lines.push(``);
|
|
43
|
-
lines.push(`To reply:
|
|
49
|
+
lines.push(`To reply: use action="write" with to="<sender>" and message="..."`);
|
|
50
|
+
return lines.join(`
|
|
51
|
+
`);
|
|
52
|
+
}
|
|
53
|
+
var WRITE_MISSING_TO = `Error: 'to' parameter is required for action="write".`;
|
|
54
|
+
var WRITE_MISSING_MESSAGE = `Error: 'message' parameter is required for action="write".`;
|
|
55
|
+
var ANNOUNCE_MISSING_MESSAGE = `Error: 'message' parameter is required for action="announce". Describe what you're working on.`;
|
|
56
|
+
function announceResult(alias, parallelAgents) {
|
|
57
|
+
const lines = [`Announced! Other agents will see your description when they list sessions.`, ``, `You are: ${alias}`];
|
|
58
|
+
if (parallelAgents.length > 0) {
|
|
59
|
+
lines.push(``);
|
|
60
|
+
lines.push(`--- Parallel Agents ---`);
|
|
61
|
+
for (const agent of parallelAgents) {
|
|
62
|
+
if (agent.description) {
|
|
63
|
+
lines.push(`• ${agent.alias} is working on: ${agent.description}`);
|
|
64
|
+
} else {
|
|
65
|
+
lines.push(`• ${agent.alias} is running (hasn't announced yet)`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
lines.push(``);
|
|
69
|
+
lines.push(`Use action="write" to coordinate with them if needed.`);
|
|
70
|
+
}
|
|
44
71
|
return lines.join(`
|
|
45
72
|
`);
|
|
46
73
|
}
|
|
47
|
-
|
|
48
|
-
|
|
74
|
+
function writeUnknownRecipient(to, known) {
|
|
75
|
+
const list = known.length > 0 ? `Known agents: ${known.join(", ")}` : "No agents available yet.";
|
|
76
|
+
return `Error: Unknown recipient "${to}". ${list}`;
|
|
77
|
+
}
|
|
49
78
|
function writeResult(to, messageId) {
|
|
50
79
|
return `Message sent!
|
|
51
80
|
|
|
@@ -58,21 +87,25 @@ function unknownAction(action) {
|
|
|
58
87
|
return `Unknown action: ${action}`;
|
|
59
88
|
}
|
|
60
89
|
var SYSTEM_PROMPT = `
|
|
90
|
+
<instructions tool="iam">
|
|
61
91
|
# Inter-Agent Messaging
|
|
62
92
|
|
|
63
93
|
You have access to an \`iam\` tool for communicating with other parallel agents.
|
|
64
94
|
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
95
|
+
Usage:
|
|
96
|
+
- action="announce", message="..." - Announce what you're working on (do this first!)
|
|
97
|
+
- action="sessions" - See other agents and what they're working on
|
|
98
|
+
- action="read" - Read your messages
|
|
99
|
+
- action="write", to="agentA", message="..." - Send a message
|
|
69
100
|
|
|
70
|
-
|
|
101
|
+
At the start of your task, use announce to let other agents know what you're doing.
|
|
102
|
+
Check your inbox when notified about new messages.
|
|
103
|
+
</instructions>
|
|
71
104
|
`;
|
|
72
105
|
function urgentNotification(unreadCount) {
|
|
73
106
|
return `<system-reminder priority="critical">
|
|
74
|
-
URGENT: You have ${unreadCount} unread message(s) in your
|
|
75
|
-
Use
|
|
107
|
+
URGENT: You have ${unreadCount} unread message(s) in your IAM inbox.
|
|
108
|
+
Use the iam tool with action="read" NOW to check your messages before continuing other work.
|
|
76
109
|
</system-reminder>`;
|
|
77
110
|
}
|
|
78
111
|
|
|
@@ -116,6 +149,30 @@ var LOG = {
|
|
|
116
149
|
// index.ts
|
|
117
150
|
var inboxes = new Map;
|
|
118
151
|
var activeSessions = new Set;
|
|
152
|
+
var sessionToAlias = new Map;
|
|
153
|
+
var aliasToSession = new Map;
|
|
154
|
+
var agentDescriptions = new Map;
|
|
155
|
+
var nextAgentIndex = 0;
|
|
156
|
+
function getNextAlias() {
|
|
157
|
+
const letter = String.fromCharCode(65 + nextAgentIndex % 26);
|
|
158
|
+
const suffix = nextAgentIndex >= 26 ? Math.floor(nextAgentIndex / 26).toString() : "";
|
|
159
|
+
nextAgentIndex++;
|
|
160
|
+
return `agent${letter}${suffix}`;
|
|
161
|
+
}
|
|
162
|
+
function getAlias(sessionId) {
|
|
163
|
+
return sessionToAlias.get(sessionId) || sessionId;
|
|
164
|
+
}
|
|
165
|
+
function setDescription(sessionId, description) {
|
|
166
|
+
const alias = getAlias(sessionId);
|
|
167
|
+
agentDescriptions.set(alias, description);
|
|
168
|
+
log.info(LOG.SESSION, `Agent announced`, { alias, description });
|
|
169
|
+
}
|
|
170
|
+
function getDescription(alias) {
|
|
171
|
+
return agentDescriptions.get(alias);
|
|
172
|
+
}
|
|
173
|
+
function resolveAlias(aliasOrSessionId) {
|
|
174
|
+
return aliasToSession.get(aliasOrSessionId) || (activeSessions.has(aliasOrSessionId) ? aliasOrSessionId : undefined);
|
|
175
|
+
}
|
|
119
176
|
function generateId() {
|
|
120
177
|
return Math.random().toString(36).substring(2, 10);
|
|
121
178
|
}
|
|
@@ -156,7 +213,7 @@ function getKnownAgents(sessionId) {
|
|
|
156
213
|
const agents = [];
|
|
157
214
|
for (const id of activeSessions) {
|
|
158
215
|
if (id !== sessionId) {
|
|
159
|
-
agents.push(id);
|
|
216
|
+
agents.push(getAlias(id));
|
|
160
217
|
}
|
|
161
218
|
}
|
|
162
219
|
return agents;
|
|
@@ -164,7 +221,10 @@ function getKnownAgents(sessionId) {
|
|
|
164
221
|
function registerSession(sessionId) {
|
|
165
222
|
if (!activeSessions.has(sessionId)) {
|
|
166
223
|
activeSessions.add(sessionId);
|
|
167
|
-
|
|
224
|
+
const alias = getNextAlias();
|
|
225
|
+
sessionToAlias.set(sessionId, alias);
|
|
226
|
+
aliasToSession.set(alias, sessionId);
|
|
227
|
+
log.info(LOG.SESSION, `Session registered`, { sessionId, alias, totalSessions: activeSessions.size });
|
|
168
228
|
}
|
|
169
229
|
}
|
|
170
230
|
var plugin = async () => {
|
|
@@ -174,7 +234,7 @@ var plugin = async () => {
|
|
|
174
234
|
iam: tool({
|
|
175
235
|
description: TOOL_DESCRIPTION,
|
|
176
236
|
args: {
|
|
177
|
-
action: tool.schema.enum(["sessions", "read", "write"]).describe(ARG_DESCRIPTIONS.action),
|
|
237
|
+
action: tool.schema.enum(["sessions", "read", "write", "announce"]).describe(ARG_DESCRIPTIONS.action),
|
|
178
238
|
to: tool.schema.string().optional().describe(ARG_DESCRIPTIONS.to),
|
|
179
239
|
message: tool.schema.string().optional().describe(ARG_DESCRIPTIONS.message)
|
|
180
240
|
},
|
|
@@ -189,7 +249,11 @@ var plugin = async () => {
|
|
|
189
249
|
if (agents.length === 0) {
|
|
190
250
|
return SESSIONS_EMPTY;
|
|
191
251
|
}
|
|
192
|
-
|
|
252
|
+
const agentsWithDesc = agents.map((alias) => ({
|
|
253
|
+
alias,
|
|
254
|
+
description: getDescription(alias)
|
|
255
|
+
}));
|
|
256
|
+
return sessionsResult(agentsWithDesc);
|
|
193
257
|
}
|
|
194
258
|
case "read": {
|
|
195
259
|
const messages = getAllMessages(sessionId);
|
|
@@ -210,9 +274,28 @@ var plugin = async () => {
|
|
|
210
274
|
log.warn(LOG.TOOL, `write missing 'message'`, { sessionId });
|
|
211
275
|
return WRITE_MISSING_MESSAGE;
|
|
212
276
|
}
|
|
213
|
-
const
|
|
277
|
+
const recipientSessionId = resolveAlias(args.to);
|
|
278
|
+
if (!recipientSessionId) {
|
|
279
|
+
log.warn(LOG.TOOL, `write unknown recipient`, { sessionId, to: args.to });
|
|
280
|
+
return writeUnknownRecipient(args.to, getKnownAgents(sessionId));
|
|
281
|
+
}
|
|
282
|
+
const senderAlias = getAlias(sessionId);
|
|
283
|
+
const msg = sendMessage(senderAlias, recipientSessionId, args.message);
|
|
214
284
|
return writeResult(args.to, msg.id);
|
|
215
285
|
}
|
|
286
|
+
case "announce": {
|
|
287
|
+
if (!args.message) {
|
|
288
|
+
log.warn(LOG.TOOL, `announce missing 'message'`, { sessionId });
|
|
289
|
+
return ANNOUNCE_MISSING_MESSAGE;
|
|
290
|
+
}
|
|
291
|
+
setDescription(sessionId, args.message);
|
|
292
|
+
const alias = getAlias(sessionId);
|
|
293
|
+
const parallelAgents = getKnownAgents(sessionId).map((agentAlias) => ({
|
|
294
|
+
alias: agentAlias,
|
|
295
|
+
description: getDescription(agentAlias)
|
|
296
|
+
}));
|
|
297
|
+
return announceResult(alias, parallelAgents);
|
|
298
|
+
}
|
|
216
299
|
default:
|
|
217
300
|
return unknownAction(args.action);
|
|
218
301
|
}
|
|
@@ -268,7 +351,7 @@ var plugin = async () => {
|
|
|
268
351
|
}
|
|
269
352
|
};
|
|
270
353
|
};
|
|
271
|
-
var
|
|
354
|
+
var iam_default = plugin;
|
|
272
355
|
export {
|
|
273
|
-
|
|
356
|
+
iam_default as default
|
|
274
357
|
};
|
package/dist/prompt.d.ts
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
|
-
export declare const TOOL_DESCRIPTION = "Inter-agent messaging. Use this to communicate with other parallel agents (task tools).\n\nActions:\n- \"sessions\": Show
|
|
1
|
+
export declare const TOOL_DESCRIPTION = "Inter-agent messaging. Use this to communicate with other parallel agents (task tools).\n\nActions:\n- \"sessions\": Show agents you can message (e.g., agentA, agentB)\n- \"read\": Read all your messages (marks them as read)\n- \"write\": Send a message (requires 'to' and 'message' parameters)\n- \"announce\": Announce what you're working on (requires 'message' parameter)";
|
|
2
2
|
export declare const ARG_DESCRIPTIONS: {
|
|
3
3
|
readonly action: "Action to perform";
|
|
4
|
-
readonly to: "Recipient
|
|
5
|
-
readonly message: "Message content (required for 'write')";
|
|
4
|
+
readonly to: "Recipient agent name, e.g. 'agentA' (required for 'write')";
|
|
5
|
+
readonly message: "Message content (required for 'write'), or self-description (required for 'announce')";
|
|
6
6
|
};
|
|
7
7
|
export declare const SESSIONS_EMPTY = "No other agents available yet.\n\nAgents will appear here when:\n- Parallel tasks are spawned by the same parent\n- Another agent sends you a message";
|
|
8
|
-
export declare function sessionsResult(agents:
|
|
9
|
-
|
|
8
|
+
export declare function sessionsResult(agents: {
|
|
9
|
+
alias: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
}[]): string;
|
|
12
|
+
export declare const READ_EMPTY = "No messages in your IAM inbox.";
|
|
10
13
|
export declare function readResult(messages: {
|
|
11
14
|
from: string;
|
|
12
15
|
body: string;
|
|
13
16
|
timestamp: number;
|
|
14
17
|
read: boolean;
|
|
15
18
|
}[], unreadCount: number): string;
|
|
16
|
-
export declare const WRITE_MISSING_TO = "Error: 'to' is required
|
|
17
|
-
export declare const WRITE_MISSING_MESSAGE = "Error: 'message' is required
|
|
19
|
+
export declare const WRITE_MISSING_TO = "Error: 'to' parameter is required for action=\"write\".";
|
|
20
|
+
export declare const WRITE_MISSING_MESSAGE = "Error: 'message' parameter is required for action=\"write\".";
|
|
21
|
+
export declare const ANNOUNCE_MISSING_MESSAGE = "Error: 'message' parameter is required for action=\"announce\". Describe what you're working on.";
|
|
22
|
+
export interface ParallelAgent {
|
|
23
|
+
alias: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function announceResult(alias: string, parallelAgents: ParallelAgent[]): string;
|
|
27
|
+
export declare function writeUnknownRecipient(to: string, known: string[]): string;
|
|
18
28
|
export declare function writeResult(to: string, messageId: string): string;
|
|
19
29
|
export declare function unknownAction(action: string): string;
|
|
20
|
-
export declare const SYSTEM_PROMPT = "\n# Inter-Agent Messaging\n\nYou have access to an `iam` tool for communicating with other parallel agents.\n\
|
|
30
|
+
export declare const SYSTEM_PROMPT = "\n<instructions tool=\"iam\">\n# Inter-Agent Messaging\n\nYou have access to an `iam` tool for communicating with other parallel agents.\n\nUsage:\n- action=\"announce\", message=\"...\" - Announce what you're working on (do this first!)\n- action=\"sessions\" - See other agents and what they're working on\n- action=\"read\" - Read your messages\n- action=\"write\", to=\"agentA\", message=\"...\" - Send a message\n\nAt the start of your task, use announce to let other agents know what you're doing.\nCheck your inbox when notified about new messages.\n</instructions>\n";
|
|
21
31
|
export declare function urgentNotification(unreadCount: number): string;
|
|
22
32
|
//# sourceMappingURL=prompt.d.ts.map
|
package/dist/prompt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../prompt.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../prompt.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,gBAAgB,2XAMgD,CAAC;AAE9E,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAMX,eAAO,MAAM,cAAc,0JAIS,CAAC;AAErC,wBAAgB,cAAc,CAAC,MAAM,EAAE;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAC,EAAE,GAAG,MAAM,CAYtF;AAED,eAAO,MAAM,UAAU,mCAAmC,CAAC;AAE3D,wBAAgB,UAAU,CACxB,QAAQ,EAAE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,EAAE,EAC1E,WAAW,EAAE,MAAM,GAClB,MAAM,CAiBR;AAED,eAAO,MAAM,gBAAgB,4DAA0D,CAAC;AACxF,eAAO,MAAM,qBAAqB,iEAA+D,CAAC;AAClG,eAAO,MAAM,wBAAwB,qGAAmG,CAAC;AAEzI,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,MAAM,CAkBrF;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAMzE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD;AAMD,eAAO,MAAM,aAAa,mkBAezB,CAAC;AAMF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D"}
|