@slock-ai/daemon 0.32.1 → 0.32.2-alpha.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,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ buildFetchDispatcher
4
+ } from "./chunk-GX2DVINN.js";
2
5
 
3
6
  // src/chat-bridge.ts
4
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -27,6 +30,11 @@ var commonHeaders = { "Content-Type": "application/json" };
27
30
  if (authToken) {
28
31
  commonHeaders["Authorization"] = `Bearer ${authToken}`;
29
32
  }
33
+ function bridgeFetch(url, init = {}) {
34
+ const dispatcher = buildFetchDispatcher(url, process.env);
35
+ const requestInit = dispatcher ? { ...init, dispatcher } : init;
36
+ return fetch(url, requestInit);
37
+ }
30
38
  function formatTarget(m) {
31
39
  if (m.channel_type === "thread" && m.parent_channel_name) {
32
40
  const shortId = m.channel_name.startsWith("thread-") ? m.channel_name.slice(7) : m.channel_name;
@@ -69,7 +77,7 @@ server.tool(
69
77
  },
70
78
  async ({ target, content, attachment_ids }) => {
71
79
  try {
72
- const res = await fetch(`${serverUrl}/internal/agent/${agentId}/send`, {
80
+ const res = await bridgeFetch(`${serverUrl}/internal/agent/${agentId}/send`, {
73
81
  method: "POST",
74
82
  headers: commonHeaders,
75
83
  body: JSON.stringify({ target, content, attachmentIds: attachment_ids })
@@ -131,7 +139,7 @@ server.tool(
131
139
  content: [{ type: "text", text: `Error: File too large (${(stat.size / 1024 / 1024).toFixed(1)}MB). Max 5MB.` }]
132
140
  };
133
141
  }
134
- const listRes = await fetch(`${serverUrl}/internal/agent/${agentId}/resolve-channel`, {
142
+ const listRes = await bridgeFetch(`${serverUrl}/internal/agent/${agentId}/resolve-channel`, {
135
143
  method: "POST",
136
144
  headers: commonHeaders,
137
145
  body: JSON.stringify({ target: channel })
@@ -165,7 +173,7 @@ server.tool(
165
173
  if (authToken) {
166
174
  uploadHeaders["Authorization"] = `Bearer ${authToken}`;
167
175
  }
168
- const res = await fetch(`${serverUrl}/internal/agent/${agentId}/upload`, {
176
+ const res = await bridgeFetch(`${serverUrl}/internal/agent/${agentId}/upload`, {
169
177
  method: "POST",
170
178
  headers: uploadHeaders,
171
179
  body: formData
@@ -222,7 +230,7 @@ Use your Read tool to view this image.` }]
222
230
  if (authToken) {
223
231
  downloadHeaders["Authorization"] = `Bearer ${authToken}`;
224
232
  }
225
- const res = await fetch(`${serverUrl}/api/attachments/${attachment_id}`, {
233
+ const res = await bridgeFetch(`${serverUrl}/api/attachments/${attachment_id}`, {
226
234
  headers: downloadHeaders,
227
235
  redirect: "follow"
228
236
  });
@@ -262,7 +270,7 @@ server.tool(
262
270
  {},
263
271
  async () => {
264
272
  try {
265
- const res = await fetch(
273
+ const res = await bridgeFetch(
266
274
  `${serverUrl}/internal/agent/${agentId}/receive`,
267
275
  { method: "GET", headers: commonHeaders }
268
276
  );
@@ -291,9 +299,10 @@ function formatMessages(messages) {
291
299
  const msgId = m.message_id ? m.message_id.slice(0, 8) : "-";
292
300
  const time = m.timestamp ? toLocalTime(m.timestamp) : "-";
293
301
  const senderType = m.sender_type === "agent" ? " type=agent" : "";
302
+ const renderedContent = m.content;
294
303
  const attachSuffix = m.attachments?.length ? ` [${m.attachments.length} image${m.attachments.length > 1 ? "s" : ""}: ${m.attachments.map((a) => `${a.filename} (id:${a.id})`).join(", ")} \u2014 use view_file to see]` : "";
295
304
  const taskSuffix = m.task_status ? ` [task #${m.task_number} status=${m.task_status}${m.task_assignee_id ? ` assignee=${m.task_assignee_type}:${m.task_assignee_id}` : ""}]` : "";
296
- return `[target=${target} msg=${msgId} time=${time}${senderType}] @${m.sender_name}: ${m.content}${attachSuffix}${taskSuffix}`;
305
+ return `[target=${target} msg=${msgId} time=${time}${senderType}] @${m.sender_name}: ${renderedContent}${attachSuffix}${taskSuffix}`;
297
306
  }).join("\n");
298
307
  }
299
308
  server.tool(
@@ -302,7 +311,7 @@ server.tool(
302
311
  {},
303
312
  async () => {
304
313
  try {
305
- const res = await fetch(
314
+ const res = await bridgeFetch(
306
315
  `${serverUrl}/internal/agent/${agentId}/server`,
307
316
  { method: "GET", headers: commonHeaders }
308
317
  );
@@ -357,9 +366,12 @@ server.tool(
357
366
  {
358
367
  query: z.string().describe("Search query"),
359
368
  channel: z.string().optional().describe("Optional target to scope the search, e.g. '#general', 'dm:@richard', '#general:abcd1234'"),
369
+ sender_id: z.string().optional().describe("Optional exact sender id filter."),
370
+ after: z.string().optional().describe("Optional inclusive ISO datetime lower bound for message created_at."),
371
+ before: z.string().optional().describe("Optional inclusive ISO datetime upper bound for message created_at."),
360
372
  limit: z.number().default(10).describe("Max number of search results to return (default 10, max 20)")
361
373
  },
362
- async ({ query, channel, limit }) => {
374
+ async ({ query, channel, sender_id, after, before, limit }) => {
363
375
  try {
364
376
  const trimmed = query.trim();
365
377
  if (!trimmed) {
@@ -371,7 +383,10 @@ server.tool(
371
383
  params.set("q", trimmed);
372
384
  params.set("limit", String(Math.min(limit, 20)));
373
385
  if (channel) params.set("channel", channel);
374
- const res = await fetch(
386
+ if (sender_id) params.set("senderId", sender_id);
387
+ if (after) params.set("after", after);
388
+ if (before) params.set("before", before);
389
+ const res = await bridgeFetch(
375
390
  `${serverUrl}/internal/agent/${agentId}/search?${params}`,
376
391
  { method: "GET", headers: commonHeaders }
377
392
  );
@@ -433,7 +448,7 @@ server.tool(
433
448
  if (around !== void 0) params.set("around", String(around));
434
449
  if (before) params.set("before", String(before));
435
450
  if (after) params.set("after", String(after));
436
- const res = await fetch(
451
+ const res = await bridgeFetch(
437
452
  `${serverUrl}/internal/agent/${agentId}/history?${params}`,
438
453
  { method: "GET", headers: commonHeaders }
439
454
  );
@@ -456,9 +471,10 @@ server.tool(
456
471
  const senderType = m.senderType === "agent" ? " type=agent" : "";
457
472
  const time = m.createdAt ? toLocalTime(m.createdAt) : "-";
458
473
  const msgId = m.id || "-";
474
+ const renderedContent = m.content;
459
475
  const attachSuffix = m.attachments?.length ? ` [${m.attachments.length} image${m.attachments.length > 1 ? "s" : ""}: ${m.attachments.map((a) => `${a.filename} (id:${a.id})`).join(", ")} \u2014 use view_file to see]` : "";
460
476
  const taskSuffix = m.taskStatus ? ` [task #${m.taskNumber} status=${m.taskStatus}${m.taskAssigneeId ? ` assignee=${m.taskAssigneeType}:${m.taskAssigneeId}` : ""}]` : "";
461
- return `[seq=${m.seq} msg=${msgId} time=${time}${senderType}] @${m.senderName}: ${m.content}${attachSuffix}${taskSuffix}`;
477
+ return `[seq=${m.seq} msg=${msgId} time=${time}${senderType}] @${m.senderName}: ${renderedContent}${attachSuffix}${taskSuffix}`;
462
478
  }).join("\n");
463
479
  let footer = "";
464
480
  if (data.historyLimited) {
@@ -519,7 +535,7 @@ server.tool(
519
535
  const params = new URLSearchParams();
520
536
  params.set("channel", channel);
521
537
  if (status !== "all") params.set("status", status);
522
- const res = await fetch(
538
+ const res = await bridgeFetch(
523
539
  `${serverUrl}/internal/agent/${agentId}/tasks?${params}`,
524
540
  { method: "GET", headers: commonHeaders }
525
541
  );
@@ -573,7 +589,7 @@ server.tool(
573
589
  },
574
590
  async ({ channel, tasks }) => {
575
591
  try {
576
- const res = await fetch(`${serverUrl}/internal/agent/${agentId}/tasks`, {
592
+ const res = await bridgeFetch(`${serverUrl}/internal/agent/${agentId}/tasks`, {
577
593
  method: "POST",
578
594
  headers: commonHeaders,
579
595
  body: JSON.stringify({ channel, tasks })
@@ -629,7 +645,7 @@ Thread messages cannot be claimed or converted into tasks. If a task is in "todo
629
645
  const body = { channel };
630
646
  if (task_numbers && task_numbers.length > 0) body.task_numbers = task_numbers;
631
647
  if (message_ids && message_ids.length > 0) body.message_ids = message_ids;
632
- const res = await fetch(
648
+ const res = await bridgeFetch(
633
649
  `${serverUrl}/internal/agent/${agentId}/tasks/claim`,
634
650
  {
635
651
  method: "POST",
@@ -687,7 +703,7 @@ server.tool(
687
703
  },
688
704
  async ({ channel, task_number }) => {
689
705
  try {
690
- const res = await fetch(
706
+ const res = await bridgeFetch(
691
707
  `${serverUrl}/internal/agent/${agentId}/tasks/unclaim`,
692
708
  {
693
709
  method: "POST",
@@ -725,7 +741,7 @@ server.tool(
725
741
  },
726
742
  async ({ channel, task_number, status }) => {
727
743
  try {
728
- const res = await fetch(
744
+ const res = await bridgeFetch(
729
745
  `${serverUrl}/internal/agent/${agentId}/tasks/update-status`,
730
746
  {
731
747
  method: "POST",
@@ -0,0 +1,73 @@
1
+ // src/proxy.ts
2
+ import { HttpsProxyAgent } from "https-proxy-agent";
3
+ import { ProxyAgent } from "undici";
4
+ var fetchDispatcherCache = /* @__PURE__ */ new Map();
5
+ function getDefaultPort(protocol) {
6
+ switch (protocol) {
7
+ case "https:":
8
+ case "wss:":
9
+ return "443";
10
+ case "http:":
11
+ case "ws:":
12
+ return "80";
13
+ default:
14
+ return "";
15
+ }
16
+ }
17
+ function hostMatchesNoProxyEntry(hostname, ruleHost) {
18
+ if (!ruleHost) return false;
19
+ const normalizedRule = ruleHost.replace(/^\*\./, ".").replace(/^\./, "").toLowerCase();
20
+ const normalizedHost = hostname.toLowerCase();
21
+ return normalizedHost === normalizedRule || normalizedHost.endsWith(`.${normalizedRule}`);
22
+ }
23
+ function getProxyUrlForTarget(targetUrl, env) {
24
+ const protocol = new URL(targetUrl).protocol;
25
+ switch (protocol) {
26
+ case "wss:":
27
+ return env.WSS_PROXY || env.wss_proxy || env.HTTPS_PROXY || env.https_proxy || env.ALL_PROXY || env.all_proxy;
28
+ case "ws:":
29
+ return env.WS_PROXY || env.ws_proxy || env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy;
30
+ case "https:":
31
+ return env.HTTPS_PROXY || env.https_proxy || env.ALL_PROXY || env.all_proxy;
32
+ case "http:":
33
+ return env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy;
34
+ default:
35
+ return env.ALL_PROXY || env.all_proxy;
36
+ }
37
+ }
38
+ function shouldBypassProxy(targetUrl, env) {
39
+ const rawNoProxy = env.NO_PROXY || env.no_proxy;
40
+ if (!rawNoProxy) return false;
41
+ const url = new URL(targetUrl);
42
+ const hostname = url.hostname.toLowerCase();
43
+ const port = url.port || getDefaultPort(url.protocol);
44
+ return rawNoProxy.split(",").map((entry) => entry.trim()).filter(Boolean).some((entry) => {
45
+ if (entry === "*") return true;
46
+ const [ruleHost, rulePort] = entry.split(":", 2);
47
+ if (rulePort && rulePort !== port) return false;
48
+ return hostMatchesNoProxyEntry(hostname, ruleHost);
49
+ });
50
+ }
51
+ function buildWebSocketOptions(wsUrl, env) {
52
+ const proxyUrl = getProxyUrlForTarget(wsUrl, env);
53
+ if (!proxyUrl) return void 0;
54
+ if (shouldBypassProxy(wsUrl, env)) return void 0;
55
+ return {
56
+ agent: new HttpsProxyAgent(proxyUrl)
57
+ };
58
+ }
59
+ function buildFetchDispatcher(targetUrl, env) {
60
+ const proxyUrl = getProxyUrlForTarget(targetUrl, env);
61
+ if (!proxyUrl) return void 0;
62
+ if (shouldBypassProxy(targetUrl, env)) return void 0;
63
+ const cached = fetchDispatcherCache.get(proxyUrl);
64
+ if (cached) return cached;
65
+ const dispatcher = new ProxyAgent(proxyUrl);
66
+ fetchDispatcherCache.set(proxyUrl, dispatcher);
67
+ return dispatcher;
68
+ }
69
+
70
+ export {
71
+ buildWebSocketOptions,
72
+ buildFetchDispatcher
73
+ };
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ buildWebSocketOptions
4
+ } from "./chunk-GX2DVINN.js";
2
5
 
3
6
  // src/index.ts
4
7
  import path5 from "path";
@@ -10,7 +13,6 @@ import { fileURLToPath } from "url";
10
13
 
11
14
  // src/connection.ts
12
15
  import WebSocket from "ws";
13
- import { HttpsProxyAgent } from "https-proxy-agent";
14
16
 
15
17
  // src/logger.ts
16
18
  function timestamp() {
@@ -44,52 +46,6 @@ var systemClock = {
44
46
  clearTimeout: (timer) => clearTimeout(timer)
45
47
  };
46
48
  var INBOUND_WATCHDOG_MS = 7e4;
47
- function getProxyUrlForWebSocket(wsUrl, env) {
48
- const protocol = new URL(wsUrl).protocol;
49
- if (protocol === "wss:") {
50
- return env.WSS_PROXY || env.wss_proxy || env.HTTPS_PROXY || env.https_proxy || env.ALL_PROXY || env.all_proxy;
51
- }
52
- return env.WS_PROXY || env.ws_proxy || env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy;
53
- }
54
- function getDefaultPort(protocol) {
55
- switch (protocol) {
56
- case "https:":
57
- case "wss:":
58
- return "443";
59
- case "http:":
60
- case "ws:":
61
- return "80";
62
- default:
63
- return "";
64
- }
65
- }
66
- function hostMatchesNoProxyEntry(hostname, ruleHost) {
67
- if (!ruleHost) return false;
68
- const normalizedRule = ruleHost.replace(/^\*\./, ".").replace(/^\./, "").toLowerCase();
69
- const normalizedHost = hostname.toLowerCase();
70
- return normalizedHost === normalizedRule || normalizedHost.endsWith(`.${normalizedRule}`);
71
- }
72
- function shouldBypassProxy(wsUrl, env) {
73
- const rawNoProxy = env.NO_PROXY || env.no_proxy;
74
- if (!rawNoProxy) return false;
75
- const url = new URL(wsUrl);
76
- const hostname = url.hostname.toLowerCase();
77
- const port = url.port || getDefaultPort(url.protocol);
78
- return rawNoProxy.split(",").map((entry) => entry.trim()).filter(Boolean).some((entry) => {
79
- if (entry === "*") return true;
80
- const [ruleHost, rulePort] = entry.split(":", 2);
81
- if (rulePort && rulePort !== port) return false;
82
- return hostMatchesNoProxyEntry(hostname, ruleHost);
83
- });
84
- }
85
- function buildWebSocketOptions(wsUrl, env) {
86
- const proxyUrl = getProxyUrlForWebSocket(wsUrl, env);
87
- if (!proxyUrl) return void 0;
88
- if (shouldBypassProxy(wsUrl, env)) return void 0;
89
- return {
90
- agent: new HttpsProxyAgent(proxyUrl)
91
- };
92
- }
93
49
  var DaemonConnection = class {
94
50
  ws = null;
95
51
  options;
@@ -1247,9 +1203,10 @@ function formatIncomingMessage(message) {
1247
1203
  const msgId = message.message_id ? message.message_id.slice(0, 8) : "-";
1248
1204
  const time = message.timestamp ? toLocalTime(message.timestamp) : "-";
1249
1205
  const senderType = message.sender_type === "agent" ? " type=agent" : "";
1206
+ const renderedContent = message.content;
1250
1207
  const attachSuffix = message.attachments?.length ? ` [${message.attachments.length} image${message.attachments.length > 1 ? "s" : ""}: ${message.attachments.map((a) => `${a.filename} (id:${a.id})`).join(", ")} \u2014 use view_file to see]` : "";
1251
1208
  const taskSuffix = message.task_status ? ` [task #${message.task_number} status=${message.task_status}${message.task_assignee_id ? ` assignee=${message.task_assignee_type}:${message.task_assignee_id}` : ""}]` : "";
1252
- return `[target=${target} msg=${msgId} time=${time}${senderType}] @${message.sender_name}: ${message.content}${attachSuffix}${taskSuffix}`;
1209
+ return `[target=${target} msg=${msgId} time=${time}${senderType}] @${message.sender_name}: ${renderedContent}${attachSuffix}${taskSuffix}`;
1253
1210
  }
1254
1211
  function buildUnreadSummary(messages, excludeChannel) {
1255
1212
  const summary = /* @__PURE__ */ new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.32.1",
3
+ "version": "0.32.2-alpha.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"
@@ -16,28 +16,30 @@
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
- "dependencies": {
20
- "@modelcontextprotocol/sdk": "^1.29.0",
21
- "https-proxy-agent": "^7.0.6",
22
- "ws": "^8.20.0",
23
- "zod": "^4.3.6"
24
- },
25
- "devDependencies": {
26
- "@types/node": "^25.5.0",
27
- "@types/ws": "^8.18.1",
28
- "tsup": "^8.5.1",
29
- "typescript": "^5.9.3",
30
- "@slock-ai/shared": "0.1.0"
31
- },
32
19
  "scripts": {
33
20
  "dev": "tsx watch src/index.ts",
34
21
  "start": "tsx src/index.ts",
35
22
  "build": "tsup",
36
23
  "test": "node --import tsx --test --test-force-exit 'src/**/*.test.ts'",
24
+ "prepublishOnly": "pnpm run build",
37
25
  "typecheck": "tsc --noEmit",
38
26
  "release:patch": "npm version patch --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @slock-ai/daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
39
27
  "release:minor": "npm version minor --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @slock-ai/daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
40
28
  "release:major": "npm version major --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @slock-ai/daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
41
29
  "release:alpha": "npm version prerelease --preid=alpha --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @slock-ai/daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags"
30
+ },
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.29.0",
33
+ "https-proxy-agent": "^7.0.6",
34
+ "undici": "^7.24.7",
35
+ "ws": "^8.20.0",
36
+ "zod": "^4.3.6"
37
+ },
38
+ "devDependencies": {
39
+ "@slock-ai/shared": "workspace:*",
40
+ "@types/node": "^25.5.0",
41
+ "@types/ws": "^8.18.1",
42
+ "tsup": "^8.5.1",
43
+ "typescript": "^5.9.3"
42
44
  }
43
- }
45
+ }