@slock-ai/daemon 0.12.0 → 0.13.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/dist/chat-bridge.js +25 -15
- package/dist/index.js +70 -14
- package/package.json +1 -1
package/dist/chat-bridge.js
CHANGED
|
@@ -27,28 +27,38 @@ var commonHeaders = { "Content-Type": "application/json" };
|
|
|
27
27
|
if (authToken) {
|
|
28
28
|
commonHeaders["Authorization"] = `Bearer ${authToken}`;
|
|
29
29
|
}
|
|
30
|
+
function formatTarget(m) {
|
|
31
|
+
if (m.channel_type === "thread" && m.parent_channel_name) {
|
|
32
|
+
const shortId = m.channel_name.startsWith("thread-") ? m.channel_name.slice(7) : m.channel_name;
|
|
33
|
+
if (m.parent_channel_type === "dm") {
|
|
34
|
+
return `dm:@${m.parent_channel_name}:${shortId}`;
|
|
35
|
+
}
|
|
36
|
+
return `#${m.parent_channel_name}:${shortId}`;
|
|
37
|
+
}
|
|
38
|
+
if (m.channel_type === "dm") {
|
|
39
|
+
return `dm:@${m.channel_name}`;
|
|
40
|
+
}
|
|
41
|
+
return `#${m.channel_name}`;
|
|
42
|
+
}
|
|
30
43
|
var server = new McpServer({
|
|
31
44
|
name: "chat",
|
|
32
45
|
version: "1.0.0"
|
|
33
46
|
});
|
|
34
47
|
server.tool(
|
|
35
48
|
"send_message",
|
|
36
|
-
"Send a message to a channel or
|
|
49
|
+
"Send a message to a channel, DM, or thread. Use the target value from received messages to reply. Format: '#channel' for channels, 'dm:@peer' for DMs, '#channel:shortid' for threads in channels, 'dm:@peer:shortid' for threads in DMs. To start a NEW DM, use 'dm:@person-name'.",
|
|
37
50
|
{
|
|
38
|
-
|
|
39
|
-
"Where to send. Reuse the identifier from received messages: '#channel
|
|
40
|
-
),
|
|
41
|
-
dm_to: z.string().optional().describe(
|
|
42
|
-
"Person's name to start a NEW DM with (e.g. 'richard'). Only for starting a new DM \u2014 to reply in an existing DM, use channel instead."
|
|
51
|
+
target: z.string().describe(
|
|
52
|
+
"Where to send. Reuse the identifier from received messages. Format: '#channel' for channels, 'dm:@name' for DMs, '#channel:id' for channel threads, 'dm:@name:id' for DM threads. Examples: '#general', 'dm:@richard', '#general:abcd1234', 'dm:@richard:abcd1234'."
|
|
43
53
|
),
|
|
44
54
|
content: z.string().describe("The message content")
|
|
45
55
|
},
|
|
46
|
-
async ({
|
|
56
|
+
async ({ target, content }) => {
|
|
47
57
|
try {
|
|
48
58
|
const res = await fetch(`${serverUrl}/internal/agent/${agentId}/send`, {
|
|
49
59
|
method: "POST",
|
|
50
60
|
headers: commonHeaders,
|
|
51
|
-
body: JSON.stringify({
|
|
61
|
+
body: JSON.stringify({ target, content })
|
|
52
62
|
});
|
|
53
63
|
const data = await res.json();
|
|
54
64
|
if (!res.ok) {
|
|
@@ -62,7 +72,7 @@ server.tool(
|
|
|
62
72
|
content: [
|
|
63
73
|
{
|
|
64
74
|
type: "text",
|
|
65
|
-
text: `Message sent to ${
|
|
75
|
+
text: `Message sent to ${target}`
|
|
66
76
|
}
|
|
67
77
|
]
|
|
68
78
|
};
|
|
@@ -75,7 +85,7 @@ server.tool(
|
|
|
75
85
|
);
|
|
76
86
|
server.tool(
|
|
77
87
|
"receive_message",
|
|
78
|
-
"Receive new messages. Use block=true to wait for new messages. Returns messages formatted as [#channel
|
|
88
|
+
"Receive new messages. Use block=true to wait for new messages. Returns messages formatted as [#channel], [dm:@peer], or [thread:#channel:id] followed by the sender and content.",
|
|
79
89
|
{
|
|
80
90
|
block: z.boolean().default(true).describe("Whether to block (wait) for new messages"),
|
|
81
91
|
timeout_ms: z.number().default(59e3).describe("How long to wait in ms when blocking (default 59s, just under MCP tool call timeout)")
|
|
@@ -96,10 +106,10 @@ server.tool(
|
|
|
96
106
|
};
|
|
97
107
|
}
|
|
98
108
|
const formatted = data.messages.map((m) => {
|
|
99
|
-
const
|
|
109
|
+
const target = formatTarget(m);
|
|
100
110
|
const senderPrefix = m.sender_type === "agent" ? "(agent) " : "";
|
|
101
111
|
const time = m.timestamp ? ` (${toLocalTime(m.timestamp)})` : "";
|
|
102
|
-
return `[${
|
|
112
|
+
return `[${target}]${time} ${senderPrefix}@${m.sender_name}: ${m.content}`;
|
|
103
113
|
}).join("\n");
|
|
104
114
|
return {
|
|
105
115
|
content: [{ type: "text", text: formatted }]
|
|
@@ -146,7 +156,7 @@ server.tool(
|
|
|
146
156
|
text += " (none)\n";
|
|
147
157
|
}
|
|
148
158
|
text += "\n### Humans\n";
|
|
149
|
-
text += 'To start a new DM: send_message(
|
|
159
|
+
text += 'To start a new DM: send_message(target="dm:@name"). To reply in an existing DM: reuse the target from received messages.\n';
|
|
150
160
|
if (data.humans?.length > 0) {
|
|
151
161
|
for (const u of data.humans) {
|
|
152
162
|
text += ` - @${u.name}
|
|
@@ -167,9 +177,9 @@ server.tool(
|
|
|
167
177
|
);
|
|
168
178
|
server.tool(
|
|
169
179
|
"read_history",
|
|
170
|
-
"Read message history for a channel or
|
|
180
|
+
"Read message history for a channel, DM, or thread. Use the same target format: '#channel', 'dm:@name', '#channel:id' for threads, 'dm:@name:id' for DM threads. Supports pagination: use 'before' to load older messages, 'after' to load messages after a seq number (e.g. to catch up on unread).",
|
|
171
181
|
{
|
|
172
|
-
channel: z.string().describe("The
|
|
182
|
+
channel: z.string().describe("The target to read history from \u2014 e.g. '#general', 'dm:@richard', '#general:abcd1234', 'dm:@richard:abcd1234'"),
|
|
173
183
|
limit: z.number().default(50).describe("Max number of messages to return (default 50, max 100)"),
|
|
174
184
|
before: z.number().optional().describe("Return messages before this seq number (for backward pagination). Omit for latest messages."),
|
|
175
185
|
after: z.number().optional().describe("Return messages after this seq number (for catching up on unread). Returns oldest-first.")
|
package/dist/index.js
CHANGED
|
@@ -144,19 +144,31 @@ ${opts.postStartupNotes.join("\n")}`;
|
|
|
144
144
|
## Messaging
|
|
145
145
|
|
|
146
146
|
Messages you receive look like:
|
|
147
|
-
- **Channel message
|
|
148
|
-
- **Channel message from an agent**: \`[#
|
|
149
|
-
- **DM
|
|
147
|
+
- **Channel message**: \`[#general] @richard: hello everyone\`
|
|
148
|
+
- **Channel message from an agent**: \`[#general] (agent) @Alice: hi there\`
|
|
149
|
+
- **DM**: \`[dm:@richard] @richard: hey, can you help?\`
|
|
150
|
+
- **Thread in a channel**: \`[#general:a1b2c3] @richard: replying in thread\`
|
|
151
|
+
- **Thread in a DM**: \`[dm:@richard:x9y8z7] @richard: thread reply\`
|
|
150
152
|
|
|
151
|
-
The \`[...]\` prefix identifies where the message came from. Reuse it as the \`
|
|
153
|
+
The \`[...]\` prefix is the **target** \u2014 it identifies where the message came from. Reuse it exactly as the \`target\` parameter when replying.
|
|
152
154
|
|
|
153
155
|
### Sending messages
|
|
154
156
|
|
|
155
|
-
- **Reply to a channel**: \`send_message(
|
|
156
|
-
- **Reply to a DM**: \`send_message(
|
|
157
|
-
- **
|
|
157
|
+
- **Reply to a channel**: \`send_message(target="#channel-name", content="...")\`
|
|
158
|
+
- **Reply to a DM**: \`send_message(target="dm:@peer-name", content="...")\`
|
|
159
|
+
- **Reply in a thread**: \`send_message(target="#channel:shortid", content="...")\` or \`send_message(target="dm:@peer:shortid", content="...")\`
|
|
160
|
+
- **Start a NEW DM**: \`send_message(target="dm:@person-name", content="...")\`
|
|
158
161
|
|
|
159
|
-
**IMPORTANT**: To reply to any message
|
|
162
|
+
**IMPORTANT**: To reply to any message, always reuse the exact \`target\` from the received message. This ensures your reply goes to the right place \u2014 whether it's a channel, DM, or thread.
|
|
163
|
+
|
|
164
|
+
### Threads
|
|
165
|
+
|
|
166
|
+
Threads are sub-conversations attached to a specific message. They let you discuss a topic without cluttering the main channel.
|
|
167
|
+
|
|
168
|
+
- **Thread targets** have a colon and short ID suffix: \`#general:a1b2c3\` (thread in #general) or \`dm:@richard:x9y8z7\` (thread in a DM).
|
|
169
|
+
- When you receive a message from a thread (the target has a \`:shortid\` suffix), **always reply using that same target** to keep the conversation in the thread.
|
|
170
|
+
- You can read thread history: \`read_history(channel="#general:a1b2c3")\`
|
|
171
|
+
- Threads cannot be nested \u2014 you cannot start a thread inside a thread.
|
|
160
172
|
|
|
161
173
|
### Discovering people and channels
|
|
162
174
|
|
|
@@ -165,13 +177,13 @@ Call \`list_server\` to see all channels in this server, which ones you have joi
|
|
|
165
177
|
### Channel awareness
|
|
166
178
|
|
|
167
179
|
Each channel has a **name** and optionally a **description** that define its purpose (visible via \`list_server\`). Respect them:
|
|
168
|
-
- **Reply in context** \u2014 always respond in the channel the message came from.
|
|
180
|
+
- **Reply in context** \u2014 always respond in the channel/thread the message came from.
|
|
169
181
|
- **Stay on topic** \u2014 when proactively sharing results or updates, post in the channel most relevant to the work. Don't scatter messages across unrelated channels.
|
|
170
182
|
- If unsure where something belongs, call \`list_server\` to review channel descriptions.
|
|
171
183
|
|
|
172
184
|
### Reading history
|
|
173
185
|
|
|
174
|
-
\`read_history(channel="#channel-name")\` or \`read_history(channel="
|
|
186
|
+
\`read_history(channel="#channel-name")\` or \`read_history(channel="dm:@peer-name")\` or \`read_history(channel="#channel:shortid")\`
|
|
175
187
|
|
|
176
188
|
### Task boards
|
|
177
189
|
|
|
@@ -472,9 +484,9 @@ var ClaudeDriver = class {
|
|
|
472
484
|
if (name === "WebFetch" || name === "web_fetch") return input.url || "";
|
|
473
485
|
if (name === "WebSearch" || name === "web_search") return input.query || "";
|
|
474
486
|
if (name === "mcp__chat__send_message") {
|
|
475
|
-
return input.channel || (input.dm_to ? `DM:@${input.dm_to}` : "");
|
|
487
|
+
return input.target || input.channel || (input.dm_to ? `DM:@${input.dm_to}` : "");
|
|
476
488
|
}
|
|
477
|
-
if (name === "mcp__chat__read_history") return input.channel || "";
|
|
489
|
+
if (name === "mcp__chat__read_history") return input.target || input.channel || "";
|
|
478
490
|
if (name === "mcp__chat__list_tasks") return input.channel || "";
|
|
479
491
|
if (name === "mcp__chat__create_tasks") return input.channel || "";
|
|
480
492
|
if (name === "mcp__chat__claim_tasks") {
|
|
@@ -683,9 +695,9 @@ var CodexDriver = class {
|
|
|
683
695
|
if (name === "file_write") return input.path || input.file_path || "";
|
|
684
696
|
if (name === "web_search") return input.query || "";
|
|
685
697
|
if (name === `${this.mcpToolPrefix}send_message`) {
|
|
686
|
-
return input.channel || (input.dm_to ? `DM:@${input.dm_to}` : "");
|
|
698
|
+
return input.target || input.channel || (input.dm_to ? `DM:@${input.dm_to}` : "");
|
|
687
699
|
}
|
|
688
|
-
if (name === `${this.mcpToolPrefix}read_history`) return input.channel || "";
|
|
700
|
+
if (name === `${this.mcpToolPrefix}read_history`) return input.target || input.channel || "";
|
|
689
701
|
if (name === `${this.mcpToolPrefix}list_tasks`) return input.channel || "";
|
|
690
702
|
if (name === `${this.mcpToolPrefix}create_tasks`) return input.channel || "";
|
|
691
703
|
if (name === `${this.mcpToolPrefix}claim_tasks`) {
|
|
@@ -1191,6 +1203,50 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1191
1203
|
}
|
|
1192
1204
|
};
|
|
1193
1205
|
|
|
1206
|
+
// ../shared/src/serverPermissions.ts
|
|
1207
|
+
var EMPTY_SERVER_CAPABILITIES = Object.freeze({
|
|
1208
|
+
manageServer: false,
|
|
1209
|
+
manageChannels: false,
|
|
1210
|
+
manageAgents: false,
|
|
1211
|
+
manageMachines: false,
|
|
1212
|
+
manageMembers: false,
|
|
1213
|
+
changeMemberRoles: false,
|
|
1214
|
+
manageBilling: false,
|
|
1215
|
+
joinPublicChannels: false
|
|
1216
|
+
});
|
|
1217
|
+
var SERVER_CAPABILITY_MATRIX = {
|
|
1218
|
+
owner: Object.freeze({
|
|
1219
|
+
manageServer: true,
|
|
1220
|
+
manageChannels: true,
|
|
1221
|
+
manageAgents: true,
|
|
1222
|
+
manageMachines: true,
|
|
1223
|
+
manageMembers: true,
|
|
1224
|
+
changeMemberRoles: true,
|
|
1225
|
+
manageBilling: true,
|
|
1226
|
+
joinPublicChannels: true
|
|
1227
|
+
}),
|
|
1228
|
+
admin: Object.freeze({
|
|
1229
|
+
manageServer: true,
|
|
1230
|
+
manageChannels: true,
|
|
1231
|
+
manageAgents: true,
|
|
1232
|
+
manageMachines: true,
|
|
1233
|
+
manageMembers: true,
|
|
1234
|
+
changeMemberRoles: false,
|
|
1235
|
+
manageBilling: false,
|
|
1236
|
+
joinPublicChannels: true
|
|
1237
|
+
}),
|
|
1238
|
+
member: Object.freeze({
|
|
1239
|
+
manageServer: false,
|
|
1240
|
+
manageChannels: false,
|
|
1241
|
+
manageAgents: false,
|
|
1242
|
+
manageMachines: false,
|
|
1243
|
+
manageMembers: false,
|
|
1244
|
+
changeMemberRoles: false,
|
|
1245
|
+
manageBilling: false,
|
|
1246
|
+
joinPublicChannels: true
|
|
1247
|
+
})
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1194
1250
|
// ../shared/src/index.ts
|
|
1195
1251
|
var RUNTIMES = [
|
|
1196
1252
|
{ id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
|