@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 CHANGED
@@ -1,40 +1,21 @@
1
1
  # IAM Plugin for OpenCode
2
2
 
3
- Inter-agent messaging for parallel subagents.
3
+ Lets parallel subagents talk to each other. No configuration needed — just install and it works.
4
4
 
5
- ## The `iam` Tool
5
+ ## What It Does
6
6
 
7
- | Action | Args | Description |
8
- |--------|------|-------------|
9
- | `sessions` | - | List agents you can message |
10
- | `read` | - | Read your messages (marks as read) |
11
- | `write` | `--to <id> --message "..."` | Send a message |
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
- - **In-memory** - fast, no file clutter, resets on restart
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
- Debug logs written to `.logs/iam.log` (clears on restart). Shows all tool calls, messages sent, sessions registered, and notifications injected.
21
+ For troubleshooting, check `.logs/iam.log` (clears on restart). Shows all tool calls, messages, and notifications.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA0GjD,QAAA,MAAM,MAAM,EAAE,MAwIb,CAAA;AAED,eAAe,MAAM,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 session IDs of agents you can message
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 another agent`;
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 session ID (required for 'write')",
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
- return [
23
- `Agents you can message:
24
- `,
25
- ...agents.map((id) => `- ${id}`),
26
- ``,
27
- `Use: iam write --to <session_id> --message "..."`
28
- ].join(`
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 iam.`;
37
+ var READ_EMPTY = `No messages in your IAM inbox.`;
32
38
  function readResult(messages, unreadCount) {
33
- const lines = [`Your iam (${unreadCount} were unread):
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: iam write --to <sender_session_id> --message "..."`);
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
- var WRITE_MISSING_TO = `Error: 'to' is required. Use: iam write --to <session_id> --message "..."`;
48
- var WRITE_MISSING_MESSAGE = `Error: 'message' is required. Use: iam write --to <session_id> --message "..."`;
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
- Commands:
66
- - \`iam sessions\` - See agents you can message
67
- - \`iam read\` - Read all your messages
68
- - \`iam write --to <session_id> --message "..."\` - Send a message
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
- Check your iam when notified about new messages.
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 iam.
75
- Use \`iam read\` NOW to check your messages before continuing other work.
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
- log.info(LOG.SESSION, `Session registered`, { sessionId, totalSessions: activeSessions.size });
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
- return sessionsResult(agents);
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 msg = sendMessage(sessionId, args.to, args.message);
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 inbox_default = plugin;
354
+ var iam_default = plugin;
272
355
  export {
273
- inbox_default as default
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 session IDs of agents you can message\n- \"read\": Read all your messages (marks them as read)\n- \"write\": Send a message to another agent";
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 session ID (required for 'write')";
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: string[]): string;
9
- export declare const READ_EMPTY = "No messages in your iam.";
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. Use: iam write --to <session_id> --message \"...\"";
17
- export declare const WRITE_MISSING_MESSAGE = "Error: 'message' is required. Use: iam write --to <session_id> --message \"...\"";
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\nCommands:\n- `iam sessions` - See agents you can message\n- `iam read` - Read all your messages\n- `iam write --to <session_id> --message \"...\"` - Send a message\n\nCheck your iam when notified about new messages.\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
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../prompt.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,gBAAgB,2QAKc,CAAC;AAE5C,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAMX,eAAO,MAAM,cAAc,0JAIS,CAAC;AAErC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAOvD;AAED,eAAO,MAAM,UAAU,6BAA6B,CAAC;AAErD,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,CAeR;AAED,eAAO,MAAM,gBAAgB,gFAA8E,CAAC;AAC5G,eAAO,MAAM,qBAAqB,qFAAmF,CAAC;AAEtH,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,6UAWzB,CAAC;AAMF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoons-and-mirrors/iam",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Inter-agent messaging for OpenCode parallel subagents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",