@slock-ai/daemon 0.39.1-alpha.1 → 0.39.1-alpha.2
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/{chunk-7JPDXVD5.js → chunk-D6DQHMCD.js} +33 -0
- package/dist/cli/index.js +116 -25
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -475,6 +475,7 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
475
475
|
};
|
|
476
476
|
|
|
477
477
|
// src/agentProcessManager.ts
|
|
478
|
+
import { writeFileSync as writeFileSync6, renameSync, rmSync } from "fs";
|
|
478
479
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
479
480
|
import path10 from "path";
|
|
480
481
|
import os3 from "os";
|
|
@@ -942,6 +943,7 @@ function prepareCliTransport(ctx, extraEnv = {}, platform = process.platform) {
|
|
|
942
943
|
mkdirSync(slockDir, { recursive: true });
|
|
943
944
|
const tokenFile = path.join(slockDir, "agent-token");
|
|
944
945
|
writeFileSync(tokenFile, ctx.config.authToken || ctx.daemonApiKey, { mode: 384 });
|
|
946
|
+
const chatContextFile = path.join(ctx.workingDirectory, "chat-context.json");
|
|
945
947
|
const posixWrapper = path.join(slockDir, "slock");
|
|
946
948
|
const posixBody = `#!/usr/bin/env bash
|
|
947
949
|
exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(ctx.slockCliPath)} "$@"
|
|
@@ -963,11 +965,13 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(ctx.slockCliPath)}
|
|
|
963
965
|
SLOCK_AGENT_ID: ctx.agentId,
|
|
964
966
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
965
967
|
SLOCK_AGENT_TOKEN_FILE: tokenFile,
|
|
968
|
+
SLOCK_CHAT_CONTEXT_FILE: chatContextFile,
|
|
966
969
|
PATH: `${slockDir}${path.delimiter}${process.env.PATH ?? ""}`
|
|
967
970
|
};
|
|
968
971
|
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
969
972
|
return {
|
|
970
973
|
slockDir,
|
|
974
|
+
chatContextFile,
|
|
971
975
|
tokenFile,
|
|
972
976
|
wrapperPath,
|
|
973
977
|
spawnEnv
|
|
@@ -2420,6 +2424,29 @@ function formatMessageTarget(message) {
|
|
|
2420
2424
|
function getMessageShortId(messageId) {
|
|
2421
2425
|
return messageId.startsWith("thread-") ? messageId.slice(7) : messageId.slice(0, 8);
|
|
2422
2426
|
}
|
|
2427
|
+
function writeAgentChatContextFile(agentDataDir, message) {
|
|
2428
|
+
const target = formatMessageTarget(message);
|
|
2429
|
+
const msgId = message.message_id ?? null;
|
|
2430
|
+
const filePath = path10.join(agentDataDir, "chat-context.json");
|
|
2431
|
+
const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
2432
|
+
const json = JSON.stringify({
|
|
2433
|
+
target,
|
|
2434
|
+
msgId,
|
|
2435
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2436
|
+
});
|
|
2437
|
+
try {
|
|
2438
|
+
writeFileSync6(tmpPath, json, { encoding: "utf-8", mode: 384 });
|
|
2439
|
+
renameSync(tmpPath, filePath);
|
|
2440
|
+
} catch (error) {
|
|
2441
|
+
try {
|
|
2442
|
+
rmSync(tmpPath, { force: true });
|
|
2443
|
+
} catch {
|
|
2444
|
+
}
|
|
2445
|
+
logger.warn(
|
|
2446
|
+
`[AgentChatContext] Failed to persist current chat context for agent dir ${agentDataDir}: ${error instanceof Error ? error.message : String(error)}`
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2423
2450
|
function formatSenderHandle(message) {
|
|
2424
2451
|
return message.sender_description ? `@${message.sender_name} \u2014 ${message.sender_description}` : `@${message.sender_name}`;
|
|
2425
2452
|
}
|
|
@@ -2655,6 +2682,9 @@ Use read_history to catch up on the channels listed above, then stop. Read each
|
|
|
2655
2682
|
prompt = driver.supportsNativeStandingPrompt ? NATIVE_STANDING_PROMPT_STARTUP_INPUT : standingPrompt;
|
|
2656
2683
|
}
|
|
2657
2684
|
const effectiveConfig = await this.buildSpawnConfig(agentId, config);
|
|
2685
|
+
if (wakeMessage) {
|
|
2686
|
+
writeAgentChatContextFile(agentDataDir, wakeMessage);
|
|
2687
|
+
}
|
|
2658
2688
|
const { process: proc } = driver.spawn({
|
|
2659
2689
|
agentId,
|
|
2660
2690
|
config: effectiveConfig,
|
|
@@ -3320,6 +3350,9 @@ Use read_history to catch up on the channels listed above, then stop. Read each
|
|
|
3320
3350
|
/** Deliver a message to an agent via stdin, formatting it the same way as the MCP bridge */
|
|
3321
3351
|
deliverMessagesViaStdin(agentId, ap, messages, mode) {
|
|
3322
3352
|
if (messages.length === 0) return true;
|
|
3353
|
+
const latestMessage = messages[messages.length - 1];
|
|
3354
|
+
const agentDataDir = path10.join(this.dataDir, agentId);
|
|
3355
|
+
writeAgentChatContextFile(agentDataDir, latestMessage);
|
|
3323
3356
|
const prompt = messages.length === 1 ? `New message received:
|
|
3324
3357
|
|
|
3325
3358
|
${formatIncomingMessage(messages[0])}
|
package/dist/cli/index.js
CHANGED
|
@@ -295,6 +295,59 @@ function registerServerInfoCommand(parent) {
|
|
|
295
295
|
});
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
// src/chatContext.ts
|
|
299
|
+
import fs2 from "fs";
|
|
300
|
+
import os from "os";
|
|
301
|
+
import path from "path";
|
|
302
|
+
var EMPTY = { target: null, msgId: null };
|
|
303
|
+
function resolveChatContextPath(agentId, env = process.env) {
|
|
304
|
+
const override = env.SLOCK_CHAT_CONTEXT_FILE;
|
|
305
|
+
if (override && override.length > 0) return override;
|
|
306
|
+
return path.join(os.homedir(), ".slock", "agents", agentId, "chat-context.json");
|
|
307
|
+
}
|
|
308
|
+
function readChatContext(agentId, env = process.env) {
|
|
309
|
+
const filePath = resolveChatContextPath(agentId, env);
|
|
310
|
+
let raw;
|
|
311
|
+
try {
|
|
312
|
+
raw = fs2.readFileSync(filePath, "utf-8");
|
|
313
|
+
} catch {
|
|
314
|
+
return EMPTY;
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const parsed = JSON.parse(raw);
|
|
318
|
+
if (!parsed || typeof parsed !== "object") return EMPTY;
|
|
319
|
+
const target = typeof parsed.target === "string" && parsed.target.length > 0 ? parsed.target : null;
|
|
320
|
+
const msgId = typeof parsed.msgId === "string" && parsed.msgId.length > 0 ? parsed.msgId : null;
|
|
321
|
+
return { target, msgId };
|
|
322
|
+
} catch {
|
|
323
|
+
return EMPTY;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function writeChatContext(agentId, ctx, env = process.env) {
|
|
327
|
+
const filePath = resolveChatContextPath(agentId, env);
|
|
328
|
+
const current = readChatContext(agentId, env);
|
|
329
|
+
const next = {
|
|
330
|
+
target: ctx.target !== void 0 ? ctx.target : current.target,
|
|
331
|
+
msgId: ctx.msgId !== void 0 ? ctx.msgId : current.msgId
|
|
332
|
+
};
|
|
333
|
+
const dir = path.dirname(filePath);
|
|
334
|
+
try {
|
|
335
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
336
|
+
} catch {
|
|
337
|
+
}
|
|
338
|
+
const tmp = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
339
|
+
const json = JSON.stringify({ ...next, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
340
|
+
try {
|
|
341
|
+
fs2.writeFileSync(tmp, json, { encoding: "utf-8", mode: 384 });
|
|
342
|
+
fs2.renameSync(tmp, filePath);
|
|
343
|
+
} catch {
|
|
344
|
+
try {
|
|
345
|
+
fs2.unlinkSync(tmp);
|
|
346
|
+
} catch {
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
298
351
|
// src/commands/message/_format.ts
|
|
299
352
|
function toLocalTime(iso) {
|
|
300
353
|
const d = new Date(iso);
|
|
@@ -527,6 +580,10 @@ function registerSendCommand(parent) {
|
|
|
527
580
|
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
528
581
|
}
|
|
529
582
|
const data = res.data;
|
|
583
|
+
writeChatContext(ctx.agentId, {
|
|
584
|
+
target: opts.target,
|
|
585
|
+
msgId: typeof data.messageId === "string" ? data.messageId : null
|
|
586
|
+
});
|
|
530
587
|
const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
|
|
531
588
|
const replyHint = shortId ? ` (to reply in this message's thread, use target "${opts.target.includes(":") ? opts.target : opts.target + ":" + shortId}")` : "";
|
|
532
589
|
let unreadSection = "";
|
|
@@ -549,8 +606,8 @@ async function drainInbox(ctx, opts) {
|
|
|
549
606
|
const query = [];
|
|
550
607
|
if (opts.block) query.push("block=true");
|
|
551
608
|
if (opts.block && opts.timeoutMs !== void 0) query.push(`timeout=${opts.timeoutMs}`);
|
|
552
|
-
const
|
|
553
|
-
const res = await client.request("GET",
|
|
609
|
+
const path2 = query.length > 0 ? `${agentPath}/receive?${query.join("&")}` : `${agentPath}/receive`;
|
|
610
|
+
const res = await client.request("GET", path2);
|
|
554
611
|
if (!res.ok) {
|
|
555
612
|
const code = res.status >= 500 ? "SERVER_5XX" : failCode;
|
|
556
613
|
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
@@ -576,6 +633,13 @@ function registerCheckCommand(parent) {
|
|
|
576
633
|
throw err;
|
|
577
634
|
}
|
|
578
635
|
const result = await drainInbox(ctx, { block: false });
|
|
636
|
+
if (result.messages.length > 0) {
|
|
637
|
+
const latest = result.messages[result.messages.length - 1];
|
|
638
|
+
const target = formatTarget(latest);
|
|
639
|
+
const rawMsgId = latest.message_id;
|
|
640
|
+
const msgId = typeof rawMsgId === "string" ? rawMsgId : null;
|
|
641
|
+
writeChatContext(ctx.agentId, { target, msgId });
|
|
642
|
+
}
|
|
579
643
|
process.stdout.write(formatMessages(result.messages) + "\n");
|
|
580
644
|
});
|
|
581
645
|
}
|
|
@@ -1008,6 +1072,48 @@ function formatReminderCanceled(r) {
|
|
|
1008
1072
|
}
|
|
1009
1073
|
|
|
1010
1074
|
// src/commands/reminder/schedule.ts
|
|
1075
|
+
function buildScheduleBody(opts, cached, now = () => Intl.DateTimeFormat().resolvedOptions().timeZone) {
|
|
1076
|
+
if (!opts.delaySeconds && !opts.fireAt && !opts.repeat) {
|
|
1077
|
+
return {
|
|
1078
|
+
body: {},
|
|
1079
|
+
error: { code: "INVALID_ARG", message: "Provide --delay-seconds, --fire-at, or --repeat" }
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
if (opts.delaySeconds && opts.fireAt) {
|
|
1083
|
+
return {
|
|
1084
|
+
body: {},
|
|
1085
|
+
error: {
|
|
1086
|
+
code: "INVALID_ARG",
|
|
1087
|
+
message: "Pass either --delay-seconds or --fire-at, not both"
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
const body = { title: opts.title, msgId: opts.msgId ?? null };
|
|
1092
|
+
if (opts.delaySeconds !== void 0) {
|
|
1093
|
+
const n = Number(opts.delaySeconds);
|
|
1094
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
|
|
1095
|
+
return {
|
|
1096
|
+
body: {},
|
|
1097
|
+
error: {
|
|
1098
|
+
code: "INVALID_ARG",
|
|
1099
|
+
message: `--delay-seconds must be a positive integer; got ${opts.delaySeconds}`
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
body.delaySeconds = n;
|
|
1104
|
+
}
|
|
1105
|
+
if (opts.fireAt !== void 0) body.fireAt = opts.fireAt;
|
|
1106
|
+
if (opts.repeat !== void 0) {
|
|
1107
|
+
body.repeat = opts.repeat;
|
|
1108
|
+
body.tz = now();
|
|
1109
|
+
}
|
|
1110
|
+
if (opts.channel !== void 0) body.channel = opts.channel;
|
|
1111
|
+
if (opts.channel === void 0 && opts.msgId === void 0) {
|
|
1112
|
+
if (cached.target) body.channel = cached.target;
|
|
1113
|
+
if (cached.msgId) body.msgId = cached.msgId;
|
|
1114
|
+
}
|
|
1115
|
+
return { body };
|
|
1116
|
+
}
|
|
1011
1117
|
function registerReminderScheduleCommand(parent) {
|
|
1012
1118
|
parent.command("schedule").description("Schedule a reminder that fires at a future time").requiredOption("--title <t>", "Short description of what the reminder is about").option(
|
|
1013
1119
|
"--delay-seconds <n>",
|
|
@@ -1020,7 +1126,7 @@ function registerReminderScheduleCommand(parent) {
|
|
|
1020
1126
|
"Recurrence rule: every:15m | every:2h | every:1d | daily@09:00 | weekly:mon,fri@09:00"
|
|
1021
1127
|
).option(
|
|
1022
1128
|
"--channel <ref>",
|
|
1023
|
-
"Optional channel to post a receipt message in (e.g. #general, dm:@alice). Without
|
|
1129
|
+
"Optional channel to post a receipt message in (e.g. #general, dm:@alice). Without --channel or --msg-id, receipt inherits the agent's current chat context (last message received/sent)."
|
|
1024
1130
|
).option("--msg-id <id>", "Optional message id this reminder is anchored to").action(async (opts) => {
|
|
1025
1131
|
let ctx;
|
|
1026
1132
|
try {
|
|
@@ -1029,37 +1135,22 @@ function registerReminderScheduleCommand(parent) {
|
|
|
1029
1135
|
if (err instanceof AgentBootstrapError) fail(err.code, err.message);
|
|
1030
1136
|
throw err;
|
|
1031
1137
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (opts.delaySeconds && opts.fireAt) {
|
|
1036
|
-
fail("INVALID_ARG", "Pass either --delay-seconds or --fire-at, not both");
|
|
1037
|
-
}
|
|
1038
|
-
const body = { title: opts.title, msgId: opts.msgId ?? null };
|
|
1039
|
-
if (opts.delaySeconds !== void 0) {
|
|
1040
|
-
const n = Number(opts.delaySeconds);
|
|
1041
|
-
if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
|
|
1042
|
-
fail("INVALID_ARG", `--delay-seconds must be a positive integer; got ${opts.delaySeconds}`);
|
|
1043
|
-
}
|
|
1044
|
-
body.delaySeconds = n;
|
|
1045
|
-
}
|
|
1046
|
-
if (opts.fireAt !== void 0) body.fireAt = opts.fireAt;
|
|
1047
|
-
if (opts.repeat !== void 0) {
|
|
1048
|
-
body.repeat = opts.repeat;
|
|
1049
|
-
body.tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1050
|
-
}
|
|
1051
|
-
if (opts.channel !== void 0) body.channel = opts.channel;
|
|
1138
|
+
const cached = readChatContext(ctx.agentId);
|
|
1139
|
+
const built = buildScheduleBody(opts, cached);
|
|
1140
|
+
if (built.error) fail(built.error.code, built.error.message);
|
|
1052
1141
|
const client = new ApiClient(ctx);
|
|
1053
1142
|
const res = await client.request(
|
|
1054
1143
|
"POST",
|
|
1055
1144
|
`/internal/agent/${encodeURIComponent(ctx.agentId)}/reminders`,
|
|
1056
|
-
body
|
|
1145
|
+
built.body
|
|
1057
1146
|
);
|
|
1058
1147
|
if (!res.ok || !res.data?.reminder) {
|
|
1059
1148
|
const code = res.status >= 500 ? "SERVER_5XX" : "SCHEDULE_FAILED";
|
|
1060
1149
|
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
1061
1150
|
}
|
|
1062
|
-
process.stdout.write(
|
|
1151
|
+
process.stdout.write(
|
|
1152
|
+
formatReminderScheduled(res.data.reminder, res.data.warning ?? null) + "\n"
|
|
1153
|
+
);
|
|
1063
1154
|
});
|
|
1064
1155
|
}
|
|
1065
1156
|
|
package/dist/core.js
CHANGED
package/dist/index.js
CHANGED