@slock-ai/daemon 0.43.0 → 0.46.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.
@@ -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-JG7ONJZ6.js";
8
+ } from "./chunk-Z3PCMYZO.js";
6
9
 
7
10
  // src/chat-bridge.ts
8
11
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -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
- "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: 10MB.",
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 > 10 * 1024 * 1024) {
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: `Error: File too large (${(stat.size / 1024 / 1024).toFixed(1)}MB). Max 10MB per file.` }]
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 them. 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';
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 status = t.joined ? "joined" : "not joined";
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 },
@@ -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;