@slock-ai/daemon 0.43.0 → 0.46.0-play.20260508161002
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 +27 -110
- package/dist/{chunk-37O7EHYE.js → chunk-MEY33LAG.js} +2315 -277
- package/dist/{chunk-JG7ONJZ6.js → chunk-Z3PCMYZO.js} +101 -1
- package/dist/cli/index.js +268 -51
- package/dist/core.js +2 -2
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/dist/chat-bridge.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
3
4
|
buildFetchDispatcher,
|
|
5
|
+
executeJsonRequest,
|
|
6
|
+
executeResponseRequest,
|
|
4
7
|
logger
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-Z3PCMYZO.js";
|
|
6
9
|
|
|
7
10
|
// src/chat-bridge.ts
|
|
8
11
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -31,7 +34,7 @@ var searchMessagesDeprecatedSchema = {
|
|
|
31
34
|
};
|
|
32
35
|
var listTasksDeprecatedSchema = {
|
|
33
36
|
channel: z.string().describe("Deprecated channel argument."),
|
|
34
|
-
status: z.enum(["all", "todo", "in_progress", "in_review", "done"]).optional().describe("Deprecated status argument.")
|
|
37
|
+
status: z.enum(["all", "todo", "in_progress", "in_review", "done", "closed"]).optional().describe("Deprecated status argument.")
|
|
35
38
|
};
|
|
36
39
|
var claimTasksDeprecatedSchema = {
|
|
37
40
|
channel: z.string().describe("Deprecated channel argument."),
|
|
@@ -45,7 +48,7 @@ var unclaimTaskDeprecatedSchema = {
|
|
|
45
48
|
var updateTaskStatusDeprecatedSchema = {
|
|
46
49
|
channel: z.string().describe("Deprecated channel argument."),
|
|
47
50
|
task_number: z.number().describe("Deprecated task number."),
|
|
48
|
-
status: z.enum(["todo", "in_progress", "in_review", "done"]).describe("Deprecated status argument.")
|
|
51
|
+
status: z.enum(["todo", "in_progress", "in_review", "done", "closed"]).describe("Deprecated status argument.")
|
|
49
52
|
};
|
|
50
53
|
var DEPRECATED_MCP_TOOL_DEFINITIONS = [
|
|
51
54
|
{
|
|
@@ -164,103 +167,6 @@ function formatHistoryMessageLine(message) {
|
|
|
164
167
|
return `[${headerParts.join(" ")}] ${formatHistorySenderHandle(message)}: ${message.content}${attachSuffix}${taskSuffix}`;
|
|
165
168
|
}
|
|
166
169
|
|
|
167
|
-
// src/chatBridgeRequest.ts
|
|
168
|
-
var DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS = Number.parseInt(
|
|
169
|
-
process.env.SLOCK_CHAT_BRIDGE_TOOL_TIMEOUT_MS || "",
|
|
170
|
-
10
|
|
171
|
-
) || 6e4;
|
|
172
|
-
var ChatBridgeToolTimeoutError = class extends Error {
|
|
173
|
-
toolName;
|
|
174
|
-
target;
|
|
175
|
-
timeoutMs;
|
|
176
|
-
durationMs;
|
|
177
|
-
constructor(toolName, target, timeoutMs, durationMs) {
|
|
178
|
-
super(`${toolName} timed out after ${timeoutMs}ms${target ? ` (target: ${target})` : ""}`);
|
|
179
|
-
this.name = "ChatBridgeToolTimeoutError";
|
|
180
|
-
this.toolName = toolName;
|
|
181
|
-
this.target = target;
|
|
182
|
-
this.timeoutMs = timeoutMs;
|
|
183
|
-
this.durationMs = durationMs;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
function describeError(err) {
|
|
187
|
-
if (err instanceof Error) return `${err.name}: ${err.message}`;
|
|
188
|
-
return String(err);
|
|
189
|
-
}
|
|
190
|
-
async function executeJsonRequest(url, init, {
|
|
191
|
-
toolName,
|
|
192
|
-
target = null,
|
|
193
|
-
timeoutMs = DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
194
|
-
fetchImpl,
|
|
195
|
-
now = () => Date.now(),
|
|
196
|
-
warn = (message) => logger.warn(message)
|
|
197
|
-
}) {
|
|
198
|
-
const startedAt = now();
|
|
199
|
-
const timeoutController = new AbortController();
|
|
200
|
-
const signals = [timeoutController.signal];
|
|
201
|
-
if (init.signal) signals.push(init.signal);
|
|
202
|
-
const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
203
|
-
const timeout = setTimeout(() => {
|
|
204
|
-
timeoutController.abort();
|
|
205
|
-
}, timeoutMs);
|
|
206
|
-
timeout.unref?.();
|
|
207
|
-
try {
|
|
208
|
-
const response = await fetchImpl(url, { ...init, signal });
|
|
209
|
-
const data = await response.json();
|
|
210
|
-
return { response, data, durationMs: now() - startedAt };
|
|
211
|
-
} catch (err) {
|
|
212
|
-
const durationMs = now() - startedAt;
|
|
213
|
-
if (timeoutController.signal.aborted && !init.signal?.aborted) {
|
|
214
|
-
warn(
|
|
215
|
-
`[ChatBridgeTimeout] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} timeout_ms=${timeoutMs} outcome=timeout`
|
|
216
|
-
);
|
|
217
|
-
throw new ChatBridgeToolTimeoutError(toolName, target, timeoutMs, durationMs);
|
|
218
|
-
}
|
|
219
|
-
warn(
|
|
220
|
-
`[ChatBridgeError] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} outcome=error error=${describeError(err)}`
|
|
221
|
-
);
|
|
222
|
-
throw err;
|
|
223
|
-
} finally {
|
|
224
|
-
clearTimeout(timeout);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
async function executeResponseRequest(url, init, {
|
|
228
|
-
toolName,
|
|
229
|
-
target = null,
|
|
230
|
-
timeoutMs = DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
231
|
-
fetchImpl,
|
|
232
|
-
now = () => Date.now(),
|
|
233
|
-
warn = (message) => logger.warn(message)
|
|
234
|
-
}) {
|
|
235
|
-
const startedAt = now();
|
|
236
|
-
const timeoutController = new AbortController();
|
|
237
|
-
const signals = [timeoutController.signal];
|
|
238
|
-
if (init.signal) signals.push(init.signal);
|
|
239
|
-
const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
240
|
-
const timeout = setTimeout(() => {
|
|
241
|
-
timeoutController.abort();
|
|
242
|
-
}, timeoutMs);
|
|
243
|
-
timeout.unref?.();
|
|
244
|
-
try {
|
|
245
|
-
const response = await fetchImpl(url, { ...init, signal });
|
|
246
|
-
return { response, durationMs: now() - startedAt };
|
|
247
|
-
} catch (err) {
|
|
248
|
-
const durationMs = now() - startedAt;
|
|
249
|
-
if (timeoutController.signal.aborted && !init.signal?.aborted) {
|
|
250
|
-
warn(
|
|
251
|
-
`[ChatBridgeTimeout] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} timeout_ms=${timeoutMs} outcome=timeout`
|
|
252
|
-
);
|
|
253
|
-
throw new ChatBridgeToolTimeoutError(toolName, target, timeoutMs, durationMs);
|
|
254
|
-
}
|
|
255
|
-
warn(
|
|
256
|
-
`[ChatBridgeError] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} outcome=error error=${describeError(err)}`
|
|
257
|
-
);
|
|
258
|
-
throw err;
|
|
259
|
-
} finally {
|
|
260
|
-
clearTimeout(timeout);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
170
|
// src/chatBridgeSendRequest.ts
|
|
265
171
|
import { randomUUID } from "crypto";
|
|
266
172
|
async function executeRetrySafeSendRequest(url, buildInit, {
|
|
@@ -325,6 +231,8 @@ function buildChatBridgeCommonHeaders(authToken2, { includeContentType = true }
|
|
|
325
231
|
}
|
|
326
232
|
|
|
327
233
|
// src/chat-bridge.ts
|
|
234
|
+
var MAX_UPLOAD_FILE_BYTES = 50 * 1024 * 1024;
|
|
235
|
+
var MAX_UPLOAD_FILE_LABEL = "50MB";
|
|
328
236
|
function toLocalTime(iso) {
|
|
329
237
|
const d = new Date(iso);
|
|
330
238
|
if (isNaN(d.getTime())) return iso;
|
|
@@ -710,7 +618,7 @@ ${formatMessages(unreadToShow)}`;
|
|
|
710
618
|
);
|
|
711
619
|
server.tool(
|
|
712
620
|
"upload_file",
|
|
713
|
-
|
|
621
|
+
`Upload a file to attach to a message. Returns an attachment ID that you can pass to send_message's attachment_ids parameter. Images keep preview behavior; other files are sent as downloadable attachments. Max size: ${MAX_UPLOAD_FILE_LABEL}. Video files are downloadable attachments and are not parsed by agents. Large PDFs may need to be downloaded and inspected in smaller chunks.`,
|
|
714
622
|
{
|
|
715
623
|
file_path: z2.string().describe("Absolute path to the file on your local filesystem"),
|
|
716
624
|
channel: z2.string().describe("The channel target where this file will be used (e.g. '#general', 'dm:@richard')")
|
|
@@ -726,10 +634,16 @@ ${formatMessages(unreadToShow)}`;
|
|
|
726
634
|
};
|
|
727
635
|
}
|
|
728
636
|
const stat = fs.statSync(file_path);
|
|
729
|
-
if (stat.size >
|
|
637
|
+
if (stat.size > MAX_UPLOAD_FILE_BYTES) {
|
|
638
|
+
return {
|
|
639
|
+
isError: true,
|
|
640
|
+
content: [{ type: "text", text: `Error: File too large (${(stat.size / 1024 / 1024).toFixed(1)}MB). Max ${MAX_UPLOAD_FILE_LABEL} per file.` }]
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
if (stat.size === 0) {
|
|
730
644
|
return {
|
|
731
645
|
isError: true,
|
|
732
|
-
content: [{ type: "text", text:
|
|
646
|
+
content: [{ type: "text", text: "Error: File is empty; refusing to upload a 0-byte attachment." }]
|
|
733
647
|
};
|
|
734
648
|
}
|
|
735
649
|
const { response: listRes, data: listData } = await executeJsonRequest(
|
|
@@ -911,10 +825,11 @@ Use this ID in send_message's attachment_ids parameter to include it in a messag
|
|
|
911
825
|
const humans = data.humans ?? [];
|
|
912
826
|
text += formatRuntimeContext(data.runtimeContext);
|
|
913
827
|
text += "### Channels\n";
|
|
914
|
-
text += 'Visible public channels may appear even when `joined=false`. Use `read_history(channel="#name")` to inspect
|
|
828
|
+
text += 'Visible public channels may appear even when `joined=false`. Private channels are shown only when you are a member; do not disclose private-channel names, membership, or content outside that channel. Use `read_history(channel="#name")` to inspect visible channels. When a channel is not joined, you cannot send messages there or receive ordinary channel delivery until a human adds you to the channel. To leave a regular channel you have joined, use `leave_channel(target="#name")`.\n';
|
|
915
829
|
if (channels.length > 0) {
|
|
916
830
|
for (const t of channels) {
|
|
917
|
-
const
|
|
831
|
+
const visibility = t.type === "private" ? "private" : "public";
|
|
832
|
+
const status = `${visibility}, ${t.joined ? "joined" : "not joined"}`;
|
|
918
833
|
text += t.description ? ` - #${t.name} [${status}] \u2014 ${t.description}
|
|
919
834
|
` : ` - #${t.name} [${status}]
|
|
920
835
|
`;
|
|
@@ -1007,9 +922,10 @@ Use this ID in send_message's attachment_ids parameter to include it in a messag
|
|
|
1007
922
|
sender_id: z2.string().optional().describe("Optional exact sender id filter."),
|
|
1008
923
|
after: z2.string().optional().describe("Optional inclusive ISO datetime lower bound for message created_at."),
|
|
1009
924
|
before: z2.string().optional().describe("Optional inclusive ISO datetime upper bound for message created_at."),
|
|
925
|
+
sort: z2.enum(["relevance", "recent"]).optional().describe("Optional result sort. Use 'relevance' for best match first or 'recent' for newest first."),
|
|
1010
926
|
limit: z2.number().default(10).describe("Max number of search results to return (default 10, max 20)")
|
|
1011
927
|
},
|
|
1012
|
-
async ({ query, channel, sender_id, after, before, limit }) => {
|
|
928
|
+
async ({ query, channel, sender_id, after, before, sort, limit }) => {
|
|
1013
929
|
try {
|
|
1014
930
|
const trimmed = query.trim();
|
|
1015
931
|
if (!trimmed) {
|
|
@@ -1024,6 +940,7 @@ Use this ID in send_message's attachment_ids parameter to include it in a messag
|
|
|
1024
940
|
if (sender_id) params.set("senderId", sender_id);
|
|
1025
941
|
if (after) params.set("after", after);
|
|
1026
942
|
if (before) params.set("before", before);
|
|
943
|
+
if (sort) params.set("sort", sort);
|
|
1027
944
|
const { response: res, data } = await executeJsonRequest(
|
|
1028
945
|
`${serverUrl}/internal/agent/${agentId}/search?${params}`,
|
|
1029
946
|
{ method: "GET", headers: commonHeaders },
|
|
@@ -1170,7 +1087,7 @@ ${formatted}${footer}`
|
|
|
1170
1087
|
"List all tasks in a channel. Returns each task's number, title, status, assignee, and message ID. Use this to see what work exists before claiming. Tasks marked as legacy are from an older system and cannot be claimed or modified.",
|
|
1171
1088
|
{
|
|
1172
1089
|
channel: z2.string().describe("The channel whose task board to view \u2014 e.g. '#engineering', '#proj-slock'"),
|
|
1173
|
-
status: z2.enum(["all", "todo", "in_progress", "in_review", "done"]).default("all").describe("Filter by status (default: all)")
|
|
1090
|
+
status: z2.enum(["all", "todo", "in_progress", "in_review", "done", "closed"]).default("all").describe("Filter by status (default: all)")
|
|
1174
1091
|
},
|
|
1175
1092
|
async ({ channel, status }) => {
|
|
1176
1093
|
try {
|
|
@@ -1323,7 +1240,7 @@ Thread messages and system messages (e.g. task-claim / task-status announcements
|
|
|
1323
1240
|
const msgShort = r.messageId ? r.messageId.slice(0, 8) : "";
|
|
1324
1241
|
return `${label} (msg:${msgShort}): claimed`;
|
|
1325
1242
|
}
|
|
1326
|
-
return `${label}: FAILED \u2014 ${r.reason || "already claimed"}
|
|
1243
|
+
return `${label}: FAILED \u2014 ${r.reason || "already claimed"}. Do not reply.`;
|
|
1327
1244
|
});
|
|
1328
1245
|
const succeeded = data.results.filter((r) => r.success).length;
|
|
1329
1246
|
const failed = data.results.length - succeeded;
|
|
@@ -1394,11 +1311,11 @@ ${lines.join("\n")}${threadHint}`
|
|
|
1394
1311
|
);
|
|
1395
1312
|
server.tool(
|
|
1396
1313
|
"update_task_status",
|
|
1397
|
-
"Update a task's progress status. You must be the task's assignee to update it. Use in_review when your work is ready for human validation. Only set done for trivial tasks or after explicit approval. Valid transitions: todo\
|
|
1314
|
+
"Update a task's progress status. You must be the task's assignee to update it. Use in_review when your work is ready for human validation. Only set done for trivial tasks or after explicit approval. Use closed to mark a task as won't-do (cancelled / abandoned / out-of-scope) \u2014 distinct from done. Valid transitions: todo\u2192{in_progress,closed}, in_progress\u2192{in_review,done,closed}, in_review\u2192{done,in_progress,closed}, done\u2192{todo,in_progress,in_review,closed}, closed\u2192todo (reopen).",
|
|
1398
1315
|
{
|
|
1399
1316
|
channel: z2.string().describe("The channel \u2014 e.g. '#engineering'"),
|
|
1400
1317
|
task_number: z2.number().describe("The task number to update (e.g. 3)"),
|
|
1401
|
-
status: z2.enum(["todo", "in_progress", "in_review", "done"]).describe("The new status")
|
|
1318
|
+
status: z2.enum(["todo", "in_progress", "in_review", "done", "closed"]).describe("The new status")
|
|
1402
1319
|
},
|
|
1403
1320
|
async ({ channel, task_number, status }) => {
|
|
1404
1321
|
try {
|