@slock-ai/daemon 0.48.0 → 0.49.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 +3 -1396
- package/dist/{chunk-B7XIMLOT.js → chunk-KNMCE6WB.js} +66 -109
- package/dist/{chunk-EDE2E6QR.js → chunk-M4A5QPUN.js} +639 -274
- package/dist/cli/index.js +287 -53
- package/dist/core.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -947,10 +947,10 @@ function mergeDefs(...defs) {
|
|
|
947
947
|
function cloneDef(schema) {
|
|
948
948
|
return mergeDefs(schema._zod.def);
|
|
949
949
|
}
|
|
950
|
-
function getElementAtPath(obj,
|
|
951
|
-
if (!
|
|
950
|
+
function getElementAtPath(obj, path2) {
|
|
951
|
+
if (!path2)
|
|
952
952
|
return obj;
|
|
953
|
-
return
|
|
953
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
954
954
|
}
|
|
955
955
|
function promiseAllObject(promisesObj) {
|
|
956
956
|
const keys = Object.keys(promisesObj);
|
|
@@ -1333,11 +1333,11 @@ function aborted(x, startIndex = 0) {
|
|
|
1333
1333
|
}
|
|
1334
1334
|
return false;
|
|
1335
1335
|
}
|
|
1336
|
-
function prefixIssues(
|
|
1336
|
+
function prefixIssues(path2, issues) {
|
|
1337
1337
|
return issues.map((iss) => {
|
|
1338
1338
|
var _a2;
|
|
1339
1339
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
1340
|
-
iss.path.unshift(
|
|
1340
|
+
iss.path.unshift(path2);
|
|
1341
1341
|
return iss;
|
|
1342
1342
|
});
|
|
1343
1343
|
}
|
|
@@ -1520,7 +1520,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1520
1520
|
}
|
|
1521
1521
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
1522
1522
|
const result = { errors: [] };
|
|
1523
|
-
const processError = (error49,
|
|
1523
|
+
const processError = (error49, path2 = []) => {
|
|
1524
1524
|
var _a2, _b;
|
|
1525
1525
|
for (const issue2 of error49.issues) {
|
|
1526
1526
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -1530,7 +1530,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1530
1530
|
} else if (issue2.code === "invalid_element") {
|
|
1531
1531
|
processError({ issues: issue2.issues }, issue2.path);
|
|
1532
1532
|
} else {
|
|
1533
|
-
const fullpath = [...
|
|
1533
|
+
const fullpath = [...path2, ...issue2.path];
|
|
1534
1534
|
if (fullpath.length === 0) {
|
|
1535
1535
|
result.errors.push(mapper(issue2));
|
|
1536
1536
|
continue;
|
|
@@ -1562,8 +1562,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
1562
1562
|
}
|
|
1563
1563
|
function toDotPath(_path) {
|
|
1564
1564
|
const segs = [];
|
|
1565
|
-
const
|
|
1566
|
-
for (const seg of
|
|
1565
|
+
const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1566
|
+
for (const seg of path2) {
|
|
1567
1567
|
if (typeof seg === "number")
|
|
1568
1568
|
segs.push(`[${seg}]`);
|
|
1569
1569
|
else if (typeof seg === "symbol")
|
|
@@ -13540,13 +13540,13 @@ function resolveRef(ref, ctx) {
|
|
|
13540
13540
|
if (!ref.startsWith("#")) {
|
|
13541
13541
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
13542
13542
|
}
|
|
13543
|
-
const
|
|
13544
|
-
if (
|
|
13543
|
+
const path2 = ref.slice(1).split("/").filter(Boolean);
|
|
13544
|
+
if (path2.length === 0) {
|
|
13545
13545
|
return ctx.rootSchema;
|
|
13546
13546
|
}
|
|
13547
13547
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
13548
|
-
if (
|
|
13549
|
-
const key =
|
|
13548
|
+
if (path2[0] === defsKey) {
|
|
13549
|
+
const key = path2[1];
|
|
13550
13550
|
if (!key || !ctx.defs[key]) {
|
|
13551
13551
|
throw new Error(`Reference not found: ${ref}`);
|
|
13552
13552
|
}
|
|
@@ -14410,7 +14410,7 @@ function formatServerInfo(data) {
|
|
|
14410
14410
|
const humans = data.humans ?? [];
|
|
14411
14411
|
text += formatRuntimeContext(data.runtimeContext);
|
|
14412
14412
|
text += "### Channels\n";
|
|
14413
|
-
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 `slock message read --channel "#name"` to inspect visible channels. When a channel is not joined, you
|
|
14413
|
+
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 `slock message read --channel "#name"` to inspect visible channels. When a public channel is not joined, you can join it with `slock channel join --target "#name"` before sending messages or receiving ordinary channel delivery. Private channels require a human with access to add you. To leave a channel you have joined, use `slock channel leave --target "#name"`. To stop following a thread, use `slock thread unfollow --target "#name:shortid"`.\n';
|
|
14414
14414
|
if (channels.length > 0) {
|
|
14415
14415
|
for (const t of channels) {
|
|
14416
14416
|
const visibility = t.type === "private" ? "private" : "public";
|
|
@@ -14507,36 +14507,6 @@ function registerChannelMembersCommand(parent) {
|
|
|
14507
14507
|
});
|
|
14508
14508
|
}
|
|
14509
14509
|
|
|
14510
|
-
// src/commands/server/info.ts
|
|
14511
|
-
function registerServerInfoCommand(parent) {
|
|
14512
|
-
parent.command("info").description("List channels, agents, and humans on the current server").action(async () => {
|
|
14513
|
-
let ctx;
|
|
14514
|
-
try {
|
|
14515
|
-
ctx = loadAgentContext();
|
|
14516
|
-
} catch (err) {
|
|
14517
|
-
if (err instanceof AgentBootstrapError) fail(err.code, err.message);
|
|
14518
|
-
throw err;
|
|
14519
|
-
}
|
|
14520
|
-
const client = new ApiClient(ctx);
|
|
14521
|
-
const res = await client.request(
|
|
14522
|
-
"GET",
|
|
14523
|
-
`/internal/agent/${encodeURIComponent(ctx.agentId)}/server`
|
|
14524
|
-
);
|
|
14525
|
-
if (!res.ok) {
|
|
14526
|
-
const code = res.status >= 500 ? "SERVER_5XX" : "INFO_FAILED";
|
|
14527
|
-
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
14528
|
-
}
|
|
14529
|
-
const data = res.data;
|
|
14530
|
-
if (data?.runtimeContext) {
|
|
14531
|
-
data.runtimeContext = {
|
|
14532
|
-
...data.runtimeContext,
|
|
14533
|
-
workspacePath: data.runtimeContext.workspacePath ?? process.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
|
|
14534
|
-
};
|
|
14535
|
-
}
|
|
14536
|
-
process.stdout.write(formatServerInfo(data));
|
|
14537
|
-
});
|
|
14538
|
-
}
|
|
14539
|
-
|
|
14540
14510
|
// src/commands/channel/leave.ts
|
|
14541
14511
|
function parseRegularChannelTarget(target) {
|
|
14542
14512
|
if (!target.startsWith("#")) return null;
|
|
@@ -14545,7 +14515,7 @@ function parseRegularChannelTarget(target) {
|
|
|
14545
14515
|
return name.length > 0 ? name : null;
|
|
14546
14516
|
}
|
|
14547
14517
|
function formatLeaveChannelResult(target) {
|
|
14548
|
-
return `Left ${target}. You can still inspect visible public channel history there, but you can no longer send or receive ordinary channel delivery until a human adds you
|
|
14518
|
+
return `Left ${target}. You can still inspect visible public channel history there, but you can no longer send or receive ordinary channel delivery until you join the public channel again or a human re-adds you to a private channel.`;
|
|
14549
14519
|
}
|
|
14550
14520
|
function formatAlreadyNotJoined(target) {
|
|
14551
14521
|
return `Already not joined in ${target}.`;
|
|
@@ -14592,6 +14562,85 @@ function registerChannelLeaveCommand(parent) {
|
|
|
14592
14562
|
});
|
|
14593
14563
|
}
|
|
14594
14564
|
|
|
14565
|
+
// src/commands/channel/join.ts
|
|
14566
|
+
function formatJoinChannelResult(target) {
|
|
14567
|
+
return `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`;
|
|
14568
|
+
}
|
|
14569
|
+
function formatAlreadyJoined(target) {
|
|
14570
|
+
return `Already joined ${target}.`;
|
|
14571
|
+
}
|
|
14572
|
+
function registerChannelJoinCommand(parent) {
|
|
14573
|
+
parent.command("join").description("Join a visible public channel").requiredOption("--target <target>", "Regular channel to join, e.g. '#engineering'").action(async (opts) => {
|
|
14574
|
+
const channelName = parseRegularChannelTarget(opts.target);
|
|
14575
|
+
if (!channelName) {
|
|
14576
|
+
fail("INVALID_TARGET", "Target must be a regular channel in the form '#channel-name'. DMs and thread targets are not supported.");
|
|
14577
|
+
}
|
|
14578
|
+
let ctx;
|
|
14579
|
+
try {
|
|
14580
|
+
ctx = loadAgentContext();
|
|
14581
|
+
} catch (err) {
|
|
14582
|
+
if (err instanceof AgentBootstrapError) fail(err.code, err.message);
|
|
14583
|
+
throw err;
|
|
14584
|
+
}
|
|
14585
|
+
const client = new ApiClient(ctx);
|
|
14586
|
+
const infoRes = await client.request(
|
|
14587
|
+
"GET",
|
|
14588
|
+
`/internal/agent/${encodeURIComponent(ctx.agentId)}/server`
|
|
14589
|
+
);
|
|
14590
|
+
if (!infoRes.ok) {
|
|
14591
|
+
const code = infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED";
|
|
14592
|
+
fail(code, infoRes.error ?? `HTTP ${infoRes.status}`);
|
|
14593
|
+
}
|
|
14594
|
+
const channel = (infoRes.data?.channels ?? []).find((candidate) => candidate.name === channelName);
|
|
14595
|
+
if (!channel) {
|
|
14596
|
+
fail("NOT_FOUND", `Channel not found: ${opts.target}`);
|
|
14597
|
+
}
|
|
14598
|
+
if (channel.joined) {
|
|
14599
|
+
process.stdout.write(formatAlreadyJoined(opts.target) + "\n");
|
|
14600
|
+
return;
|
|
14601
|
+
}
|
|
14602
|
+
const joinRes = await client.request(
|
|
14603
|
+
"POST",
|
|
14604
|
+
`/internal/agent/${encodeURIComponent(ctx.agentId)}/channels/${encodeURIComponent(channel.id)}/join`
|
|
14605
|
+
);
|
|
14606
|
+
if (!joinRes.ok) {
|
|
14607
|
+
const code = joinRes.status >= 500 ? "SERVER_5XX" : "JOIN_FAILED";
|
|
14608
|
+
fail(code, joinRes.error ?? `HTTP ${joinRes.status}`);
|
|
14609
|
+
}
|
|
14610
|
+
process.stdout.write(formatJoinChannelResult(opts.target) + "\n");
|
|
14611
|
+
});
|
|
14612
|
+
}
|
|
14613
|
+
|
|
14614
|
+
// src/commands/server/info.ts
|
|
14615
|
+
function registerServerInfoCommand(parent) {
|
|
14616
|
+
parent.command("info").description("List channels, agents, and humans on the current server").action(async () => {
|
|
14617
|
+
let ctx;
|
|
14618
|
+
try {
|
|
14619
|
+
ctx = loadAgentContext();
|
|
14620
|
+
} catch (err) {
|
|
14621
|
+
if (err instanceof AgentBootstrapError) fail(err.code, err.message);
|
|
14622
|
+
throw err;
|
|
14623
|
+
}
|
|
14624
|
+
const client = new ApiClient(ctx);
|
|
14625
|
+
const res = await client.request(
|
|
14626
|
+
"GET",
|
|
14627
|
+
`/internal/agent/${encodeURIComponent(ctx.agentId)}/server`
|
|
14628
|
+
);
|
|
14629
|
+
if (!res.ok) {
|
|
14630
|
+
const code = res.status >= 500 ? "SERVER_5XX" : "INFO_FAILED";
|
|
14631
|
+
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
14632
|
+
}
|
|
14633
|
+
const data = res.data;
|
|
14634
|
+
if (data?.runtimeContext) {
|
|
14635
|
+
data.runtimeContext = {
|
|
14636
|
+
...data.runtimeContext,
|
|
14637
|
+
workspacePath: data.runtimeContext.workspacePath ?? process.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
|
|
14638
|
+
};
|
|
14639
|
+
}
|
|
14640
|
+
process.stdout.write(formatServerInfo(data));
|
|
14641
|
+
});
|
|
14642
|
+
}
|
|
14643
|
+
|
|
14595
14644
|
// src/commands/thread/unfollow.ts
|
|
14596
14645
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14597
14646
|
var SHORT_ID_RE = /^[0-9a-f]{8}$/i;
|
|
@@ -14644,6 +14693,69 @@ function registerThreadUnfollowCommand(parent) {
|
|
|
14644
14693
|
});
|
|
14645
14694
|
}
|
|
14646
14695
|
|
|
14696
|
+
// src/commands/message/_continueDraftState.ts
|
|
14697
|
+
import fs2 from "fs";
|
|
14698
|
+
import os from "os";
|
|
14699
|
+
import path from "path";
|
|
14700
|
+
var DEFAULT_LOCAL_DRAFT_TTL_MS = 10 * 60 * 1e3;
|
|
14701
|
+
function stateFilePath(agentId) {
|
|
14702
|
+
return path.join(process.env.SLOCK_CLI_DRAFT_STATE_DIR ?? os.tmpdir(), "slock-cli-attested-send", agentId, "continue-state.json");
|
|
14703
|
+
}
|
|
14704
|
+
function readState(agentId) {
|
|
14705
|
+
const filePath = stateFilePath(agentId);
|
|
14706
|
+
try {
|
|
14707
|
+
const raw = fs2.readFileSync(filePath, "utf8");
|
|
14708
|
+
const parsed = JSON.parse(raw);
|
|
14709
|
+
return typeof parsed === "object" && parsed ? parsed : {};
|
|
14710
|
+
} catch {
|
|
14711
|
+
return {};
|
|
14712
|
+
}
|
|
14713
|
+
}
|
|
14714
|
+
function writeState(agentId, state) {
|
|
14715
|
+
const filePath = stateFilePath(agentId);
|
|
14716
|
+
fs2.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
14717
|
+
fs2.writeFileSync(filePath, JSON.stringify(state), "utf8");
|
|
14718
|
+
}
|
|
14719
|
+
function getSavedDraft(agentId, target) {
|
|
14720
|
+
const state = readState(agentId);
|
|
14721
|
+
const draft = state.targets?.[target];
|
|
14722
|
+
if (!draft || typeof draft === "string") return null;
|
|
14723
|
+
if (typeof draft.content !== "string") return null;
|
|
14724
|
+
const attachmentIds = Array.isArray(draft.attachmentIds) ? draft.attachmentIds.filter((item) => typeof item === "string") : [];
|
|
14725
|
+
const savedAt = Number.isFinite(draft.savedAt) ? draft.savedAt : Date.now();
|
|
14726
|
+
const reholdCount = Number.isFinite(draft.reholdCount) ? draft.reholdCount : 0;
|
|
14727
|
+
const seenUpToSeq = Number.isFinite(draft.seenUpToSeq) ? draft.seenUpToSeq : void 0;
|
|
14728
|
+
if (Date.now() - savedAt > DEFAULT_LOCAL_DRAFT_TTL_MS) {
|
|
14729
|
+
clearSavedDraft(agentId, target);
|
|
14730
|
+
return null;
|
|
14731
|
+
}
|
|
14732
|
+
return {
|
|
14733
|
+
content: draft.content,
|
|
14734
|
+
attachmentIds,
|
|
14735
|
+
savedAt,
|
|
14736
|
+
reholdCount,
|
|
14737
|
+
seenUpToSeq
|
|
14738
|
+
};
|
|
14739
|
+
}
|
|
14740
|
+
function setSavedDraft(agentId, target, draft) {
|
|
14741
|
+
const state = readState(agentId);
|
|
14742
|
+
const targets = state.targets ?? {};
|
|
14743
|
+
targets[target] = {
|
|
14744
|
+
content: draft.content,
|
|
14745
|
+
attachmentIds: draft.attachmentIds,
|
|
14746
|
+
savedAt: draft.savedAt,
|
|
14747
|
+
reholdCount: draft.reholdCount,
|
|
14748
|
+
...draft.seenUpToSeq !== void 0 ? { seenUpToSeq: draft.seenUpToSeq } : {}
|
|
14749
|
+
};
|
|
14750
|
+
writeState(agentId, { targets });
|
|
14751
|
+
}
|
|
14752
|
+
function clearSavedDraft(agentId, target) {
|
|
14753
|
+
const state = readState(agentId);
|
|
14754
|
+
if (!state.targets || !(target in state.targets)) return;
|
|
14755
|
+
delete state.targets[target];
|
|
14756
|
+
writeState(agentId, state);
|
|
14757
|
+
}
|
|
14758
|
+
|
|
14647
14759
|
// src/commands/message/_format.ts
|
|
14648
14760
|
function toLocalTime(iso) {
|
|
14649
14761
|
const d = new Date(iso);
|
|
@@ -14811,6 +14923,13 @@ async function resolveSendContent(input = process.stdin) {
|
|
|
14811
14923
|
}
|
|
14812
14924
|
return content;
|
|
14813
14925
|
}
|
|
14926
|
+
async function resolveOptionalSendContent(input = process.stdin) {
|
|
14927
|
+
if (input.isTTY) {
|
|
14928
|
+
return void 0;
|
|
14929
|
+
}
|
|
14930
|
+
const content = await readStream2(input);
|
|
14931
|
+
return content.trim().length > 0 ? content : void 0;
|
|
14932
|
+
}
|
|
14814
14933
|
function rejectArgContent(positionalContent, opts) {
|
|
14815
14934
|
if (positionalContent.length > 0) {
|
|
14816
14935
|
throw new SendContentError(
|
|
@@ -14835,8 +14954,35 @@ function rejectArgContent(positionalContent, opts) {
|
|
|
14835
14954
|
);
|
|
14836
14955
|
}
|
|
14837
14956
|
}
|
|
14957
|
+
function validateDraftSendFlags(opts) {
|
|
14958
|
+
if (opts.anyway && !opts.sendDraft) {
|
|
14959
|
+
throw new SendContentError(
|
|
14960
|
+
"SEND_DRAFT_ANYWAY_REQUIRES_SEND_DRAFT",
|
|
14961
|
+
"--anyway can only be used together with --send-draft."
|
|
14962
|
+
);
|
|
14963
|
+
}
|
|
14964
|
+
if (opts.sendDraft && opts.attachmentId && opts.attachmentId.length > 0) {
|
|
14965
|
+
throw new SendContentError(
|
|
14966
|
+
"SEND_DRAFT_ATTACHMENTS_UNSUPPORTED",
|
|
14967
|
+
"--attachment-id cannot be used with --send-draft. Use a normal send to replace the draft."
|
|
14968
|
+
);
|
|
14969
|
+
}
|
|
14970
|
+
}
|
|
14971
|
+
function rejectSendDraftStdin(content, target) {
|
|
14972
|
+
if (content === void 0) return;
|
|
14973
|
+
throw new SendContentError(
|
|
14974
|
+
"SEND_DRAFT_STDIN_UNSUPPORTED",
|
|
14975
|
+
[
|
|
14976
|
+
"--send-draft sends the current saved draft and does not accept stdin.",
|
|
14977
|
+
"To update the draft, send the revised content normally without --send-draft:",
|
|
14978
|
+
` slock message send --target "${target}" <<'EOF'`,
|
|
14979
|
+
" revised message",
|
|
14980
|
+
" EOF"
|
|
14981
|
+
].join("\n")
|
|
14982
|
+
);
|
|
14983
|
+
}
|
|
14838
14984
|
function registerSendCommand(parent) {
|
|
14839
|
-
parent.command("send").description("Send a message to a channel, DM, or thread").argument("[content...]", "Unsupported positional message content. Pipe content to stdin instead.").requiredOption("--target <target>", "Target: '#channel', 'dm:@peer', '#channel:threadId', 'dm:@peer:threadId'").option("--content <content>", "Unsupported. Pipe message content to stdin instead.").option(
|
|
14985
|
+
parent.command("send").description("Send a message to a channel, DM, or thread").argument("[content...]", "Unsupported positional message content. Pipe content to stdin instead.").requiredOption("--target <target>", "Target: '#channel', 'dm:@peer', '#channel:threadId', 'dm:@peer:threadId'").option("--send-draft", "Send the current saved draft after reviewing newer messages").option("--anyway", "Escape hatch: send a saved draft even if freshness re-check is still stale").option("--content <content>", "Unsupported. Pipe message content to stdin instead.").option(
|
|
14840
14986
|
"--attachment-id <id>",
|
|
14841
14987
|
"Attachment id to link (repeatable). Get one from `slock attachment upload`.",
|
|
14842
14988
|
(value, prev = []) => prev.concat(value)
|
|
@@ -14855,16 +15001,72 @@ function registerSendCommand(parent) {
|
|
|
14855
15001
|
throw err;
|
|
14856
15002
|
}
|
|
14857
15003
|
const client = new ApiClient(ctx);
|
|
14858
|
-
let content;
|
|
14859
15004
|
try {
|
|
14860
|
-
|
|
15005
|
+
validateDraftSendFlags(opts);
|
|
14861
15006
|
} catch (err) {
|
|
14862
15007
|
if (err instanceof SendContentError) fail(err.code, err.message);
|
|
14863
15008
|
throw err;
|
|
14864
15009
|
}
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
15010
|
+
let content;
|
|
15011
|
+
let outgoingContent;
|
|
15012
|
+
let outgoingAttachmentIds = [];
|
|
15013
|
+
let previousDraftReholdCount = 0;
|
|
15014
|
+
let seenUpToSeq;
|
|
15015
|
+
if (opts.sendDraft) {
|
|
15016
|
+
content = await resolveOptionalSendContent();
|
|
15017
|
+
try {
|
|
15018
|
+
rejectSendDraftStdin(content, opts.target);
|
|
15019
|
+
} catch (err) {
|
|
15020
|
+
if (err instanceof SendContentError) fail(err.code, err.message);
|
|
15021
|
+
throw err;
|
|
15022
|
+
}
|
|
15023
|
+
const savedDraft = getSavedDraft(ctx.agentId, opts.target);
|
|
15024
|
+
if (!savedDraft) {
|
|
15025
|
+
fail(
|
|
15026
|
+
"SEND_DRAFT_NOT_FOUND",
|
|
15027
|
+
[
|
|
15028
|
+
"No saved draft exists for this target.",
|
|
15029
|
+
"To create or update a draft, send message content normally:",
|
|
15030
|
+
` slock message send --target "${opts.target}" <<'EOF'`,
|
|
15031
|
+
" message body",
|
|
15032
|
+
" EOF"
|
|
15033
|
+
].join("\n")
|
|
15034
|
+
);
|
|
15035
|
+
return;
|
|
15036
|
+
}
|
|
15037
|
+
outgoingContent = savedDraft.content;
|
|
15038
|
+
outgoingAttachmentIds = savedDraft.attachmentIds;
|
|
15039
|
+
previousDraftReholdCount = savedDraft.reholdCount;
|
|
15040
|
+
seenUpToSeq = savedDraft.seenUpToSeq;
|
|
15041
|
+
} else {
|
|
15042
|
+
try {
|
|
15043
|
+
content = await resolveSendContent();
|
|
15044
|
+
} catch (err) {
|
|
15045
|
+
if (err instanceof SendContentError) fail(err.code, err.message);
|
|
15046
|
+
throw err;
|
|
15047
|
+
}
|
|
15048
|
+
outgoingContent = content;
|
|
15049
|
+
outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
|
|
15050
|
+
const previousDraft = getSavedDraft(ctx.agentId, opts.target);
|
|
15051
|
+
previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
|
|
15052
|
+
seenUpToSeq = previousDraft?.seenUpToSeq;
|
|
15053
|
+
}
|
|
15054
|
+
const body = {
|
|
15055
|
+
target: opts.target,
|
|
15056
|
+
content: outgoingContent,
|
|
15057
|
+
draftReholdCount: previousDraftReholdCount
|
|
15058
|
+
};
|
|
15059
|
+
if (seenUpToSeq !== void 0) {
|
|
15060
|
+
body.seenUpToSeq = seenUpToSeq;
|
|
15061
|
+
}
|
|
15062
|
+
if (opts.sendDraft) {
|
|
15063
|
+
body.sendDraft = true;
|
|
15064
|
+
if (opts.anyway) body.continueAnyway = true;
|
|
15065
|
+
} else {
|
|
15066
|
+
body.draftReplacedExisting = previousDraftReholdCount > 0;
|
|
15067
|
+
}
|
|
15068
|
+
if (outgoingAttachmentIds.length > 0) {
|
|
15069
|
+
body.attachmentIds = outgoingAttachmentIds;
|
|
14868
15070
|
}
|
|
14869
15071
|
const res = await client.request(
|
|
14870
15072
|
"POST",
|
|
@@ -14876,6 +15078,37 @@ function registerSendCommand(parent) {
|
|
|
14876
15078
|
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
14877
15079
|
}
|
|
14878
15080
|
const data = res.data;
|
|
15081
|
+
if (data.state === "held") {
|
|
15082
|
+
setSavedDraft(ctx.agentId, opts.target, {
|
|
15083
|
+
content: outgoingContent,
|
|
15084
|
+
attachmentIds: outgoingAttachmentIds,
|
|
15085
|
+
savedAt: Date.now(),
|
|
15086
|
+
reholdCount: previousDraftReholdCount + 1,
|
|
15087
|
+
seenUpToSeq: data.seenUpToSeq
|
|
15088
|
+
});
|
|
15089
|
+
const heldHistory = data.heldMessages && data.heldMessages.length > 0 ? `
|
|
15090
|
+
|
|
15091
|
+
${formatHistory(opts.target, { messages: data.heldMessages })}` : "";
|
|
15092
|
+
const mentionNote = (data.mentionAnnotation?.formalMentionCount ?? 0) > 0 ? `
|
|
15093
|
+
|
|
15094
|
+
Note: ${data.mentionAnnotation.formalMentionCount} of these messages formally @mention you.` : "";
|
|
15095
|
+
process.stdout.write(
|
|
15096
|
+
`Not sent yet \u2014 ${data.newMessageCount ?? 0} newer message(s) arrived.
|
|
15097
|
+
Your message has been saved as a draft. Read the new messages below, then choose one path.${mentionNote}${heldHistory}
|
|
15098
|
+
|
|
15099
|
+
To update the draft, send revised content normally:
|
|
15100
|
+
slock message send --target "${opts.target}" <<'EOF'
|
|
15101
|
+
revised message
|
|
15102
|
+
EOF
|
|
15103
|
+
To send the current draft unchanged:
|
|
15104
|
+
slock message send --send-draft --target "${opts.target}"
|
|
15105
|
+
` + (data.continueAnywaySuggested ? `If repeated updates keep blocking the same draft and this is still the right reply, you may use:
|
|
15106
|
+
slock message send --send-draft --anyway --target "${opts.target}"
|
|
15107
|
+
` : "")
|
|
15108
|
+
);
|
|
15109
|
+
return;
|
|
15110
|
+
}
|
|
15111
|
+
clearSavedDraft(ctx.agentId, opts.target);
|
|
14879
15112
|
const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
|
|
14880
15113
|
const replyHint = shortId ? ` (to reply in this message's thread, use target "${opts.target.includes(":") ? opts.target : opts.target + ":" + shortId}")` : "";
|
|
14881
15114
|
let unreadSection = "";
|
|
@@ -14898,8 +15131,8 @@ async function drainInbox(ctx, opts) {
|
|
|
14898
15131
|
const query = [];
|
|
14899
15132
|
if (opts.block) query.push("block=true");
|
|
14900
15133
|
if (opts.block && opts.timeoutMs !== void 0) query.push(`timeout=${opts.timeoutMs}`);
|
|
14901
|
-
const
|
|
14902
|
-
const res = await client.request("GET",
|
|
15134
|
+
const path2 = query.length > 0 ? `${agentPath}/receive?${query.join("&")}` : `${agentPath}/receive`;
|
|
15135
|
+
const res = await client.request("GET", path2);
|
|
14903
15136
|
if (!res.ok) {
|
|
14904
15137
|
const code = res.status >= 500 ? "SERVER_5XX" : failCode;
|
|
14905
15138
|
fail(code, res.error ?? `HTTP ${res.status}`);
|
|
@@ -16097,6 +16330,7 @@ var authCmd = program.command("auth").description("Auth introspection");
|
|
|
16097
16330
|
registerWhoamiCommand(authCmd);
|
|
16098
16331
|
var channelCmd = program.command("channel").description("Channel membership operations");
|
|
16099
16332
|
registerChannelMembersCommand(channelCmd);
|
|
16333
|
+
registerChannelJoinCommand(channelCmd);
|
|
16100
16334
|
registerChannelLeaveCommand(channelCmd);
|
|
16101
16335
|
var threadCmd = program.command("thread").description("Thread attention operations");
|
|
16102
16336
|
registerThreadUnfollowCommand(threadCmd);
|
package/dist/core.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
resolveSlockCliPath,
|
|
10
10
|
resolveWorkspaceDirectoryPath,
|
|
11
11
|
scanWorkspaceDirectories
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-M4A5QPUN.js";
|
|
13
13
|
import {
|
|
14
14
|
subscribeDaemonLogs
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-KNMCE6WB.js";
|
|
16
16
|
export {
|
|
17
17
|
DAEMON_CLI_USAGE,
|
|
18
18
|
DaemonCore,
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
DAEMON_CLI_USAGE,
|
|
4
4
|
DaemonCore,
|
|
5
5
|
parseDaemonCliArgs
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-M4A5QPUN.js";
|
|
7
|
+
import "./chunk-KNMCE6WB.js";
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
10
|
var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
|