@slock-ai/daemon 0.13.0 → 0.14.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 +11 -7
- package/dist/index.js +51 -35
- package/package.json +1 -1
package/dist/chat-bridge.js
CHANGED
|
@@ -68,11 +68,13 @@ server.tool(
|
|
|
68
68
|
]
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
+
const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
|
|
72
|
+
const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
|
|
71
73
|
return {
|
|
72
74
|
content: [
|
|
73
75
|
{
|
|
74
76
|
type: "text",
|
|
75
|
-
text: `Message sent to ${target}`
|
|
77
|
+
text: `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}`
|
|
76
78
|
}
|
|
77
79
|
]
|
|
78
80
|
};
|
|
@@ -107,9 +109,10 @@ server.tool(
|
|
|
107
109
|
}
|
|
108
110
|
const formatted = data.messages.map((m) => {
|
|
109
111
|
const target = formatTarget(m);
|
|
110
|
-
const
|
|
111
|
-
const time = m.timestamp ?
|
|
112
|
-
|
|
112
|
+
const msgId = m.message_id ? m.message_id.slice(0, 8) : "-";
|
|
113
|
+
const time = m.timestamp ? toLocalTime(m.timestamp) : "-";
|
|
114
|
+
const senderType = m.sender_type === "agent" ? " type=agent" : "";
|
|
115
|
+
return `[target=${target} msg=${msgId} time=${time}${senderType}] @${m.sender_name}: ${m.content}`;
|
|
113
116
|
}).join("\n");
|
|
114
117
|
return {
|
|
115
118
|
content: [{ type: "text", text: formatted }]
|
|
@@ -211,9 +214,10 @@ server.tool(
|
|
|
211
214
|
};
|
|
212
215
|
}
|
|
213
216
|
const formatted = data.messages.map((m) => {
|
|
214
|
-
const
|
|
215
|
-
const time = m.createdAt ?
|
|
216
|
-
|
|
217
|
+
const senderType = m.senderType === "agent" ? " type=agent" : "";
|
|
218
|
+
const time = m.createdAt ? toLocalTime(m.createdAt) : "-";
|
|
219
|
+
const msgId = m.id ? m.id.slice(0, 8) : "-";
|
|
220
|
+
return `[seq=${m.seq} msg=${msgId} time=${time}${senderType}] @${m.senderName}: ${m.content}`;
|
|
217
221
|
}).join("\n");
|
|
218
222
|
let footer = "";
|
|
219
223
|
if (data.historyLimited) {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import
|
|
4
|
+
import path4 from "path";
|
|
5
5
|
import os2 from "os";
|
|
6
6
|
import { createRequire } from "module";
|
|
7
7
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -84,11 +84,13 @@ var DaemonConnection = class {
|
|
|
84
84
|
|
|
85
85
|
// src/agentProcessManager.ts
|
|
86
86
|
import { mkdir, writeFile, access, readdir, stat, readFile, rm } from "fs/promises";
|
|
87
|
-
import
|
|
87
|
+
import path3 from "path";
|
|
88
88
|
import os from "os";
|
|
89
89
|
|
|
90
90
|
// src/drivers/claude.ts
|
|
91
91
|
import { spawn } from "child_process";
|
|
92
|
+
import { writeFileSync } from "fs";
|
|
93
|
+
import path from "path";
|
|
92
94
|
|
|
93
95
|
// src/drivers/systemPrompt.ts
|
|
94
96
|
function toolRef(prefix, name) {
|
|
@@ -143,14 +145,21 @@ ${opts.postStartupNotes.join("\n")}`;
|
|
|
143
145
|
|
|
144
146
|
## Messaging
|
|
145
147
|
|
|
146
|
-
Messages you receive
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
Messages you receive have a single RFC 5424-style structured data header followed by the sender and content:
|
|
149
|
+
|
|
150
|
+
\`\`\`
|
|
151
|
+
[target=#general msg=a1b2c3d4 time=2026-03-15T01:00:00] @richard: hello everyone
|
|
152
|
+
[target=#general msg=e5f6a7b8 time=2026-03-15T01:00:01 type=agent] @Alice: hi there
|
|
153
|
+
[target=dm:@richard msg=c9d0e1f2 time=2026-03-15T01:00:02] @richard: hey, can you help?
|
|
154
|
+
[target=#general:a1b2c3d4 msg=f3a4b5c6 time=2026-03-15T01:00:03] @richard: thread reply
|
|
155
|
+
[target=dm:@richard:x9y8z7a0 msg=d7e8f9a0 time=2026-03-15T01:00:04] @richard: DM thread reply
|
|
156
|
+
\`\`\`
|
|
152
157
|
|
|
153
|
-
|
|
158
|
+
Header fields:
|
|
159
|
+
- \`target=\` \u2014 where the message came from. Reuse as the \`target\` parameter when replying.
|
|
160
|
+
- \`msg=\` \u2014 message short ID (first 8 chars of UUID). Use as thread suffix to start/reply in a thread.
|
|
161
|
+
- \`time=\` \u2014 timestamp.
|
|
162
|
+
- \`type=agent\` \u2014 present only if the sender is an agent.
|
|
154
163
|
|
|
155
164
|
### Sending messages
|
|
156
165
|
|
|
@@ -165,9 +174,11 @@ The \`[...]\` prefix is the **target** \u2014 it identifies where the message ca
|
|
|
165
174
|
|
|
166
175
|
Threads are sub-conversations attached to a specific message. They let you discuss a topic without cluttering the main channel.
|
|
167
176
|
|
|
168
|
-
- **Thread targets** have a colon and short ID suffix: \`#general:
|
|
177
|
+
- **Thread targets** have a colon and short ID suffix: \`#general:a1b2c3d4\` (thread in #general) or \`dm:@richard:x9y8z7a0\` (thread in a DM).
|
|
169
178
|
- 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
|
-
-
|
|
179
|
+
- **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=a1b2c3d4 ...]\`, reply with \`send_message(target="#general:a1b2c3d4", content="...")\`. The thread will be auto-created if it doesn't exist yet.
|
|
180
|
+
- When you send a message, the response includes the message ID. You can use it to start a thread on your own message.
|
|
181
|
+
- You can read thread history: \`read_history(channel="#general:a1b2c3d4")\`
|
|
171
182
|
- Threads cannot be nested \u2014 you cannot start a thread inside a thread.
|
|
172
183
|
|
|
173
184
|
### Discovering people and channels
|
|
@@ -360,6 +371,8 @@ var ClaudeDriver = class {
|
|
|
360
371
|
}
|
|
361
372
|
}
|
|
362
373
|
});
|
|
374
|
+
const mcpConfigPath = path.join(ctx.workingDirectory, ".slock-claude-mcp.json");
|
|
375
|
+
writeFileSync(mcpConfigPath, mcpConfig, "utf8");
|
|
363
376
|
const args2 = [
|
|
364
377
|
"--allow-dangerously-skip-permissions",
|
|
365
378
|
"--dangerously-skip-permissions",
|
|
@@ -369,7 +382,7 @@ var ClaudeDriver = class {
|
|
|
369
382
|
"--input-format",
|
|
370
383
|
"stream-json",
|
|
371
384
|
"--mcp-config",
|
|
372
|
-
|
|
385
|
+
mcpConfigPath,
|
|
373
386
|
"--model",
|
|
374
387
|
ctx.config.model || "sonnet"
|
|
375
388
|
];
|
|
@@ -506,13 +519,13 @@ var ClaudeDriver = class {
|
|
|
506
519
|
// src/drivers/codex.ts
|
|
507
520
|
import { spawn as spawn2, execSync } from "child_process";
|
|
508
521
|
import { existsSync } from "fs";
|
|
509
|
-
import
|
|
522
|
+
import path2 from "path";
|
|
510
523
|
var CodexDriver = class {
|
|
511
524
|
id = "codex";
|
|
512
525
|
supportsStdinNotification = false;
|
|
513
526
|
mcpToolPrefix = "mcp_chat_";
|
|
514
527
|
spawn(ctx) {
|
|
515
|
-
const gitDir =
|
|
528
|
+
const gitDir = path2.join(ctx.workingDirectory, ".git");
|
|
516
529
|
if (!existsSync(gitDir)) {
|
|
517
530
|
execSync("git init", { cwd: ctx.workingDirectory, stdio: "pipe" });
|
|
518
531
|
execSync("git add -A && git commit --allow-empty -m 'init'", {
|
|
@@ -728,7 +741,7 @@ function getDriver(runtimeId) {
|
|
|
728
741
|
}
|
|
729
742
|
|
|
730
743
|
// src/agentProcessManager.ts
|
|
731
|
-
var DATA_DIR =
|
|
744
|
+
var DATA_DIR = path3.join(os.homedir(), ".slock", "agents");
|
|
732
745
|
function toLocalTime(iso) {
|
|
733
746
|
const d = new Date(iso);
|
|
734
747
|
if (isNaN(d.getTime())) return iso;
|
|
@@ -753,9 +766,9 @@ var AgentProcessManager = class {
|
|
|
753
766
|
this.agentsStarting.add(agentId);
|
|
754
767
|
try {
|
|
755
768
|
const driver = getDriver(config.runtime || "claude");
|
|
756
|
-
const agentDataDir =
|
|
769
|
+
const agentDataDir = path3.join(DATA_DIR, agentId);
|
|
757
770
|
await mkdir(agentDataDir, { recursive: true });
|
|
758
|
-
const memoryMdPath =
|
|
771
|
+
const memoryMdPath = path3.join(agentDataDir, "MEMORY.md");
|
|
759
772
|
try {
|
|
760
773
|
await access(memoryMdPath);
|
|
761
774
|
} catch {
|
|
@@ -773,7 +786,7 @@ ${config.description || "No role defined yet."}
|
|
|
773
786
|
`;
|
|
774
787
|
await writeFile(memoryMdPath, initialMemoryMd);
|
|
775
788
|
}
|
|
776
|
-
await mkdir(
|
|
789
|
+
await mkdir(path3.join(agentDataDir, "notes"), { recursive: true });
|
|
777
790
|
const isResume = !!config.sessionId;
|
|
778
791
|
let prompt;
|
|
779
792
|
if (isResume && wakeMessage) {
|
|
@@ -953,7 +966,7 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
953
966
|
}
|
|
954
967
|
}
|
|
955
968
|
async resetWorkspace(agentId) {
|
|
956
|
-
const agentDataDir =
|
|
969
|
+
const agentDataDir = path3.join(DATA_DIR, agentId);
|
|
957
970
|
try {
|
|
958
971
|
await rm(agentDataDir, { recursive: true, force: true });
|
|
959
972
|
console.log(`[Agent ${agentId}] Workspace deleted: ${agentDataDir}`);
|
|
@@ -979,14 +992,14 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
979
992
|
}
|
|
980
993
|
for (const entry of entries) {
|
|
981
994
|
if (!entry.isDirectory()) continue;
|
|
982
|
-
const dirPath =
|
|
995
|
+
const dirPath = path3.join(DATA_DIR, entry.name);
|
|
983
996
|
try {
|
|
984
997
|
const dirContents = await readdir(dirPath, { withFileTypes: true });
|
|
985
998
|
let totalSize = 0;
|
|
986
999
|
let latestMtime = /* @__PURE__ */ new Date(0);
|
|
987
1000
|
let fileCount = 0;
|
|
988
1001
|
for (const item of dirContents) {
|
|
989
|
-
const itemPath =
|
|
1002
|
+
const itemPath = path3.join(dirPath, item.name);
|
|
990
1003
|
try {
|
|
991
1004
|
const info = await stat(itemPath);
|
|
992
1005
|
if (item.isFile()) {
|
|
@@ -1016,7 +1029,7 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1016
1029
|
if (directoryName.includes("/") || directoryName.includes("..") || directoryName.includes("\\")) {
|
|
1017
1030
|
return false;
|
|
1018
1031
|
}
|
|
1019
|
-
const targetDir =
|
|
1032
|
+
const targetDir = path3.join(DATA_DIR, directoryName);
|
|
1020
1033
|
try {
|
|
1021
1034
|
await rm(targetDir, { recursive: true, force: true });
|
|
1022
1035
|
console.log(`[Workspace] Deleted directory: ${targetDir}`);
|
|
@@ -1028,7 +1041,7 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1028
1041
|
}
|
|
1029
1042
|
// Workspace file browsing
|
|
1030
1043
|
async getFileTree(agentId, dirPath) {
|
|
1031
|
-
const agentDir =
|
|
1044
|
+
const agentDir = path3.join(DATA_DIR, agentId);
|
|
1032
1045
|
try {
|
|
1033
1046
|
await stat(agentDir);
|
|
1034
1047
|
} catch {
|
|
@@ -1036,8 +1049,8 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1036
1049
|
}
|
|
1037
1050
|
let targetDir = agentDir;
|
|
1038
1051
|
if (dirPath) {
|
|
1039
|
-
const resolved =
|
|
1040
|
-
if (!resolved.startsWith(agentDir +
|
|
1052
|
+
const resolved = path3.resolve(agentDir, dirPath);
|
|
1053
|
+
if (!resolved.startsWith(agentDir + path3.sep) && resolved !== agentDir) {
|
|
1041
1054
|
return [];
|
|
1042
1055
|
}
|
|
1043
1056
|
targetDir = resolved;
|
|
@@ -1045,9 +1058,9 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1045
1058
|
return this.listDirectoryChildren(targetDir, agentDir);
|
|
1046
1059
|
}
|
|
1047
1060
|
async readFile(agentId, filePath) {
|
|
1048
|
-
const agentDir =
|
|
1049
|
-
const resolved =
|
|
1050
|
-
if (!resolved.startsWith(agentDir +
|
|
1061
|
+
const agentDir = path3.join(DATA_DIR, agentId);
|
|
1062
|
+
const resolved = path3.resolve(agentDir, filePath);
|
|
1063
|
+
if (!resolved.startsWith(agentDir + path3.sep) && resolved !== agentDir) {
|
|
1051
1064
|
throw new Error("Access denied");
|
|
1052
1065
|
}
|
|
1053
1066
|
const info = await stat(resolved);
|
|
@@ -1071,7 +1084,7 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1071
1084
|
".sh",
|
|
1072
1085
|
".py"
|
|
1073
1086
|
]);
|
|
1074
|
-
const ext =
|
|
1087
|
+
const ext = path3.extname(resolved).toLowerCase();
|
|
1075
1088
|
if (!TEXT_EXTENSIONS.has(ext) && ext !== "") {
|
|
1076
1089
|
return { content: null, binary: true };
|
|
1077
1090
|
}
|
|
@@ -1110,7 +1123,10 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1110
1123
|
const inputSummary = driver.summarizeToolInput(toolName, event.input);
|
|
1111
1124
|
trajectory.push({ kind: "tool_start", toolName, toolInput: inputSummary });
|
|
1112
1125
|
if (toolName === `${driver.mcpToolPrefix}receive_message`) {
|
|
1113
|
-
|
|
1126
|
+
const isBlocking = event.input?.block !== false;
|
|
1127
|
+
if (isBlocking) {
|
|
1128
|
+
activity = "online";
|
|
1129
|
+
}
|
|
1114
1130
|
if (ap) {
|
|
1115
1131
|
ap.isInReceiveMessage = true;
|
|
1116
1132
|
ap.pendingNotificationCount = 0;
|
|
@@ -1185,8 +1201,8 @@ Note: While you are busy, you may receive [System notification: ...] messages ab
|
|
|
1185
1201
|
const nodes = [];
|
|
1186
1202
|
for (const entry of entries) {
|
|
1187
1203
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
1188
|
-
const fullPath =
|
|
1189
|
-
const relativePath =
|
|
1204
|
+
const fullPath = path3.join(dir, entry.name);
|
|
1205
|
+
const relativePath = path3.relative(rootDir, fullPath);
|
|
1190
1206
|
let info;
|
|
1191
1207
|
try {
|
|
1192
1208
|
info = await stat(fullPath);
|
|
@@ -1281,12 +1297,12 @@ if (!serverUrl || !apiKey) {
|
|
|
1281
1297
|
console.error("Usage: slock-daemon --server-url <url> --api-key <key>");
|
|
1282
1298
|
process.exit(1);
|
|
1283
1299
|
}
|
|
1284
|
-
var __dirname =
|
|
1285
|
-
var chatBridgePath =
|
|
1300
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
1301
|
+
var chatBridgePath = path4.resolve(__dirname, "chat-bridge.js");
|
|
1286
1302
|
try {
|
|
1287
1303
|
accessSync(chatBridgePath);
|
|
1288
1304
|
} catch {
|
|
1289
|
-
chatBridgePath =
|
|
1305
|
+
chatBridgePath = path4.resolve(__dirname, "chat-bridge.ts");
|
|
1290
1306
|
}
|
|
1291
1307
|
var connection;
|
|
1292
1308
|
var agentManager = new AgentProcessManager(chatBridgePath, (msg) => {
|